<commit_before>use game_map::{RoomId, GameMap};
use combat::CombatState;
use platform;

const PAUSE_MS: u64 = 2500;
const CHEATING_FOOD_DIVISOR: i32 = 4;
const INITIAL_STRENGTH: i32 = 100;
const INITIAL_WEALTH: i32 = 75;
const STRENGTH_PER_FOOD: i32 = 5;
const TALLY_PER_MOVE: i32 = 1;
const STRENGTH_LOSS_PER_MOVE: i32 = 5;

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum GameMode {
  AskName,
  Primary,
  Inventory,
  EatFood,
  Combat(CombatState),
  Finished,

  #[cfg(debug_assertions)]
  Debug,
}

// We have our input callbacks have a GameState explicitly passed
// into them instead of expecting 'self' to be captured into their
// closure, because the latter leads to all kinds of lifetime
// headaches.
//
// Note also that this doesn't need to be a FnOnce, since it can
// request that it be called again, e.g. if the user input was invalid.
type InputCallback = Fn(&mut GameState, String);

pub struct GameState {
  pub map: GameMap,
  pub curr_mode: GameMode,
  pub shown_hint: bool,
  pub player_name: String,
  pub strength: i32,
  pub wealth: i32,
  pub food: i32,
  pub tally: i32,
  pub monsters_killed: i32,
  pub sword: bool,
  pub amulet: bool,
  pub axe: bool,
  pub suit: bool,
  pub light: bool,
  pub curr_room: RoomId,
  pub show_desc: bool,
  input_callback: Option<Box<InputCallback>>,
  last_input_prompt: String,
  read_input_again: bool,
}

impl GameState {
  pub fn new() -> Self {
    Self {
      map: GameMap::new(),
      player_name: String::from(""),
      curr_mode: GameMode::AskName,
      curr_room: RoomId::Entrance,
      shown_hint: false,
      strength: INITIAL_STRENGTH,
      wealth: INITIAL_WEALTH,
      food: 0,
      tally: 0,
      monsters_killed: 0,
      sword: false,
      amulet: false,
      axe: false,
      suit: false,
      light: false,
      show_desc: true,
      input_callback: None,
      last_input_prompt: String::from(""),
      read_input_again: false,
    }
  }

  pub fn show_prompt(&mut self, prompt: &str) {
    self.last_input_prompt = String::from(prompt);
    platform::show_prompt(prompt);
  }

  pub fn ask_again(&mut self) {
    self.read_input_again = true;
  }

  pub fn ask_i32<F>(&mut self, question: &str, cb: F)
      where F: 'static + Fn(&mut GameState, i32) {
    self.show_prompt(question);
    self.read_input(move |state, input| {
      match input.parse::<i32>() {
        Ok(amount) => {
          cb(state, amount);
        },
        Err(_) => {
          println!("That does not even look like a number, {}.",
                   state.player_name);
          state.ask_again();
        }
      }
    });
  }

  pub fn ask<F>(&mut self, question: &str, cb: F)
      where F: 'static + Fn(&mut GameState, String) {
    self.show_prompt(question);
    self.read_input(cb);
  }

  pub fn read_input<F>(&mut self, cb: F)
      where F: 'static + Fn(&mut GameState, String) {
    assert!(self.input_callback.is_none(),
            "Program must not already be waiting for input");
    self.read_input_again = false;
    self.input_callback = Some(Box::new(cb));
  }

  pub fn can_player_see(&self) -> bool {
    self.curr_room == RoomId::Entrance || self.light
  }

  pub fn set_mode(&mut self, mode: GameMode) {
    self.show_desc = true;
    self.curr_mode = mode;
  }

  pub fn print_wealth(&self) {
    print!("You have ");
    if self.wealth > 0 {
      println!("${}.", self.wealth);
    } else {
      println!("no money.");
    }
  }

  pub fn print_food(&self) {
    println!("Your provisions sack holds {} unit{} of food.",
             self.food, if self.food == 1 { "" } else { "s" });
  }

  fn get_score(&self) -> i32 {
    3  * self.tally +
    5  * self.strength +
    2  * self.wealth +
    1  * self.food +
    30 * self.monsters_killed
  }

  pub fn finish_game(&mut self) {
    self.curr_mode = GameMode::Finished;
    println!("Your score is {}.\n", self.get_score());
    println!("Farewell.");
  }

  pub fn is_finished(&self) -> bool {
    self.curr_mode == GameMode::Finished
  }

  pub fn accuse_player_of_cheating(&mut self) {
    println!("YOU HAVE TRIED TO CHEAT ME!");
    self.wealth = 0;
    self.light = false;
    self.axe = false;
    self.sword = false;
    self.food = self.food / CHEATING_FOOD_DIVISOR;
    self.amulet = false;
    self.suit = false;
    Self::pause();
  }

  pub fn pause() {
    platform::sleep(PAUSE_MS);
  }

  fn die(&mut self) {
    println!("You have died.........");
    Self::pause();
    self.finish_game();
  }

  fn tick_ask_name_mode(&mut self) {
    self.ask("What is your name, explorer? ", |state, input| {
      if input.len() == 0 {
        println!("Pardon me?");
      } else {
        state.player_name = input;
        state.set_mode(GameMode::Primary);
      }
    });
  }

  fn tick_eat_food_mode(&mut self) {
    if self.show_desc {
      self.print_food();
      println!("");
      self.show_desc = false;
    }

    self.ask_i32("How many do you want to eat? ", |state, amount| {
      if amount < 0 {
        println!("GIVE ME A POSITIVE INTEGER.");
        state.ask_again();
      } else if amount == 0 {
        println!("Fine, be that way.");
        Self::pause();
        state.set_mode(GameMode::Primary);
      } else if amount > state.food {
        state.accuse_player_of_cheating();
        state.set_mode(GameMode::Primary);
      } else {
        println!("After some munching, you feel stronger.");
        state.food -= amount;
        state.strength += amount * STRENGTH_PER_FOOD;
        state.set_mode(GameMode::Primary);
        Self::pause();
      }
    });
  }

  pub fn process_move(&mut self) {
    self.tally += TALLY_PER_MOVE;
    self.strength -= STRENGTH_LOSS_PER_MOVE;
  }

  pub fn tick(&mut self) {
    let mut input_processed = false;
    let mut input_cb: Option<Box<InputCallback>> = None;

    ::std::mem::swap(&mut input_cb, &mut self.input_callback);

    if let Some(ref cb) = input_cb {
      match platform::read_input() {
        Some(input) => {
          platform::hide_prompt();
          cb(self, input);
          // Note that at this point, self.input_callback may be
          // set again, if the callback asked for input again.
        },
        None => {
          // We're probably running in the browser and there's currently
          // no input to process.
        }
      }
      input_processed = true;
    }

    if input_processed {
      if self.read_input_again {
        assert!(self.input_callback.is_none(),
                "Program cannot ask to re-run last input callback \
                 *and* run a new input callback simultaneously");
        self.read_input_again = false;
        self.input_callback = input_cb;
        platform::show_prompt(self.last_input_prompt.as_str());
      }

      return;
    }

    if self.strength < 1 { self.die() }

    match self.curr_mode {
      GameMode::AskName => { self.tick_ask_name_mode() },
      GameMode::Primary => { self.tick_primary_mode() },
      GameMode::Inventory => { self.tick_inventory_mode() },
      GameMode::EatFood => { self.tick_eat_food_mode() },
      GameMode::Combat(state) => { self.tick_combat_mode(&state) },
      GameMode::Finished => {},

      #[cfg(debug_assertions)]
      GameMode::Debug => { self.tick_debug_mode() },
    }
  }
}
<commit_msg>Panic if ask_again() called outside an input callback.<commit_after>use game_map::{RoomId, GameMap};
use combat::CombatState;
use platform;

const PAUSE_MS: u64 = 2500;
const CHEATING_FOOD_DIVISOR: i32 = 4;
const INITIAL_STRENGTH: i32 = 100;
const INITIAL_WEALTH: i32 = 75;
const STRENGTH_PER_FOOD: i32 = 5;
const TALLY_PER_MOVE: i32 = 1;
const STRENGTH_LOSS_PER_MOVE: i32 = 5;

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum GameMode {
  AskName,
  Primary,
  Inventory,
  EatFood,
  Combat(CombatState),
  Finished,

  #[cfg(debug_assertions)]
  Debug,
}

// We have our input callbacks have a GameState explicitly passed
// into them instead of expecting 'self' to be captured into their
// closure, because the latter leads to all kinds of lifetime
// headaches.
//
// Note also that this doesn't need to be a FnOnce, since it can
// request that it be called again, e.g. if the user input was invalid.
type InputCallback = Fn(&mut GameState, String);

pub struct GameState {
  pub map: GameMap,
  pub curr_mode: GameMode,
  pub shown_hint: bool,
  pub player_name: String,
  pub strength: i32,
  pub wealth: i32,
  pub food: i32,
  pub tally: i32,
  pub monsters_killed: i32,
  pub sword: bool,
  pub amulet: bool,
  pub axe: bool,
  pub suit: bool,
  pub light: bool,
  pub curr_room: RoomId,
  pub show_desc: bool,
  input_callback: Option<Box<InputCallback>>,
  is_processing_input: bool,
  last_input_prompt: String,
  read_input_again: bool,
}

impl GameState {
  pub fn new() -> Self {
    Self {
      map: GameMap::new(),
      player_name: String::from(""),
      curr_mode: GameMode::AskName,
      curr_room: RoomId::Entrance,
      shown_hint: false,
      strength: INITIAL_STRENGTH,
      wealth: INITIAL_WEALTH,
      food: 0,
      tally: 0,
      monsters_killed: 0,
      sword: false,
      amulet: false,
      axe: false,
      suit: false,
      light: false,
      show_desc: true,
      input_callback: None,
      is_processing_input: false,
      last_input_prompt: String::from(""),
      read_input_again: false,
    }
  }

  pub fn show_prompt(&mut self, prompt: &str) {
    self.last_input_prompt = String::from(prompt);
    platform::show_prompt(prompt);
  }

  pub fn ask_again(&mut self) {
    assert_eq!(self.is_processing_input, true,
               "This method must be called from an input callback");
    self.read_input_again = true;
  }

  pub fn ask_i32<F>(&mut self, question: &str, cb: F)
      where F: 'static + Fn(&mut GameState, i32) {
    self.show_prompt(question);
    self.read_input(move |state, input| {
      match input.parse::<i32>() {
        Ok(amount) => {
          cb(state, amount);
        },
        Err(_) => {
          println!("That does not even look like a number, {}.",
                   state.player_name);
          state.ask_again();
        }
      }
    });
  }

  pub fn ask<F>(&mut self, question: &str, cb: F)
      where F: 'static + Fn(&mut GameState, String) {
    self.show_prompt(question);
    self.read_input(cb);
  }

  pub fn read_input<F>(&mut self, cb: F)
      where F: 'static + Fn(&mut GameState, String) {
    assert!(self.input_callback.is_none(),
            "Program must not already be waiting for input");
    self.read_input_again = false;
    self.input_callback = Some(Box::new(cb));
  }

  pub fn can_player_see(&self) -> bool {
    self.curr_room == RoomId::Entrance || self.light
  }

  pub fn set_mode(&mut self, mode: GameMode) {
    self.show_desc = true;
    self.curr_mode = mode;
  }

  pub fn print_wealth(&self) {
    print!("You have ");
    if self.wealth > 0 {
      println!("${}.", self.wealth);
    } else {
      println!("no money.");
    }
  }

  pub fn print_food(&self) {
    println!("Your provisions sack holds {} unit{} of food.",
             self.food, if self.food == 1 { "" } else { "s" });
  }

  fn get_score(&self) -> i32 {
    3  * self.tally +
    5  * self.strength +
    2  * self.wealth +
    1  * self.food +
    30 * self.monsters_killed
  }

  pub fn finish_game(&mut self) {
    self.curr_mode = GameMode::Finished;
    println!("Your score is {}.\n", self.get_score());
    println!("Farewell.");
  }

  pub fn is_finished(&self) -> bool {
    self.curr_mode == GameMode::Finished
  }

  pub fn accuse_player_of_cheating(&mut self) {
    println!("YOU HAVE TRIED TO CHEAT ME!");
    self.wealth = 0;
    self.light = false;
    self.axe = false;
    self.sword = false;
    self.food = self.food / CHEATING_FOOD_DIVISOR;
    self.amulet = false;
    self.suit = false;
    Self::pause();
  }

  pub fn pause() {
    platform::sleep(PAUSE_MS);
  }

  fn die(&mut self) {
    println!("You have died.........");
    Self::pause();
    self.finish_game();
  }

  fn tick_ask_name_mode(&mut self) {
    self.ask("What is your name, explorer? ", |state, input| {
      if input.len() == 0 {
        println!("Pardon me?");
      } else {
        state.player_name = input;
        state.set_mode(GameMode::Primary);
      }
    });
  }

  fn tick_eat_food_mode(&mut self) {
    if self.show_desc {
      self.print_food();
      println!("");
      self.show_desc = false;
    }

    self.ask_i32("How many do you want to eat? ", |state, amount| {
      if amount < 0 {
        println!("GIVE ME A POSITIVE INTEGER.");
        state.ask_again();
      } else if amount == 0 {
        println!("Fine, be that way.");
        Self::pause();
        state.set_mode(GameMode::Primary);
      } else if amount > state.food {
        state.accuse_player_of_cheating();
        state.set_mode(GameMode::Primary);
      } else {
        println!("After some munching, you feel stronger.");
        state.food -= amount;
        state.strength += amount * STRENGTH_PER_FOOD;
        state.set_mode(GameMode::Primary);
        Self::pause();
      }
    });
  }

  pub fn process_move(&mut self) {
    self.tally += TALLY_PER_MOVE;
    self.strength -= STRENGTH_LOSS_PER_MOVE;
  }

  pub fn tick(&mut self) {
    let mut input_processed = false;
    let mut input_cb: Option<Box<InputCallback>> = None;

    ::std::mem::swap(&mut input_cb, &mut self.input_callback);

    if let Some(ref cb) = input_cb {
      self.is_processing_input = true;
      match platform::read_input() {
        Some(input) => {
          platform::hide_prompt();
          cb(self, input);
          // Note that at this point, self.input_callback may be
          // set again, if the callback asked for input again.
        },
        None => {
          // We're probably running in the browser and there's currently
          // no input to process.
        }
      }
      self.is_processing_input = false;
      input_processed = true;
    }

    if input_processed {
      if self.read_input_again {
        assert!(self.input_callback.is_none(),
                "Program cannot ask to re-run last input callback \
                 *and* run a new input callback simultaneously");
        self.read_input_again = false;
        self.input_callback = input_cb;
        platform::show_prompt(self.last_input_prompt.as_str());
      }

      return;
    }

    if self.strength < 1 { self.die() }

    match self.curr_mode {
      GameMode::AskName => { self.tick_ask_name_mode() },
      GameMode::Primary => { self.tick_primary_mode() },
      GameMode::Inventory => { self.tick_inventory_mode() },
      GameMode::EatFood => { self.tick_eat_food_mode() },
      GameMode::Combat(state) => { self.tick_combat_mode(&state) },
      GameMode::Finished => {},

      #[cfg(debug_assertions)]
      GameMode::Debug => { self.tick_debug_mode() },
    }
  }
}
<|endoftext|>


<commit_before>use std::collections::BinaryHeap;
use std::cmp::Ord;

pub(crate) fn k_smallest<T: Ord, I: Iterator<Item = T>>(mut iter: I, k: usize) -> BinaryHeap<T> {
    if k == 0 { return BinaryHeap::new(); }

    let mut heap = iter.by_ref().take(k).collect::<BinaryHeap<_>>();

    for i in iter {
        debug_assert_eq!(heap.len(), k);
        // Guaranteed not-None, since we keep exactly k>0 elements in the heap.
        let mut lorgest = heap.peek_mut().unwrap();
        // Equivalent to heap.push(min(i, heap.pop())) but more efficient.
        if *lorgest > i { *lorgest = i; }
    }

    heap
}
<commit_msg>k_smallest: Work around suboptimality in `peek_mut`<commit_after>use std::collections::BinaryHeap;
use std::cmp::Ord;

pub(crate) fn k_smallest<T: Ord, I: Iterator<Item = T>>(mut iter: I, k: usize) -> BinaryHeap<T> {
    if k == 0 { return BinaryHeap::new(); }

    let mut heap = iter.by_ref().take(k).collect::<BinaryHeap<_>>();

    for i in iter {
        debug_assert_eq!(heap.len(), k);
        // Equivalent to heap.push(min(i, heap.pop())) but more efficient.
        // This should be done with a single `.peek_mut().unwrap()` but
        //  `PeekMut` sifts-down unconditionally on Rust 1.46.0 and prior.
        if *heap.peek().unwrap() > i {
            *heap.peek_mut().unwrap() = i;
        }
    }

    heap
}
<|endoftext|>


<commit_before>// Copyright 2014 Dmitry "Divius" Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

//! DHT node table implementation based on Kademlia.
//!
//! See [original paper](http://pdos.csail.mit.edu/%7Epetar/papers/maymounkov-kademlia-lncs.pdf)
//! for details. The most essential difference is that when k-bucket is full,
//! no RPC call is done. It is up to upper-level code to ensure proper clean up
//! using `pop_oldest` call.

use std::cmp;
use std::fmt::Debug;

use super::GenericId;
use super::GenericNodeTable;
use super::Node;

// TODO(divius): make public?
static BUCKET_SIZE: usize = 32;
static HASH_SIZE: usize = 64;

/// Kademlia node table.
///
/// Keeps nodes in a number of k-buckets (equal to bit size of ID in a system,
/// usually 160), where N-th k-bucket contains nodes with distance
/// from 2^N to 2^(N+1) from our node.
pub struct KNodeTable<TId, TAddr> {
    this_id: TId,
    hash_size: usize,
    // TODO(divius): convert to more appropriate data structure
    buckets: Vec<KBucket<TId, TAddr>>,
}

/// K-bucket - structure for keeping last nodes in Kademlia.
struct KBucket<TId, TAddr> {
    data: Vec<Node<TId, TAddr>>,
    size: usize,
}

impl<TId, TAddr> KNodeTable<TId, TAddr>
        where TId: GenericId,
              TAddr: Clone + Debug {
    /// Create a new node table.
    ///
    /// `this_id` -- ID of the current node (used to calculate metrics).
    pub fn new(this_id: TId) -> KNodeTable<TId, TAddr> {
        KNodeTable::with_details(this_id, BUCKET_SIZE, HASH_SIZE)
    }

    // TODO(divius): make public?
    fn with_details(this_id: TId, bucket_size: usize,
                    hash_size: usize) -> KNodeTable<TId, TAddr> {
        KNodeTable {
            this_id: this_id,
            hash_size: hash_size,
            buckets: (0..hash_size).map(
                              |_| KBucket::new(bucket_size)).collect(),
        }
    }

    #[inline]
    fn distance(id1: &TId, id2: &TId) -> TId {
        id1.bitxor(id2)
    }

    fn bucket_number(&self, id: &TId) -> usize {
        let diff = KNodeTable::<TId, TAddr>::distance(&self.this_id, id);
        debug_assert!(!diff.is_zero());
        let res = diff.bits() - 1;
        debug!("ID {:?} relative to own ID {:?} falls into bucket {:?}",
               id, self.this_id, res);
        res
    }
}

impl<TId, TAddr> GenericNodeTable<TId, TAddr> for KNodeTable<TId, TAddr>
        where TId: GenericId,
              TAddr: Clone + Debug + Sync + Send {
    fn random_id(&self) -> TId {
        TId::gen(self.hash_size)
    }

    fn update(&mut self, node: &Node<TId, TAddr>) -> bool {
        assert!(node.id != self.this_id);
        let bucket = self.bucket_number(&node.id);
        self.buckets[bucket].update(node)
    }

    fn find(&self, id: &TId, count: usize) -> Vec<Node<TId, TAddr>> {
        debug_assert!(count > 0);
        assert!(*id != self.this_id);
        let bucket = self.bucket_number(id);
        self.buckets[bucket].find(id, count)
    }

    fn pop_oldest(&mut self) -> Vec<Node<TId, TAddr>> {
        // For every full k-bucket, pop the last.
        // TODO(divius): TTL expiration?
        self.buckets.iter_mut()
            .filter(|b| { !b.data.is_empty() && b.size == b.data.len() })
            .map(|b| b.data.remove(0))
            .collect()
    }
}

impl<TId, TAddr> KBucket<TId, TAddr>
        where TId: GenericId,
              TAddr: Clone + Debug {
    pub fn new(k: usize) -> KBucket<TId, TAddr> {
        assert!(k > 0);
        KBucket {
            data: Vec::new(),
            size: k
        }
    }

    pub fn update(&mut self, node: &Node<TId, TAddr>) -> bool {
        if self.data.iter().any(|x| x.id == node.id) {
            self.update_position(node.clone());
            debug!("Promoted node {:?} to the top of kbucket", node);
            true
        }
        else if self.data.len() == self.size {
            debug!("Not adding new node {:?} to kbucket - no space left", node);
            false
        }
        else {
            self.data.push(node.clone());
            debug!("Added new node {:?} to kbucket", node);
            true
        }
    }

    pub fn find(&self, id: &TId, count: usize) -> Vec<Node<TId, TAddr>> {
        let sort_fn = |a: &Node<TId, TAddr>, b: &Node<TId, TAddr>| {
            KNodeTable::<TId, TAddr>::distance(id, &a.id)
                .cmp(&KNodeTable::<TId, TAddr>::distance(id, &b.id))
        };
        let mut data_copy = self.data.clone();
        data_copy.sort_by(sort_fn);
        data_copy[0..cmp::min(count, data_copy.len())].to_vec()
    }

    fn update_position(&mut self, node: Node<TId, TAddr>) {
        // TODO(divius): 1. optimize, 2. make it less ugly
        let mut new_data = Vec::with_capacity(self.data.len());
        new_data.extend(self.data.iter()
                        .filter(|x| x.id != node.id)
                        .map(|x| x.clone()));
        new_data.push(node.clone());
        self.data = new_data;
    }
}

#[cfg(test)]
mod test {
    use std::net;

    use super::super::GenericNodeTable;
    use super::super::Node;

    use super::HASH_SIZE;
    use super::KBucket;
    use super::KNodeTable;

    use super::super::utils::test;
    type TestsIdType = test::IdType;
    use super::super::base::GenericId;

    fn prepare(count: u8) -> KBucket<TestsIdType, net::SocketAddr> {
        KBucket {
            data: (0..count).map(|i| test::new_node(test::make_id(i))).collect(),
            size: 3,
        }
    }

    fn assert_node_list_eq(expected: &[&Node<TestsIdType, net::SocketAddr>], actual: &Vec<Node<TestsIdType, net::SocketAddr>>) {
        let act: Vec<TestsIdType> = actual.iter()
            .map(|n| n.id.clone()).collect();
        let exp: Vec<TestsIdType> = expected.iter()
            .map(|n| n.id.clone()).collect();
        assert_eq!(exp, act);
    }

    #[test]
    fn test_nodetable_new() {
        let n = KNodeTable::<u64, ()>::new(42);
        assert_eq!(HASH_SIZE, n.buckets.len());
    }

    #[test]
    fn test_nodetable_bucket_number() {
        let n = KNodeTable::<u64, ()>::new(42);
        let id = 41;
        // 42 xor 41 == 3
        assert_eq!(1, n.bucket_number(&id));
    }

    #[test]
    fn test_nodetable_pop_oldest() {
        let mut n = KNodeTable::<TestsIdType, net::SocketAddr>::with_details(
            test::make_id(42), 2, HASH_SIZE);
        n.update(&test::new_node(test::make_id(41)));
        n.update(&test::new_node(test::make_id(43)));
        n.update(&test::new_node(test::make_id(40)));
        assert_eq!(0, n.buckets[2].data.len());
        assert_eq!(2, n.buckets[1].data.len());
        assert_eq!(1, n.buckets[0].data.len());
        let nodes = n.pop_oldest();
        assert_eq!(1, nodes.len());
        assert_eq!(test::make_id(41), nodes[0].id);
        assert_eq!(0, n.buckets[2].data.len());
        assert_eq!(1, n.buckets[1].data.len());
        assert_eq!(1, n.buckets[0].data.len());
        assert_eq!(test::make_id(40), n.buckets[1].data[0].id);
    }

    #[test]
    fn test_nodetable_find() {
        let n = KNodeTable {
            buckets: vec![prepare(1), prepare(3), prepare(1)],
            this_id: test::make_id(0),
            hash_size: HASH_SIZE,
        };
        // 0 xor 3 = 3, 1 xor 3 = 2, 2 xor 3 = 1
        let id = test::make_id(3);
        assert_node_list_eq(&[&n.buckets[1].data[2]],
                            &n.find(&id, 1));
    }

    #[test]
    fn test_nodetable_update() {
        let mut n = KNodeTable::with_details(
            test::make_id(42), 1, HASH_SIZE);
        let node = test::new_node(test::make_id(41));
        n.update(&node);
        assert_eq!(1, n.buckets[1].data.len());
        n.update(&node);
        assert_eq!(1, n.buckets[1].data.len());
    }

    #[test]
    fn test_nodetable_random_id() {
        let n = KNodeTable::<u64, ()>::with_details(
            42, 1, HASH_SIZE);
        for _ in 0..100 {
            assert!(n.random_id().bits() <= HASH_SIZE);
        }
        assert!(n.random_id() != n.random_id());
    }

    #[test]
    fn test_kbucket_new() {
        let b = KBucket::<TestsIdType, net::SocketAddr>::new(3);
        assert_eq!(0, b.data.len());
        assert_eq!(3, b.size);
    }

    #[test]
    fn test_kbucket_update_unknown() {
        let mut b = prepare(1);
        let node = test::new_node(test::make_id(42));
        assert!(b.update(&node));
        assert_eq!(2, b.data.len());
        assert_eq!(node.id, b.data[1].id);
    }

    #[test]
    fn test_kbucket_update_known() {
        let mut b = prepare(2);
        let node = test::new_node(test::make_id(0));
        assert!(b.update(&node));
        assert_eq!(2, b.data.len());
        assert_eq!(node.id, b.data[1].id);
    }

    #[test]
    fn test_kbucket_update_conflict() {
        let mut b = prepare(3);  // 3 is size
        let node = test::new_node(test::make_id(42));
        assert!(!b.update(&node))
    }

    #[test]
    fn test_kbucket_find() {
        let b = prepare(3);
        // Nodes with ID's 0, 1, 2; assume our ID is also 2 (impossible IRL)
        let id = test::make_id(2);
        // 0 xor 2 = 2, 1 xor 2 = 3, 2 xor 2 = 0
        assert_node_list_eq(&[&b.data[2]], &b.find(&id, 1));
        assert_node_list_eq(&[&b.data[2], &b.data[0]], &b.find(&id, 2));
    }

    #[test]
    fn test_kbucket_find_too_much() {
        let b = prepare(3);
        // Nodes with ID's 0, 1, 2; assume our ID is also 2 (impossible IRL)
        let id = test::make_id(2);
        // 0 xor 2 = 2, 1 xor 2 = 3, 2 xor 2 = 0
        assert_node_list_eq(&[&b.data[2], &b.data[0], &b.data[1]],
                            &b.find(&id, 100));
    }
}
<commit_msg>Improve KNodeTable::pop_oldest()'s complexity.<commit_after>// Copyright 2014 Dmitry "Divius" Tantsur <divius.inside@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

//! DHT node table implementation based on Kademlia.
//!
//! See [original paper](http://pdos.csail.mit.edu/%7Epetar/papers/maymounkov-kademlia-lncs.pdf)
//! for details. The most essential difference is that when k-bucket is full,
//! no RPC call is done. It is up to upper-level code to ensure proper clean up
//! using `pop_oldest` call.

use std::cmp;
use std::fmt::Debug;
use std::collections::VecDeque;

use super::GenericId;
use super::GenericNodeTable;
use super::Node;

// TODO(divius): make public?
static BUCKET_SIZE: usize = 32;
static HASH_SIZE: usize = 64;

/// Kademlia node table.
///
/// Keeps nodes in a number of k-buckets (equal to bit size of ID in a system,
/// usually 160), where N-th k-bucket contains nodes with distance
/// from 2^N to 2^(N+1) from our node.
pub struct KNodeTable<TId, TAddr> {
    this_id: TId,
    hash_size: usize,
    // TODO(divius): convert to more appropriate data structure
    buckets: Vec<KBucket<TId, TAddr>>,
}

/// K-bucket - structure for keeping last nodes in Kademlia.
struct KBucket<TId, TAddr> {
    data: VecDeque<Node<TId, TAddr>>,
    size: usize,
}

impl<TId, TAddr> KNodeTable<TId, TAddr>
        where TId: GenericId,
              TAddr: Clone + Debug {
    /// Create a new node table.
    ///
    /// `this_id` -- ID of the current node (used to calculate metrics).
    pub fn new(this_id: TId) -> KNodeTable<TId, TAddr> {
        KNodeTable::with_details(this_id, BUCKET_SIZE, HASH_SIZE)
    }

    // TODO(divius): make public?
    fn with_details(this_id: TId, bucket_size: usize,
                    hash_size: usize) -> KNodeTable<TId, TAddr> {
        KNodeTable {
            this_id: this_id,
            hash_size: hash_size,
            buckets: (0..hash_size).map(
                              |_| KBucket::new(bucket_size)).collect(),
        }
    }

    #[inline]
    fn distance(id1: &TId, id2: &TId) -> TId {
        id1.bitxor(id2)
    }

    fn bucket_number(&self, id: &TId) -> usize {
        let diff = KNodeTable::<TId, TAddr>::distance(&self.this_id, id);
        debug_assert!(!diff.is_zero());
        let res = diff.bits() - 1;
        debug!("ID {:?} relative to own ID {:?} falls into bucket {:?}",
               id, self.this_id, res);
        res
    }
}

impl<TId, TAddr> GenericNodeTable<TId, TAddr> for KNodeTable<TId, TAddr>
        where TId: GenericId,
              TAddr: Clone + Debug + Sync + Send {
    fn random_id(&self) -> TId {
        TId::gen(self.hash_size)
    }

    fn update(&mut self, node: &Node<TId, TAddr>) -> bool {
        assert!(node.id != self.this_id);
        let bucket = self.bucket_number(&node.id);
        self.buckets[bucket].update(node)
    }

    fn find(&self, id: &TId, count: usize) -> Vec<Node<TId, TAddr>> {
        debug_assert!(count > 0);
        assert!(*id != self.this_id);
        let bucket = self.bucket_number(id);
        self.buckets[bucket].find(id, count)
    }

    fn pop_oldest(&mut self) -> Vec<Node<TId, TAddr>> {
        // For every full k-bucket, pop the last.
        // TODO(divius): TTL expiration?
        self.buckets.iter_mut()
            .filter(|b| { !b.data.is_empty() && b.size == b.data.len() })
            .map(|b| b.data.pop_front().unwrap())
            .collect()
    }
}

impl<TId, TAddr> KBucket<TId, TAddr>
        where TId: GenericId,
              TAddr: Clone + Debug {
    pub fn new(k: usize) -> KBucket<TId, TAddr> {
        assert!(k > 0);
        KBucket {
            data: VecDeque::new(),
            size: k
        }
    }

    pub fn update(&mut self, node: &Node<TId, TAddr>) -> bool {
        if self.data.iter().any(|x| x.id == node.id) {
            self.update_position(node.clone());
            debug!("Promoted node {:?} to the top of kbucket", node);
            true
        }
        else if self.data.len() == self.size {
            debug!("Not adding new node {:?} to kbucket - no space left", node);
            false
        }
        else {
            self.data.push_back(node.clone());
            debug!("Added new node {:?} to kbucket", node);
            true
        }
    }

    pub fn find(&self, id: &TId, count: usize) -> Vec<Node<TId, TAddr>> {
        let sort_fn = |a: &Node<TId, TAddr>, b: &Node<TId, TAddr>| {
            KNodeTable::<TId, TAddr>::distance(id, &a.id)
                .cmp(&KNodeTable::<TId, TAddr>::distance(id, &b.id))
        };
        let mut data_copy: Vec<_> = self.data.iter().map(|n| n.clone()).collect();
        data_copy.sort_by(sort_fn);
        data_copy[0..cmp::min(count, data_copy.len())].to_vec()
    }

    fn update_position(&mut self, node: Node<TId, TAddr>) {
        // TODO(divius): 1. optimize, 2. make it less ugly
        let mut new_data = VecDeque::with_capacity(self.data.len());
        new_data.extend(self.data.iter()
                        .filter(|x| x.id != node.id)
                        .map(|x| x.clone()));
        new_data.push_back(node.clone());
        self.data = new_data;
    }
}

#[cfg(test)]
mod test {
    use std::net;

    use super::super::GenericNodeTable;
    use super::super::Node;

    use super::HASH_SIZE;
    use super::KBucket;
    use super::KNodeTable;

    use super::super::utils::test;
    type TestsIdType = test::IdType;
    use super::super::base::GenericId;

    fn prepare(count: u8) -> KBucket<TestsIdType, net::SocketAddr> {
        KBucket {
            data: (0..count).map(|i| test::new_node(test::make_id(i))).collect(),
            size: 3,
        }
    }

    fn assert_node_list_eq(expected: &[&Node<TestsIdType, net::SocketAddr>], actual: &Vec<Node<TestsIdType, net::SocketAddr>>) {
        let act: Vec<TestsIdType> = actual.iter()
            .map(|n| n.id.clone()).collect();
        let exp: Vec<TestsIdType> = expected.iter()
            .map(|n| n.id.clone()).collect();
        assert_eq!(exp, act);
    }

    #[test]
    fn test_nodetable_new() {
        let n = KNodeTable::<u64, ()>::new(42);
        assert_eq!(HASH_SIZE, n.buckets.len());
    }

    #[test]
    fn test_nodetable_bucket_number() {
        let n = KNodeTable::<u64, ()>::new(42);
        let id = 41;
        // 42 xor 41 == 3
        assert_eq!(1, n.bucket_number(&id));
    }

    #[test]
    fn test_nodetable_pop_oldest() {
        let mut n = KNodeTable::<TestsIdType, net::SocketAddr>::with_details(
            test::make_id(42), 2, HASH_SIZE);
        n.update(&test::new_node(test::make_id(41)));
        n.update(&test::new_node(test::make_id(43)));
        n.update(&test::new_node(test::make_id(40)));
        assert_eq!(0, n.buckets[2].data.len());
        assert_eq!(2, n.buckets[1].data.len());
        assert_eq!(1, n.buckets[0].data.len());
        let nodes = n.pop_oldest();
        assert_eq!(1, nodes.len());
        assert_eq!(test::make_id(41), nodes[0].id);
        assert_eq!(0, n.buckets[2].data.len());
        assert_eq!(1, n.buckets[1].data.len());
        assert_eq!(1, n.buckets[0].data.len());
        assert_eq!(test::make_id(40), n.buckets[1].data[0].id);
    }

    #[test]
    fn test_nodetable_find() {
        let n = KNodeTable {
            buckets: vec![prepare(1), prepare(3), prepare(1)],
            this_id: test::make_id(0),
            hash_size: HASH_SIZE,
        };
        // 0 xor 3 = 3, 1 xor 3 = 2, 2 xor 3 = 1
        let id = test::make_id(3);
        assert_node_list_eq(&[&n.buckets[1].data[2]],
                            &n.find(&id, 1));
    }

    #[test]
    fn test_nodetable_update() {
        let mut n = KNodeTable::with_details(
            test::make_id(42), 1, HASH_SIZE);
        let node = test::new_node(test::make_id(41));
        n.update(&node);
        assert_eq!(1, n.buckets[1].data.len());
        n.update(&node);
        assert_eq!(1, n.buckets[1].data.len());
    }

    #[test]
    fn test_nodetable_random_id() {
        let n = KNodeTable::<u64, ()>::with_details(
            42, 1, HASH_SIZE);
        for _ in 0..100 {
            assert!(n.random_id().bits() <= HASH_SIZE);
        }
        assert!(n.random_id() != n.random_id());
    }

    #[test]
    fn test_kbucket_new() {
        let b = KBucket::<TestsIdType, net::SocketAddr>::new(3);
        assert_eq!(0, b.data.len());
        assert_eq!(3, b.size);
    }

    #[test]
    fn test_kbucket_update_unknown() {
        let mut b = prepare(1);
        let node = test::new_node(test::make_id(42));
        assert!(b.update(&node));
        assert_eq!(2, b.data.len());
        assert_eq!(node.id, b.data[1].id);
    }

    #[test]
    fn test_kbucket_update_known() {
        let mut b = prepare(2);
        let node = test::new_node(test::make_id(0));
        assert!(b.update(&node));
        assert_eq!(2, b.data.len());
        assert_eq!(node.id, b.data[1].id);
    }

    #[test]
    fn test_kbucket_update_conflict() {
        let mut b = prepare(3);  // 3 is size
        let node = test::new_node(test::make_id(42));
        assert!(!b.update(&node))
    }

    #[test]
    fn test_kbucket_find() {
        let b = prepare(3);
        // Nodes with ID's 0, 1, 2; assume our ID is also 2 (impossible IRL)
        let id = test::make_id(2);
        // 0 xor 2 = 2, 1 xor 2 = 3, 2 xor 2 = 0
        assert_node_list_eq(&[&b.data[2]], &b.find(&id, 1));
        assert_node_list_eq(&[&b.data[2], &b.data[0]], &b.find(&id, 2));
    }

    #[test]
    fn test_kbucket_find_too_much() {
        let b = prepare(3);
        // Nodes with ID's 0, 1, 2; assume our ID is also 2 (impossible IRL)
        let id = test::make_id(2);
        // 0 xor 2 = 2, 1 xor 2 = 3, 2 xor 2 = 0
        assert_node_list_eq(&[&b.data[2], &b.data[0], &b.data[1]],
                            &b.find(&id, 100));
    }
}
<|endoftext|>


<commit_before>// (c) 2016 Productize SPRL <joost@productize.be>

// extension: .kicad_pcb
// format: new-style

use std::fmt;
use std::result;

// from parent
use Sexp;
use symbolic_expressions::IntoSexp;
use layout::data::*;

impl IntoSexp for Layout {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("kicad_pcb".into());

        v.push(Sexp::new_named("version", self.version));

        let mut v2 = vec![];
        v2.push(Sexp::new_string("host"));
        v2.push(Sexp::new_string(self.host.tool.clone()));
        v2.push(Sexp::new_string(self.host.build.clone()));
        v.push(Sexp::new_list(v2));

        v.push(self.general.into_sexp());

        v.push(Sexp::new_named("page", self.page.clone()));

        let mut v2 = vec![];
        v2.push(Sexp::new_string("layers"));
        for layer in &self.layers {
            v2.push(layer.into_sexp());
        }
        v.push(Sexp::new_list(v2));

        v.push(self.setup.into_sexp());

        for element in &self.elements {
            v.push(element.into_sexp());
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for General {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("general"));
        v.push(Sexp::new_named("links", self.links));
        v.push(Sexp::new_named("no_connects", self.no_connects));
        v.push(self.area.into_sexp());
        v.push(Sexp::new_named("thickness", self.thickness));
        v.push(Sexp::new_named("drawings", self.drawings));
        v.push(Sexp::new_named("tracks", self.tracks));
        v.push(Sexp::new_named("zones", self.zones));
        v.push(Sexp::new_named("modules", self.modules));
        v.push(Sexp::new_named("nets", self.nets));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Area {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("area"));
        v.push(Sexp::new_string(self.x1));
        v.push(Sexp::new_string(self.y1));
        v.push(Sexp::new_string(self.x2));
        v.push(Sexp::new_string(self.y2));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Element {
    fn into_sexp(&self) -> Sexp {
        match *self {
            Element::Other(ref s) => s.clone(),
            Element::Module(ref s) => s.into_sexp(),
            Element::Net(ref s) => s.into_sexp(),
            Element::NetClass(ref s) => s.into_sexp(),
            Element::GrText(ref s) => s.into_sexp(),
            Element::GrLine(ref s) => s.into_sexp(),
            Element::GrArc(ref s) => s.into_sexp(),
            Element::Dimension(ref s) => s.into_sexp(),
            Element::Zone(ref s) => s.into_sexp(),
        }
    }
}

impl IntoSexp for Zone {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("zone"));
        v.push(Sexp::new_named("net", self.net));
        v.push(Sexp::new_named("net_name", &self.net_name));
        for o in &self.other {
            v.push(o.clone());
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Net {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("net"));
        v.push(Sexp::new_string(self.num));
        v.push(Sexp::new_string(self.name.clone()));
        Sexp::new_list(v)
    }
}

impl IntoSexp for NetClass {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("net_class"));
        v.push(Sexp::new_string(self.name.clone()));
        v.push(Sexp::new_string(self.desc.clone()));
        v.push(Sexp::new_named("clearance", self.clearance));
        v.push(Sexp::new_named("trace_width", self.trace_width));
        v.push(Sexp::new_named("via_dia", self.via_dia));
        v.push(Sexp::new_named("via_drill", self.via_drill));
        v.push(Sexp::new_named("uvia_dia", self.uvia_dia));
        v.push(Sexp::new_named("uvia_drill", self.uvia_drill));
        if let Some(diff_pair_gap) = self.diff_pair_gap {
            v.push(Sexp::new_named("diff_pair_gap", diff_pair_gap));
        }
        if let Some(diff_pair_width) = self.diff_pair_width {
            v.push(Sexp::new_named("diff_pair_width", diff_pair_width));
        }
        for net in &self.nets {
            v.push(Sexp::new_named("add_net", net));
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Layer {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string(self.num));
        v.push(Sexp::new_string(self.layer.clone()));
        v.push(Sexp::new_string(self.layer_type.clone()));
        if self.hide {
            v.push(Sexp::new_string("hide"));
        }
        Sexp::new_list(v)
    }
}

impl fmt::Display for LayerType {
    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        let s = match *self {
            LayerType::Signal => "signal",
            LayerType::User => "user",
        };
        write!(f, "{}", s)
    }
}

impl IntoSexp for SetupElement {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string(self.name.clone()));
        v.push(Sexp::new_string(self.value1.clone()));
        if let Some(ref x) = self.value2 {
            v.push(Sexp::new_string(x))
        }
        Sexp::new_list(v)
    }
}

impl IntoSexp for Setup {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("setup"));
        for ref k in &self.elements {
            v.push(k.into_sexp())
        }
        let mut v2 = vec![];
        v2.push(Sexp::new_string("pcbplotparams"));
        for ref k in &self.pcbplotparams {
            v2.push(k.into_sexp())
        }
        v.push(Sexp::new_list(v2));
        Sexp::new_list(v)
    }
}

impl IntoSexp for GrText {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("gr_text"));
        v.push(Sexp::new_string(self.value.clone()));
        v.push(self.at.into_sexp());
        v.push(Sexp::new_named_sexp("layer", &self.layer));
        v.push(self.effects.into_sexp());
        Sexp::new_list(v)
    }
}

impl IntoSexp for GrLine {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("gr_line"));
        v.push(self.start.into_sexp());
        v.push(self.end.into_sexp());
        v.push(Sexp::new_named("angle", self.angle));
        v.push(Sexp::new_named_sexp("layer", &self.layer));
        v.push(Sexp::new_named("width", self.width));
        Sexp::new_list(v)
    }
}

impl IntoSexp for GrArc {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("gr_arc"));
        v.push(self.start.into_sexp());
        v.push(self.end.into_sexp());
        v.push(Sexp::new_named("angle", self.angle));
        v.push(Sexp::new_named_sexp("layer", &self.layer));
        v.push(Sexp::new_named("width", self.width));
        Sexp::new_list(v)
    }
}

impl IntoSexp for Dimension {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::new_string("dimension"));
        v.push(Sexp::new_string(self.name.clone()));
        v.push(Sexp::new_named("width", self.width));
        v.push(Sexp::new_named_sexp("layer", &self.layer));
        match self.tstamp {
            None => (),
            Some(ref tstamp) => {
                v.push(Sexp::new_named("tstamp", tstamp));
            }
        }
        v.push(self.text.into_sexp());
        v.push(Sexp::new_named_sexp("feature1", &self.feature1));
        v.push(Sexp::new_named_sexp("feature2", &self.feature2));
        v.push(Sexp::new_named_sexp("crossbar", &self.crossbar));
        v.push(Sexp::new_named_sexp("arrow1a", &self.arrow1a));
        v.push(Sexp::new_named_sexp("arrow1b", &self.arrow1b));
        v.push(Sexp::new_named_sexp("arrow2a", &self.arrow2a));
        v.push(Sexp::new_named_sexp("arrow2b", &self.arrow2b));
        Sexp::new_list(v)
    }
}
<commit_msg>rework layout with into()<commit_after>// (c) 2016-2017 Productize SPRL <joost@productize.be>

// extension: .kicad_pcb
// format: new-style

use std::fmt;
use std::result;

// from parent
use Sexp;
use symbolic_expressions::IntoSexp;
use layout::data::*;

impl IntoSexp for Layout {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("kicad_pcb".into());

        v.push(("version", &self.version).into());

        let mut v2 = vec![];
        v2.push("host".into());
        v2.push(self.host.tool.clone().into());
        v2.push(self.host.build.clone().into());
        v.push(v2.into());

        v.push(self.general.into_sexp());

        v.push(("page", &self.page).into());

        let mut v2 = vec![];
        v2.push("layers".into());
        for layer in &self.layers {
            v2.push(layer.into_sexp());
        }
        v.push(v2.into());

        v.push(self.setup.into_sexp());

        for element in &self.elements {
            v.push(element.into_sexp());
        }
        v.into()
    }
}

impl IntoSexp for General {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("general".into());
        v.push(("links", &self.links).into());
        v.push(("no_connects", &self.no_connects).into());
        v.push(self.area.into_sexp());
        v.push(("thickness", &self.thickness).into());
        v.push(("drawings", &self.drawings).into());
        v.push(("tracks", &self.tracks).into());
        v.push(("zones", &self.zones).into());
        v.push(("modules", &self.modules).into());
        v.push(("nets", &self.nets).into());
        v.into()
    }
}

impl IntoSexp for Area {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("area".into());
        v.push(self.x1.into());
        v.push(self.y1.into());
        v.push(self.x2.into());
        v.push(self.y2.into());
        v.into()
    }
}

impl IntoSexp for Element {
    fn into_sexp(&self) -> Sexp {
        match *self {
            Element::Other(ref s) => s.clone(),
            Element::Module(ref s) => s.into_sexp(),
            Element::Net(ref s) => s.into_sexp(),
            Element::NetClass(ref s) => s.into_sexp(),
            Element::GrText(ref s) => s.into_sexp(),
            Element::GrLine(ref s) => s.into_sexp(),
            Element::GrArc(ref s) => s.into_sexp(),
            Element::Dimension(ref s) => s.into_sexp(),
            Element::Zone(ref s) => s.into_sexp(),
        }
    }
}

impl IntoSexp for Zone {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("zone".into());
        v.push(("net", &self.net).into());
        v.push(("net_name", &self.net_name).into());
        for o in &self.other {
            v.push(o.clone());
        }
        v.into()
    }
}

impl IntoSexp for Net {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("net".into());
        v.push(self.num.into());
        v.push(self.name.clone().into());
        v.into()
    }
}

impl IntoSexp for NetClass {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("net_class".into());
        v.push(self.name.clone().into());
        v.push(self.desc.clone().into());
        v.push(("clearance", &self.clearance).into());
        v.push(("trace_width", &self.trace_width).into());
        v.push(("via_dia", &self.via_dia).into());
        v.push(("via_drill", &self.via_drill).into());
        v.push(("uvia_dia", &self.uvia_dia).into());
        v.push(("uvia_drill", &self.uvia_drill).into());
        if let Some(diff_pair_gap) = self.diff_pair_gap {
            v.push(("diff_pair_gap", &diff_pair_gap).into());
        }
        if let Some(diff_pair_width) = self.diff_pair_width {
            v.push(("diff_pair_width", &diff_pair_width).into());
        }
        for net in &self.nets {
            v.push(("add_net", net).into());
        }
        v.into()
    }
}

impl IntoSexp for Layer {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(self.num.into());
        v.push(format!("{}", self.layer).into());
        v.push(format!("{}", self.layer_type).into());
        if self.hide {
            v.push("hide".into());
        }
        v.into()
    }
}

impl fmt::Display for LayerType {
    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
        let s = match *self {
            LayerType::Signal => "signal",
            LayerType::User => "user",
        };
        write!(f, "{}", s)
    }
}

impl IntoSexp for SetupElement {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push(self.name.clone().into());
        v.push(self.value1.clone().into());
        if let Some(ref x) = self.value2 {
            v.push(x.clone().into())
        }
        v.into()
    }
}

impl IntoSexp for Setup {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("setup".into());
        for ref k in &self.elements {
            v.push(k.into_sexp())
        }
        let mut v2 = vec![];
        v2.push("pcbplotparams".into());
        for ref k in &self.pcbplotparams {
            v2.push(k.into_sexp())
        }
        v.push(v2.into());
        v.into()
    }
}

impl IntoSexp for GrText {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("gr_text".into());
        v.push(self.value.clone().into());
        v.push(self.at.into_sexp());
        v.push(("layer", &self.layer).into());
        v.push(self.effects.into_sexp());
        v.into()
    }
}

impl IntoSexp for GrLine {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("gr_line".into());
        v.push(self.start.into_sexp());
        v.push(self.end.into_sexp());
        v.push(("angle", &self.angle).into());
        v.push(("layer", &self.layer).into());
        v.push(("width", &self.width).into());
        v.into()
    }
}

impl IntoSexp for GrArc {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("gr_arc".into());
        v.push(self.start.into_sexp());
        v.push(self.end.into_sexp());
        v.push(("angle", &self.angle).into());
        v.push(("layer", &self.layer).into());
        v.push(("width", &self.width).into());
        v.into()
    }
}

impl IntoSexp for Dimension {
    fn into_sexp(&self) -> Sexp {
        let mut v = vec![];
        v.push("dimension".into());
        v.push(self.name.clone().into());
        v.push(("width", &self.width).into());
        v.push(("layer", &self.layer).into());
        match self.tstamp {
            None => (),
            Some(ref tstamp) => {
                v.push(("tstamp", tstamp).into());
            }
        }
        v.push(self.text.into_sexp());
        v.push(Sexp::new_named_sexp("feature1", &self.feature1));
        v.push(Sexp::new_named_sexp("feature2", &self.feature2));
        v.push(Sexp::new_named_sexp("crossbar", &self.crossbar));
        v.push(Sexp::new_named_sexp("arrow1a", &self.arrow1a));
        v.push(Sexp::new_named_sexp("arrow1b", &self.arrow1b));
        v.push(Sexp::new_named_sexp("arrow2a", &self.arrow2a));
        v.push(Sexp::new_named_sexp("arrow2b", &self.arrow2b));
        v.into()
    }
}
<|endoftext|>


<commit_before>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;

use std::io::Cursor;

use serde::Deserialize;

use rmps::Deserializer;
use rmps::decode::Error;

#[test]
fn pass_newtype() {
    let buf = [0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct(u32);

    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Struct(42), actual);
}

#[test]
fn pass_tuple_struct() {
    let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Decoded(u32, u32);

    let mut de = Deserializer::new(cur);
    let actual: Decoded = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Decoded(42, 100500), actual);
}

#[test]
fn pass_single_field_struct() {
    let buf = [0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct {
        inner: u32
    };

    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Struct{inner: 42}, actual);
}

#[test]
fn pass_struct() {
    let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Decoded {
        id: u32,
        value: u32
    };

    let mut de = Deserializer::new(cur);
    let actual: Decoded = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Decoded { id: 42, value: 100500 }, actual);
}

#[test]
fn pass_struct_from_map() {
    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct {
        et: String,
        le: u8,
        shit: u8,
    }

    let buf = [
        0x83, // 3 (size)
        0xa2, 0x65, 0x74, // "et"
        0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila"
        0xa2, 0x6c, 0x65, // "le"
        0x00, // 0
        0xa4, 0x73, 0x68, 0x69, 0x74, // "shit"
        0x01, // 1
    ];
    let cur = Cursor::new(&buf[..]);

    // It appears no special behavior is needed for deserializing structs encoded as maps.
    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();
    let expected = Struct { et: "voila".into(), le: 0, shit: 1 };

    assert_eq!(expected, actual);
}

#[test]
fn pass_unit_variant() {
    // We expect enums to be encoded as [id, [...]]

    let buf = [0x92, 0x01, 0x90];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B, actual);
    assert_eq!(3, de.get_ref().position());
}

#[test]
fn pass_tuple_enum_with_arg() {
    // The encoded byte-array is: [1, [42]].
    let buf = [0x92, 0x01, 0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B(u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B(42), actual);
    assert_eq!(4, de.get_ref().position())
}

#[test]
fn pass_tuple_enum_with_args() {
    // The encoded bytearray is: [1, [42, 58]].
    let buf = [0x92, 0x01, 0x92, 0x2a, 0x3a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B(u32, u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B(42, 58), actual);
    assert_eq!(5, de.get_ref().position())
}

#[test]
fn fail_enum_sequence_mismatch() {
    // The encoded bytearray is: [1, 2, 100500].
    let buf = [0x93, 0x1, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    match actual.err().unwrap() {
        Error::LengthMismatch(3) => (),
        other => panic!("unexpected result: {:?}", other)
    }
}

#[test]
fn fail_enum_overflow() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    // TODO: Rename to Enum: A, B, C, ...
    enum Enum {
        A,
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    match actual.err().unwrap() {
        Error::Syntax(..) => (),
        other => panic!("unexpected result: {:?}", other)
    }
}

#[test]
fn pass_struct_enum_with_arg() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B { id: u32 },
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B { id: 42 }, actual);
    assert_eq!(4, de.get_ref().position())
}

#[test]
fn pass_newtype_variant() {
    // The encoded bytearray is: [0, [['le message']]].
    let buf = [0x92, 0x0, 0x91, 0x91, 0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Nested(String);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A(Nested),
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::A(Nested("le message".into())), actual);
    assert_eq!(buf.len() as u64, de.get_ref().position())
}

#[cfg(disabled)]  // This test doesn't actually compile anymore
#[test]
fn pass_enum_custom_policy() {
    use std::io::Read;
    use rmp_serde::decode::VariantVisitor;

    // We expect enums to be endoded as id, [...] (without wrapping tuple).

    let buf = [0x01, 0x90];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    struct CustomDeserializer<R: Read> {
        inner: Deserializer<R>,
    }

    impl<R: Read> serde::Deserializer for CustomDeserializer<R> {
        type Error = Error;

        fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Error>
            where V: serde::de::Visitor
        {
            self.inner.deserialize(visitor)
        }

        fn deserialize_enum<V>(&mut self, _enum: &str, _variants: &'static [&'static str], mut visitor: V)
            -> Result<V::Value, Error>
            where V: serde::de::EnumVisitor
        {
            visitor.visit(VariantVisitor::new(&mut self.inner))
        }

        forward_to_deserialize! {
            bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string unit seq
            seq_fixed_size bytes map tuple_struct unit_struct struct struct_field
            tuple option newtype_struct ignored_any
        }
    }

    let mut de = CustomDeserializer { inner: Deserializer::new(cur) };
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B, actual);
    assert_eq!(2, de.inner.get_ref().position());
}

#[test]
fn pass_struct_variant() {
    #[derive(Debug, PartialEq, Deserialize)]
    enum Custom {
        First { data: u32 },
        Second { data: u32 },
    }
    let out_first = vec![0x92, 0x00, 0x91, 0x2a];
    let out_second = vec![0x92, 0x01, 0x91, 0x2a];

    for (expected, out) in vec![(Custom::First{ data: 42 }, out_first), (Custom::Second { data: 42 }, out_second)] {
        let mut de = Deserializer::new(Cursor::new(&out[..]));
        let val: Custom = Deserialize::deserialize(&mut de).unwrap();
        assert_eq!(expected, val);
    }
}

#[test]
fn pass_adjacently_tagged_enum() {
    // ["Foo", 123]
    let buf = [146, 163, 70, 111, 111, 123];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    #[serde(tag = "t", content = "c")]
    enum Enum {
        Foo(i32),
        Bar(u32),
    }

    let mut de = Deserializer::new(cur);
    let actual = Deserialize::deserialize(&mut de);

    assert!(actual.is_ok());
    assert_eq!(Enum::Foo(123), actual.unwrap());
}

#[test]
#[should_panic(expected = "assertion failed")]
fn fail_internally_tagged_enum_tuple() {
    // ["Foo", 123]
    let buf = [146, 163, 70, 111, 111, 123];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    #[serde(tag = "t")]
    enum Enum {
        Foo(i32),
        Bar(u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    assert!(actual.is_ok())
}

#[test]
fn pass_internally_tagged_enum_struct() {
    let buf = [130, 161, 116, 163, 70, 111, 111, 165, 118, 97, 108, 117, 101, 123];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    #[serde(tag = "t")]
    enum Enum {
        Foo { value: i32 },
        Bar { value: u32 },
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    assert!(actual.is_ok());
    assert_eq!(Enum::Foo{ value: 123 }, actual.unwrap())

}

#[test]
fn pass_enum_with_one_arg() {
    // The encoded bytearray is: [0, [[1, 2]]].
    let buf = [0x92, 0x0, 0x91, 0x92, 0x01, 0x02];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        V1(Vec<u32>),
        V2,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::V1(vec![1, 2]), actual);
    assert_eq!(buf.len() as u64, de.get_ref().position())
}

#[test]
fn pass_from_slice() {
    let buf = [0x93, 0xa4, 0x4a, 0x6f, 0x68, 0x6e, 0xa5, 0x53, 0x6d, 0x69, 0x74, 0x68, 0x2a];

    #[derive(Debug, PartialEq, Deserialize)]
    struct Person<'a> {
        name: &'a str,
        surname: &'a str,
        age: u8,
    }

    assert_eq!(Person { name: "John", surname: "Smith", age: 42 }, rmps::from_slice(&buf[..]).unwrap());
}
<commit_msg>Fix newtype variant test<commit_after>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;

use std::io::Cursor;

use serde::Deserialize;

use rmps::Deserializer;
use rmps::decode::Error;

#[test]
fn pass_newtype() {
    let buf = [0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct(u32);

    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Struct(42), actual);
}

#[test]
fn pass_tuple_struct() {
    let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Decoded(u32, u32);

    let mut de = Deserializer::new(cur);
    let actual: Decoded = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Decoded(42, 100500), actual);
}

#[test]
fn pass_single_field_struct() {
    let buf = [0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct {
        inner: u32
    };

    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Struct{inner: 42}, actual);
}

#[test]
fn pass_struct() {
    let buf = [0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Decoded {
        id: u32,
        value: u32
    };

    let mut de = Deserializer::new(cur);
    let actual: Decoded = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Decoded { id: 42, value: 100500 }, actual);
}

#[test]
fn pass_struct_from_map() {
    #[derive(Debug, PartialEq, Deserialize)]
    struct Struct {
        et: String,
        le: u8,
        shit: u8,
    }

    let buf = [
        0x83, // 3 (size)
        0xa2, 0x65, 0x74, // "et"
        0xa5, 0x76, 0x6f, 0x69, 0x6c, 0x61, // "voila"
        0xa2, 0x6c, 0x65, // "le"
        0x00, // 0
        0xa4, 0x73, 0x68, 0x69, 0x74, // "shit"
        0x01, // 1
    ];
    let cur = Cursor::new(&buf[..]);

    // It appears no special behavior is needed for deserializing structs encoded as maps.
    let mut de = Deserializer::new(cur);
    let actual: Struct = Deserialize::deserialize(&mut de).unwrap();
    let expected = Struct { et: "voila".into(), le: 0, shit: 1 };

    assert_eq!(expected, actual);
}

#[test]
fn pass_unit_variant() {
    // We expect enums to be encoded as [id, [...]]

    let buf = [0x92, 0x01, 0x90];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B, actual);
    assert_eq!(3, de.get_ref().position());
}

#[test]
fn pass_tuple_enum_with_arg() {
    // The encoded byte-array is: [1, [42]].
    let buf = [0x92, 0x01, 0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B(u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B(42), actual);
    assert_eq!(4, de.get_ref().position())
}

#[test]
fn pass_tuple_enum_with_args() {
    // The encoded bytearray is: [1, [42, 58]].
    let buf = [0x92, 0x01, 0x92, 0x2a, 0x3a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B(u32, u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B(42, 58), actual);
    assert_eq!(5, de.get_ref().position())
}

#[test]
fn fail_enum_sequence_mismatch() {
    // The encoded bytearray is: [1, 2, 100500].
    let buf = [0x93, 0x1, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    match actual.err().unwrap() {
        Error::LengthMismatch(3) => (),
        other => panic!("unexpected result: {:?}", other)
    }
}

#[test]
fn fail_enum_overflow() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    // TODO: Rename to Enum: A, B, C, ...
    enum Enum {
        A,
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    match actual.err().unwrap() {
        Error::Syntax(..) => (),
        other => panic!("unexpected result: {:?}", other)
    }
}

#[test]
fn pass_struct_enum_with_arg() {
    // The encoded bytearray is: [1, [42]].
    let buf = [0x92, 0x01, 0x91, 0x2a];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B { id: u32 },
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B { id: 42 }, actual);
    assert_eq!(4, de.get_ref().position())
}

#[test]
fn pass_newtype_variant() {
    // The encoded bytearray is: [0, ['le message']].
    let buf = [0x92, 0x0, 0x91, 0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    struct Nested(String);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A(Nested),
        B,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::A(Nested("le message".into())), actual);
    assert_eq!(buf.len() as u64, de.get_ref().position())
}

#[cfg(disabled)]  // This test doesn't actually compile anymore
#[test]
fn pass_enum_custom_policy() {
    use std::io::Read;
    use rmp_serde::decode::VariantVisitor;

    // We expect enums to be endoded as id, [...] (without wrapping tuple).

    let buf = [0x01, 0x90];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        A,
        B,
    }

    struct CustomDeserializer<R: Read> {
        inner: Deserializer<R>,
    }

    impl<R: Read> serde::Deserializer for CustomDeserializer<R> {
        type Error = Error;

        fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Error>
            where V: serde::de::Visitor
        {
            self.inner.deserialize(visitor)
        }

        fn deserialize_enum<V>(&mut self, _enum: &str, _variants: &'static [&'static str], mut visitor: V)
            -> Result<V::Value, Error>
            where V: serde::de::EnumVisitor
        {
            visitor.visit(VariantVisitor::new(&mut self.inner))
        }

        forward_to_deserialize! {
            bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string unit seq
            seq_fixed_size bytes map tuple_struct unit_struct struct struct_field
            tuple option newtype_struct ignored_any
        }
    }

    let mut de = CustomDeserializer { inner: Deserializer::new(cur) };
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::B, actual);
    assert_eq!(2, de.inner.get_ref().position());
}

#[test]
fn pass_struct_variant() {
    #[derive(Debug, PartialEq, Deserialize)]
    enum Custom {
        First { data: u32 },
        Second { data: u32 },
    }
    let out_first = vec![0x92, 0x00, 0x91, 0x2a];
    let out_second = vec![0x92, 0x01, 0x91, 0x2a];

    for (expected, out) in vec![(Custom::First{ data: 42 }, out_first), (Custom::Second { data: 42 }, out_second)] {
        let mut de = Deserializer::new(Cursor::new(&out[..]));
        let val: Custom = Deserialize::deserialize(&mut de).unwrap();
        assert_eq!(expected, val);
    }
}

#[test]
fn pass_adjacently_tagged_enum() {
    // ["Foo", 123]
    let buf = [146, 163, 70, 111, 111, 123];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    #[serde(tag = "t", content = "c")]
    enum Enum {
        Foo(i32),
        Bar(u32),
    }

    let mut de = Deserializer::new(cur);
    let actual = Deserialize::deserialize(&mut de);

    assert!(actual.is_ok());
    assert_eq!(Enum::Foo(123), actual.unwrap());
}

#[test]
#[should_panic(expected = "assertion failed")]
fn fail_internally_tagged_enum_tuple() {
    // ["Foo", 123]
    let buf = [146, 163, 70, 111, 111, 123];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    #[serde(tag = "t")]
    enum Enum {
        Foo(i32),
        Bar(u32),
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    assert!(actual.is_ok())
}

#[test]
fn pass_internally_tagged_enum_struct() {
    let buf = [130, 161, 116, 163, 70, 111, 111, 165, 118, 97, 108, 117, 101, 123];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    #[serde(tag = "t")]
    enum Enum {
        Foo { value: i32 },
        Bar { value: u32 },
    }

    let mut de = Deserializer::new(cur);
    let actual: Result<Enum, Error> = Deserialize::deserialize(&mut de);

    assert!(actual.is_ok());
    assert_eq!(Enum::Foo{ value: 123 }, actual.unwrap())

}

#[test]
fn pass_enum_with_one_arg() {
    // The encoded bytearray is: [0, [[1, 2]]].
    let buf = [0x92, 0x0, 0x91, 0x92, 0x01, 0x02];
    let cur = Cursor::new(&buf[..]);

    #[derive(Debug, PartialEq, Deserialize)]
    enum Enum {
        V1(Vec<u32>),
        V2,
    }

    let mut de = Deserializer::new(cur);
    let actual: Enum = Deserialize::deserialize(&mut de).unwrap();

    assert_eq!(Enum::V1(vec![1, 2]), actual);
    assert_eq!(buf.len() as u64, de.get_ref().position())
}

#[test]
fn pass_from_slice() {
    let buf = [0x93, 0xa4, 0x4a, 0x6f, 0x68, 0x6e, 0xa5, 0x53, 0x6d, 0x69, 0x74, 0x68, 0x2a];

    #[derive(Debug, PartialEq, Deserialize)]
    struct Person<'a> {
        name: &'a str,
        surname: &'a str,
        age: u8,
    }

    assert_eq!(Person { name: "John", surname: "Smith", age: 42 }, rmps::from_slice(&buf[..]).unwrap());
}
<|endoftext|>


<commit_before>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;

use serde::Serialize;
use rmps::Serializer;
use rmps::encode::{Ext, UnderlyingWrite};

#[test]
fn pass_unit_struct() {
    #[derive(Serialize)]
    struct Unit;

    let mut buf = Vec::new();
    Unit.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [].
    assert_eq!(vec![0x90], buf);
}

#[test]
fn pass_unit_variant() {
    #[derive(Serialize)]
    enum Enum {
        V1,
        V2,
    }

    let mut buf = Vec::new();
    Enum::V1.serialize(&mut Serializer::new(&mut buf)).unwrap();
    Enum::V2.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [0, []] [1, []].
    assert_eq!(vec![0x92, 0x00, 0x90, 0x92, 0x01, 0x90], buf);
}

#[test]
fn pass_newtype_struct() {
    #[derive(Serialize)]
    struct Struct(u64);

    let val = Struct(42);
    let mut buf = Vec::new();
    val.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [42].
    assert_eq!(vec![0x91, 0x2a], buf);
}

#[test]
fn pass_newtype_variant() {
    #[derive(Serialize)]
    enum Enum {
        V1,
        V2(u64),
    }

    let mut buf = Vec::new();
    Enum::V1.serialize(&mut Serializer::new(&mut buf)).unwrap();
    Enum::V2(42).serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [0, []] [1, [42]].
    assert_eq!(vec![0x92, 0x00, 0x90, 0x92, 0x01, 0x91, 0x2a], buf);
}

#[test]
fn pass_tuple_struct() {
    #[derive(Serialize)]
    struct Struct(u32, u64);

    let val = Struct(42, 100500);
    let mut buf = Vec::new();
    val.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [42, 100500].
    assert_eq!(vec![0x92, 0x2a, 0xce, 0x00, 0x01, 0x88, 0x94], buf);
}

#[test]
fn pass_tuple_variant() {
    #[derive(Serialize)]
    enum Enum {
        V1,
        V2(u32, u64),
    }

    let mut buf = Vec::new();
    Enum::V1.serialize(&mut Serializer::new(&mut buf)).unwrap();
    Enum::V2(42, 100500).serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [0, []] [2, [42, 100500]].
    assert_eq!(vec![0x92, 0x00, 0x90, 0x92, 0x01, 0x92, 0x2a, 0xce, 0x00, 0x01, 0x88, 0x94], buf);
}

#[test]
fn pass_struct() {
    #[derive(Serialize)]
    struct Struct {
        f1: u32,
        f2: u32,
    }

    let val = Struct {
        f1: 42,
        f2: 100500,
    };
    let mut buf = Vec::new();
    val.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [42, 100500].
    assert_eq!(vec![0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94], buf);
}

#[test]
fn serialize_struct_variant() {
    #[derive(Serialize)]
    enum Enum {
        V1 {
            f1: u32,
        },
        V2 {
            f1: u32,
        },
    }

    let mut buf = Vec::new();
    Enum::V1 { f1: 42 }.serialize(&mut Serializer::new(&mut buf)).unwrap();
    Enum::V2 { f1: 43 }.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [0, [42]] [1, [43]].
    assert_eq!(vec![0x92, 0x00, 0x91, 0x2a, 0x92, 0x01, 0x91, 0x2b], buf);
}

//#[test]
//fn pass_struct_as_map() {
//    use std::io::Write;
//    use rmp::Marker;
//    use rmp::encode::{ValueWriteError, write_map_len, write_str};
//    use rmps::encode::VariantWriter;
//
//    #[derive(Serialize)]
//    struct Dog {
//        name: String,
//        age: u16,
//    }
//
//    let dog = Dog {
//        name: "Bobby".into(),
//        age: 8,
//    };
//
//    struct StructMapWriter;
//
//    impl VariantWriter for StructMapWriter {
//        fn write_struct_len<W: Write>(&self, wr: &mut W, len: u32) ->
//            Result<Marker, ValueWriteError>
//        {
//            write_map_len(wr, len)
//        }
//
//        fn write_field_name<W: Write>(&self, wr: &mut W, key: &str) ->
//            Result<(), ValueWriteError>
//        {
//            write_str(wr, key)
//        }
//    }
//
//    let mut se = Serializer::with(Vec::new(), StructMapWriter);
//    dog.serialize(&mut se).unwrap();
//
//    // Expect: {"name": "Bobby", "age": 8}.
//    assert_eq!(vec![0x82, 0xa4, 0x6e, 0x61, 0x6d, 0x65, 0xa5, 0x42, 0x6f, 0x62, 0x62, 0x79, 0xa3, 0x61, 0x67, 0x65, 0x08],
//        se.into_inner());
//}

#[test]
fn pass_struct_as_map_using_ext() {
    #[derive(Serialize)]
    struct Dog<'a> {
        name: &'a str,
        age: u16,
    }

    let dog = Dog {
        name: "Bobby",
        age: 8,
    };

    let mut se = Serializer::new(Vec::new())
        .with_struct_map();

    dog.serialize(&mut se).unwrap();

    // Expect: {"name": "Bobby", "age": 8}.
    assert_eq!(vec![0x82, 0xa4, 0x6e, 0x61, 0x6d, 0x65, 0xa5, 0x42, 0x6f, 0x62, 0x62, 0x79, 0xa3, 0x61, 0x67, 0x65, 0x08],
               se.into_inner());
}

#[test]
fn pass_struct_as_tuple_using_double_ext() {
    #[derive(Serialize)]
    struct Dog<'a> {
        name: &'a str,
        age: u16,
    }

    let dog = Dog {
        name: "Bobby",
        age: 8,
    };

    let mut se = Serializer::new(Vec::new())
        .with_struct_map()
        .with_struct_tuple();

    dog.serialize(&mut se).unwrap();

    assert_eq!(vec![0x92, 0xa5, 0x42, 0x6f, 0x62, 0x62, 0x79, 0x08],
               se.into_inner());
}

#[test]
fn pass_struct_as_map_using_triple_ext() {
    #[derive(Serialize)]
    struct Dog<'a> {
        name: &'a str,
        age: u16,
    }

    let dog = Dog {
        name: "Bobby",
        age: 8,
    };

    let mut se = Serializer::new(Vec::new())
        .with_struct_map()
        .with_struct_tuple()
        .with_struct_map();

    dog.serialize(&mut se).unwrap();

    // Expect: {"name": "Bobby", "age": 8}.
    assert_eq!(vec![0x82, 0xa4, 0x6e, 0x61, 0x6d, 0x65, 0xa5, 0x42, 0x6f, 0x62, 0x62, 0x79, 0xa3, 0x61, 0x67, 0x65, 0x08],
               se.into_inner());
}

#[test]
fn pass_struct_as_map_using_triple_ext_sequently() {
    #[derive(Serialize)]
    struct Dog<'a> {
        name: &'a str,
        age: u16,
    }

    let dog = Dog {
        name: "Bobby",
        age: 8,
    };

    let mut se = Serializer::new(Vec::new())
        .with_struct_map()
        .with_struct_tuple()
        .with_struct_map()
        .with_struct_map()
        .with_struct_map()
        .with_struct_map();

    dog.serialize(&mut se).unwrap();

    // Expect: {"name": "Bobby", "age": 8}.
    assert_eq!(vec![0x82, 0xa4, 0x6e, 0x61, 0x6d, 0x65, 0xa5, 0x42, 0x6f, 0x62, 0x62, 0x79, 0xa3, 0x61, 0x67, 0x65, 0x08],
               se.into_inner());
}
<commit_msg>chore: remove dead test<commit_after>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;

use serde::Serialize;
use rmps::Serializer;
use rmps::encode::{Ext, UnderlyingWrite};

#[test]
fn pass_unit_struct() {
    #[derive(Serialize)]
    struct Unit;

    let mut buf = Vec::new();
    Unit.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [].
    assert_eq!(vec![0x90], buf);
}

#[test]
fn pass_unit_variant() {
    #[derive(Serialize)]
    enum Enum {
        V1,
        V2,
    }

    let mut buf = Vec::new();
    Enum::V1.serialize(&mut Serializer::new(&mut buf)).unwrap();
    Enum::V2.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [0, []] [1, []].
    assert_eq!(vec![0x92, 0x00, 0x90, 0x92, 0x01, 0x90], buf);
}

#[test]
fn pass_newtype_struct() {
    #[derive(Serialize)]
    struct Struct(u64);

    let val = Struct(42);
    let mut buf = Vec::new();
    val.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [42].
    assert_eq!(vec![0x91, 0x2a], buf);
}

#[test]
fn pass_newtype_variant() {
    #[derive(Serialize)]
    enum Enum {
        V1,
        V2(u64),
    }

    let mut buf = Vec::new();
    Enum::V1.serialize(&mut Serializer::new(&mut buf)).unwrap();
    Enum::V2(42).serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [0, []] [1, [42]].
    assert_eq!(vec![0x92, 0x00, 0x90, 0x92, 0x01, 0x91, 0x2a], buf);
}

#[test]
fn pass_tuple_struct() {
    #[derive(Serialize)]
    struct Struct(u32, u64);

    let val = Struct(42, 100500);
    let mut buf = Vec::new();
    val.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [42, 100500].
    assert_eq!(vec![0x92, 0x2a, 0xce, 0x00, 0x01, 0x88, 0x94], buf);
}

#[test]
fn pass_tuple_variant() {
    #[derive(Serialize)]
    enum Enum {
        V1,
        V2(u32, u64),
    }

    let mut buf = Vec::new();
    Enum::V1.serialize(&mut Serializer::new(&mut buf)).unwrap();
    Enum::V2(42, 100500).serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [0, []] [2, [42, 100500]].
    assert_eq!(vec![0x92, 0x00, 0x90, 0x92, 0x01, 0x92, 0x2a, 0xce, 0x00, 0x01, 0x88, 0x94], buf);
}

#[test]
fn pass_struct() {
    #[derive(Serialize)]
    struct Struct {
        f1: u32,
        f2: u32,
    }

    let val = Struct {
        f1: 42,
        f2: 100500,
    };
    let mut buf = Vec::new();
    val.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [42, 100500].
    assert_eq!(vec![0x92, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94], buf);
}

#[test]
fn serialize_struct_variant() {
    #[derive(Serialize)]
    enum Enum {
        V1 {
            f1: u32,
        },
        V2 {
            f1: u32,
        },
    }

    let mut buf = Vec::new();
    Enum::V1 { f1: 42 }.serialize(&mut Serializer::new(&mut buf)).unwrap();
    Enum::V2 { f1: 43 }.serialize(&mut Serializer::new(&mut buf)).unwrap();

    // Expect: [0, [42]] [1, [43]].
    assert_eq!(vec![0x92, 0x00, 0x91, 0x2a, 0x92, 0x01, 0x91, 0x2b], buf);
}

#[test]
fn pass_struct_as_map_using_ext() {
    #[derive(Serialize)]
    struct Dog<'a> {
        name: &'a str,
        age: u16,
    }

    let dog = Dog {
        name: "Bobby",
        age: 8,
    };

    let mut se = Serializer::new(Vec::new())
        .with_struct_map();

    dog.serialize(&mut se).unwrap();

    // Expect: {"name": "Bobby", "age": 8}.
    assert_eq!(vec![0x82, 0xa4, 0x6e, 0x61, 0x6d, 0x65, 0xa5, 0x42, 0x6f, 0x62, 0x62, 0x79, 0xa3, 0x61, 0x67, 0x65, 0x08],
               se.into_inner());
}

#[test]
fn pass_struct_as_tuple_using_double_ext() {
    #[derive(Serialize)]
    struct Dog<'a> {
        name: &'a str,
        age: u16,
    }

    let dog = Dog {
        name: "Bobby",
        age: 8,
    };

    let mut se = Serializer::new(Vec::new())
        .with_struct_map()
        .with_struct_tuple();

    dog.serialize(&mut se).unwrap();

    assert_eq!(vec![0x92, 0xa5, 0x42, 0x6f, 0x62, 0x62, 0x79, 0x08],
               se.into_inner());
}

#[test]
fn pass_struct_as_map_using_triple_ext() {
    #[derive(Serialize)]
    struct Dog<'a> {
        name: &'a str,
        age: u16,
    }

    let dog = Dog {
        name: "Bobby",
        age: 8,
    };

    let mut se = Serializer::new(Vec::new())
        .with_struct_map()
        .with_struct_tuple()
        .with_struct_map();

    dog.serialize(&mut se).unwrap();

    // Expect: {"name": "Bobby", "age": 8}.
    assert_eq!(vec![0x82, 0xa4, 0x6e, 0x61, 0x6d, 0x65, 0xa5, 0x42, 0x6f, 0x62, 0x62, 0x79, 0xa3, 0x61, 0x67, 0x65, 0x08],
               se.into_inner());
}

#[test]
fn pass_struct_as_map_using_triple_ext_sequently() {
    #[derive(Serialize)]
    struct Dog<'a> {
        name: &'a str,
        age: u16,
    }

    let dog = Dog {
        name: "Bobby",
        age: 8,
    };

    let mut se = Serializer::new(Vec::new())
        .with_struct_map()
        .with_struct_tuple()
        .with_struct_map()
        .with_struct_map()
        .with_struct_map()
        .with_struct_map();

    dog.serialize(&mut se).unwrap();

    // Expect: {"name": "Bobby", "age": 8}.
    assert_eq!(vec![0x82, 0xa4, 0x6e, 0x61, 0x6d, 0x65, 0xa5, 0x42, 0x6f, 0x62, 0x62, 0x79, 0xa3, 0x61, 0x67, 0x65, 0x08],
               se.into_inner());
}
<|endoftext|>


<commit_before>use crate::{convert, ops};

/// Used to tell an operation whether it should exit early or go on as usual.
///
/// This is used when exposing things (like graph traversals or visitors) where
/// you want the user to be able to choose whether to exit early.
/// Having the enum makes it clearer -- no more wondering "wait, what did `false`
/// mean again?" -- and allows including a value.
///
/// # Examples
///
/// Early-exiting from [`Iterator::try_for_each`]:
/// ```
/// use std::ops::ControlFlow;
///
/// let r = (2..100).try_for_each(|x| {
///     if 403 % x == 0 {
///         return ControlFlow::Break(x)
///     }
///
///     ControlFlow::Continue(())
/// });
/// assert_eq!(r, ControlFlow::Break(13));
/// ```
///
/// A basic tree traversal:
/// ```no_run
/// use std::ops::ControlFlow;
///
/// pub struct TreeNode<T> {
///     value: T,
///     left: Option<Box<TreeNode<T>>>,
///     right: Option<Box<TreeNode<T>>>,
/// }
///
/// impl<T> TreeNode<T> {
///     pub fn traverse_inorder<B>(&self, mut f: impl FnMut(&T) -> ControlFlow<B>) -> ControlFlow<B> {
///         if let Some(left) = &self.left {
///             left.traverse_inorder(&mut f)?;
///         }
///         f(&self.value)?;
///         if let Some(right) = &self.right {
///             right.traverse_inorder(&mut f)?;
///         }
///         ControlFlow::Continue(())
///     }
/// }
/// ```
#[stable(feature = "control_flow_enum_type", since = "1.55.0")]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ControlFlow<B, C = ()> {
    /// Move on to the next phase of the operation as normal.
    #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
    #[lang = "Continue"]
    Continue(C),
    /// Exit the operation without running subsequent phases.
    #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
    #[lang = "Break"]
    Break(B),
    // Yes, the order of the variants doesn't match the type parameters.
    // They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
    // is a no-op conversion in the `Try` implementation.
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<B, C> ops::Try for ControlFlow<B, C> {
    type Output = C;
    type Residual = ControlFlow<B, convert::Infallible>;

    #[inline]
    fn from_output(output: Self::Output) -> Self {
        ControlFlow::Continue(output)
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            ControlFlow::Continue(c) => ControlFlow::Continue(c),
            ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<B, C> ops::FromResidual for ControlFlow<B, C> {
    #[inline]
    fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
        match residual {
            ControlFlow::Break(b) => ControlFlow::Break(b),
        }
    }
}

impl<B, C> ControlFlow<B, C> {
    /// Returns `true` if this is a `Break` variant.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// assert!(ControlFlow::<i32, String>::Break(3).is_break());
    /// assert!(!ControlFlow::<String, i32>::Continue(3).is_break());
    /// ```
    #[inline]
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub fn is_break(&self) -> bool {
        matches!(*self, ControlFlow::Break(_))
    }

    /// Returns `true` if this is a `Continue` variant.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// assert!(!ControlFlow::<i32, String>::Break(3).is_continue());
    /// assert!(ControlFlow::<String, i32>::Continue(3).is_continue());
    /// ```
    #[inline]
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub fn is_continue(&self) -> bool {
        matches!(*self, ControlFlow::Continue(_))
    }

    /// Converts the `ControlFlow` into an `Option` which is `Some` if the
    /// `ControlFlow` was `Break` and `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// assert_eq!(ControlFlow::<i32, String>::Break(3).break_value(), Some(3));
    /// assert_eq!(ControlFlow::<String, i32>::Continue(3).break_value(), None);
    /// ```
    #[inline]
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub fn break_value(self) -> Option<B> {
        match self {
            ControlFlow::Continue(..) => None,
            ControlFlow::Break(x) => Some(x),
        }
    }

    /// Maps `ControlFlow<B, C>` to `ControlFlow<T, C>` by applying a function
    /// to the break value in case it exists.
    #[inline]
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub fn map_break<T, F>(self, f: F) -> ControlFlow<T, C>
    where
        F: FnOnce(B) -> T,
    {
        match self {
            ControlFlow::Continue(x) => ControlFlow::Continue(x),
            ControlFlow::Break(x) => ControlFlow::Break(f(x)),
        }
    }
}

/// These are used only as part of implementing the iterator adapters.
/// They have mediocre names and non-obvious semantics, so aren't
/// currently on a path to potential stabilization.
impl<R: ops::Try> ControlFlow<R, R::Output> {
    /// Create a `ControlFlow` from any type implementing `Try`.
    #[inline]
    pub(crate) fn from_try(r: R) -> Self {
        match R::branch(r) {
            ControlFlow::Continue(v) => ControlFlow::Continue(v),
            ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)),
        }
    }

    /// Convert a `ControlFlow` into any type implementing `Try`;
    #[inline]
    pub(crate) fn into_try(self) -> R {
        match self {
            ControlFlow::Continue(v) => R::from_output(v),
            ControlFlow::Break(v) => v,
        }
    }
}

impl<B> ControlFlow<B, ()> {
    /// It's frequently the case that there's no value needed with `Continue`,
    /// so this provides a way to avoid typing `(())`, if you prefer it.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// let mut partial_sum = 0;
    /// let last_used = (1..10).chain(20..25).try_for_each(|x| {
    ///     partial_sum += x;
    ///     if partial_sum > 100 { ControlFlow::Break(x) }
    ///     else { ControlFlow::CONTINUE }
    /// });
    /// assert_eq!(last_used.break_value(), Some(22));
    /// ```
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub const CONTINUE: Self = ControlFlow::Continue(());
}

impl<C> ControlFlow<(), C> {
    /// APIs like `try_for_each` don't need values with `Break`,
    /// so this provides a way to avoid typing `(())`, if you prefer it.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// let mut partial_sum = 0;
    /// (1..10).chain(20..25).try_for_each(|x| {
    ///     if partial_sum > 100 { ControlFlow::BREAK }
    ///     else { partial_sum += x; ControlFlow::CONTINUE }
    /// });
    /// assert_eq!(partial_sum, 108);
    /// ```
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub const BREAK: Self = ControlFlow::Break(());
}
<commit_msg>Update control_flow.rs<commit_after>use crate::{convert, ops};

/// Used to tell an operation whether it should exit early or go on as usual.
///
/// This is used when exposing things (like graph traversals or visitors) where
/// you want the user to be able to choose whether to exit early.
/// Having the enum makes it clearer -- no more wondering "wait, what did `false`
/// mean again?" -- and allows including a value.
///
/// # Examples
///
/// Early-exiting from [`Iterator::try_for_each`]:
/// ```
/// use std::ops::ControlFlow;
///
/// let r = (2..100).try_for_each(|x| {
///     if 403 % x == 0 {
///         return ControlFlow::Break(x)
///     }
///
///     ControlFlow::Continue(())
/// });
/// assert_eq!(r, ControlFlow::Break(13));
/// ```
///
/// A basic tree traversal:
/// ```no_run
/// use std::ops::ControlFlow;
///
/// pub struct TreeNode<T> {
///     value: T,
///     left: Option<Box<TreeNode<T>>>,
///     right: Option<Box<TreeNode<T>>>,
/// }
///
/// impl<T> TreeNode<T> {
///     pub fn traverse_inorder<B>(&self, f: &impl Fn(&T) -> ControlFlow<B>) -> ControlFlow<B> {
///         if let Some(left) = &self.left {
///             left.traverse_inorder(f)?;
///         }
///         f(&self.value)?;
///         if let Some(right) = &self.right {
///             right.traverse_inorder(f)?;
///         }
///         ControlFlow::Continue(())
///     }
/// }
///
/// let node = TreeNode {
///     value: 0,
///     left: Some(Box::new(TreeNode {
///         value: 1,
///         left: None,
///         right: None
///     })),
///     right: Some(Box::new(TreeNode {
///         value: 2,
///         left: None,
///         right: None
///     }))
/// };
///
/// node.traverse_inorder(& |val| {
///     println!("{}", val);
///     if *val <= 0 {
///         ControlFlow::Break(())
///     } else {
///         ControlFlow::Continue(())
///     }
/// });
/// ```
#[stable(feature = "control_flow_enum_type", since = "1.55.0")]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ControlFlow<B, C = ()> {
    /// Move on to the next phase of the operation as normal.
    #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
    #[lang = "Continue"]
    Continue(C),
    /// Exit the operation without running subsequent phases.
    #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
    #[lang = "Break"]
    Break(B),
    // Yes, the order of the variants doesn't match the type parameters.
    // They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
    // is a no-op conversion in the `Try` implementation.
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<B, C> ops::Try for ControlFlow<B, C> {
    type Output = C;
    type Residual = ControlFlow<B, convert::Infallible>;

    #[inline]
    fn from_output(output: Self::Output) -> Self {
        ControlFlow::Continue(output)
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            ControlFlow::Continue(c) => ControlFlow::Continue(c),
            ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<B, C> ops::FromResidual for ControlFlow<B, C> {
    #[inline]
    fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
        match residual {
            ControlFlow::Break(b) => ControlFlow::Break(b),
        }
    }
}

impl<B, C> ControlFlow<B, C> {
    /// Returns `true` if this is a `Break` variant.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// assert!(ControlFlow::<i32, String>::Break(3).is_break());
    /// assert!(!ControlFlow::<String, i32>::Continue(3).is_break());
    /// ```
    #[inline]
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub fn is_break(&self) -> bool {
        matches!(*self, ControlFlow::Break(_))
    }

    /// Returns `true` if this is a `Continue` variant.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// assert!(!ControlFlow::<i32, String>::Break(3).is_continue());
    /// assert!(ControlFlow::<String, i32>::Continue(3).is_continue());
    /// ```
    #[inline]
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub fn is_continue(&self) -> bool {
        matches!(*self, ControlFlow::Continue(_))
    }

    /// Converts the `ControlFlow` into an `Option` which is `Some` if the
    /// `ControlFlow` was `Break` and `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// assert_eq!(ControlFlow::<i32, String>::Break(3).break_value(), Some(3));
    /// assert_eq!(ControlFlow::<String, i32>::Continue(3).break_value(), None);
    /// ```
    #[inline]
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub fn break_value(self) -> Option<B> {
        match self {
            ControlFlow::Continue(..) => None,
            ControlFlow::Break(x) => Some(x),
        }
    }

    /// Maps `ControlFlow<B, C>` to `ControlFlow<T, C>` by applying a function
    /// to the break value in case it exists.
    #[inline]
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub fn map_break<T, F>(self, f: F) -> ControlFlow<T, C>
    where
        F: FnOnce(B) -> T,
    {
        match self {
            ControlFlow::Continue(x) => ControlFlow::Continue(x),
            ControlFlow::Break(x) => ControlFlow::Break(f(x)),
        }
    }
}

/// These are used only as part of implementing the iterator adapters.
/// They have mediocre names and non-obvious semantics, so aren't
/// currently on a path to potential stabilization.
impl<R: ops::Try> ControlFlow<R, R::Output> {
    /// Create a `ControlFlow` from any type implementing `Try`.
    #[inline]
    pub(crate) fn from_try(r: R) -> Self {
        match R::branch(r) {
            ControlFlow::Continue(v) => ControlFlow::Continue(v),
            ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)),
        }
    }

    /// Convert a `ControlFlow` into any type implementing `Try`;
    #[inline]
    pub(crate) fn into_try(self) -> R {
        match self {
            ControlFlow::Continue(v) => R::from_output(v),
            ControlFlow::Break(v) => v,
        }
    }
}

impl<B> ControlFlow<B, ()> {
    /// It's frequently the case that there's no value needed with `Continue`,
    /// so this provides a way to avoid typing `(())`, if you prefer it.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// let mut partial_sum = 0;
    /// let last_used = (1..10).chain(20..25).try_for_each(|x| {
    ///     partial_sum += x;
    ///     if partial_sum > 100 { ControlFlow::Break(x) }
    ///     else { ControlFlow::CONTINUE }
    /// });
    /// assert_eq!(last_used.break_value(), Some(22));
    /// ```
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub const CONTINUE: Self = ControlFlow::Continue(());
}

impl<C> ControlFlow<(), C> {
    /// APIs like `try_for_each` don't need values with `Break`,
    /// so this provides a way to avoid typing `(())`, if you prefer it.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(control_flow_enum)]
    /// use std::ops::ControlFlow;
    ///
    /// let mut partial_sum = 0;
    /// (1..10).chain(20..25).try_for_each(|x| {
    ///     if partial_sum > 100 { ControlFlow::BREAK }
    ///     else { partial_sum += x; ControlFlow::CONTINUE }
    /// });
    /// assert_eq!(partial_sum, 108);
    /// ```
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    pub const BREAK: Self = ControlFlow::Break(());
}
<|endoftext|>