<commit_before>
use std::collections::BTreeMap;
use std::mem;

use assembler::data_range::DataRange;
use assembler::directive::Directive;
use assembler::instruction::Instruction;
use assembler::parser::Node;
use assembler::source_file_location::SourceFileLocation;
use assembler::u12::*;

// MARK: - Constants

lazy_static! {
  static ref BYTES_PER_INSTRUCTION: U12 = U12::from(2);
}

// MARK: - Helper Methods

fn format_semantic_error<'a>(location: &'a SourceFileLocation, description: String) -> String {
  format!("{}: error: {}", location, description)
}

// MARK: - Pass 1: Define Labels

/**
 In a 2-pass assembler, the first pass is used to resolve the address of all labels
 declared in the assembly. This involves walking the ASL, computing the size of instructions
 and directives in the output stream and using that information to establish the label-address map.
 @param syntax_list The un-filtered syntax list.
 @return The map of labels to their corresponding addresses on success or a string describing
     the reason the first pass failed.
 */
fn define_labels<'a>(syntax_list: &Vec<Node<'a>>) -> Result<BTreeMap<&'a str, U12>, String> {
  let mut label_address_map = BTreeMap::new();
  let mut current_address = U12::zero();

  // Define all labels and process '.org' directives.
  for node in syntax_list.iter() {
    match *node {
      Node::Directive(ref data) => {
        // Validate the directive and that the arguments match the identifier.
        let directive = match Directive::from_identifier_and_parameters(data.identifier, &data.arguments) {
           Ok(result) => result,
          Err(reason) => return Err(format_semantic_error(&data.location, reason))
        };

        // Ensure the directive is not too large to emit.
        let directive_size = match directive.size().as_u12() {
          Some(size) => size,
          None => {
            let reason = format!("Directive ({}) size {} exceeds 4096 bytes.", directive, directive.size());
            return Err(format_semantic_error(&data.location, reason));
          }
        };

        // Offset the current address by the size of the directive being processed.
        current_address = match current_address.checked_add(directive_size) {
          Some(sum) => sum,
          None => {
            let reason = format!("Directive ({}) would cause the 12-bit address counter to overflow.", directive);
            return Err(format_semantic_error(&data.location, reason));
          }
        };

        // The origin directive changes the current address.
        if let Directive::Org(address) = directive {
          current_address = address;
        }
      }

      Node::Label(ref data) => {
        // Map the label to the current address and remove from the ASL.
        if label_address_map.contains_key(&data.identifier) {
          let reason = format!("Attempted re-definition of label {}.", data.identifier);
          return Err(format_semantic_error(&data.location, reason));
        } else {
          label_address_map.insert(data.identifier, current_address);
        }
      }

      Node::Instruction(ref data) => {
        // All Chip8 instructions are the same length.
        current_address = match current_address.checked_add(*BYTES_PER_INSTRUCTION) {
          Some(sum) => sum,
          None => {
            let reason = format!("Instruction would cause address counter to overflow $FFF.");
            return Err(format_semantic_error(&data.location, reason));
          }
        };
      }
    }
  }

  // Semantic analysis for directives and labels is complete.
  Ok(label_address_map)
}

// MARK: - Pass 2: Emit Bytes

fn emit_data_ranges<'a>(syntax_list: Vec<Node<'a>>, label_address_map: &BTreeMap<&'a str, U12>) -> Result<Vec<DataRange>, String> {
  let mut data_ranges = Vec::new();
  let mut current_range = DataRange::new(U12::zero());

  for node in syntax_list {
    match node {

      Node::Directive(data) => {
        match Directive::from_identifier_and_parameters(data.identifier, &data.arguments).unwrap() {

          // Process the origin directive to build a new data range.
          Directive::Org(address) => {
            let new_range = DataRange::new(address);
            let previous_range = mem::replace(&mut current_range, new_range);
            if previous_range.len() > 0 {
              data_ranges.push(previous_range);
            }
          }

          // Emit the directive into the range.
          directive @ _ => {
            assert_eq!(current_range.append(directive.into_vec().as_slice()), true);
          }

        }
      }

      Node::Instruction(data) => {
        // Verify the semantics and append the instruction to the output buffer.
        match Instruction::from_mnemonic_and_parameters(data.mnemonic, &data.fields, label_address_map) {
          Ok(instruction) => {
            assert_eq!(current_range.append(instruction.into_vec().as_slice()), true);
          }
          Err(reason) => {
            return Err(format_semantic_error(&data.location, reason));
          }
        }
      }

      Node::Label(_) => {
        // Processed in Pass 1.
      }

    }
  }

  // Push the last range into the list.
  data_ranges.push(current_range);
  Ok(data_ranges)
}

// MARK: - Public API

/**
 Analyze the ASL for the assembly and convert it into an output byte stream.
 */
pub fn assemble<'a>(syntax_list: Vec<Node<'a>>) -> Result<Vec<DataRange>, String> {
  let label_address_map = try!(define_labels(&syntax_list));
  emit_data_ranges(syntax_list, &label_address_map)
}

// MARK: - Tests

#[cfg(test)]
mod tests {

  use assembler::parser::*;
  use assembler::source_file_location::SourceFileLocation;
  use assembler::u12::*;

  use super::define_labels;

  // MARK: - Helpers

  /// Creates a Label type node with associated data at location "-:seq:1-name.len()".
  fn make_label_node<'a>(seq: usize, name: &'a str) -> Node<'a> {
    Node::Label (
      LabelData {
        location: SourceFileLocation::new("-", seq, 1, name.len()),
        identifier: name
      }
    )
  }

  /// Creates a Directive type node with associated data at location "-:seq:2-name.len()+1".
  fn make_directive_node<'a>(seq: usize, name: &'a str, args: Vec<Literal<'a>>) -> Node<'a> {
    Node::Directive (
      DirectiveData {
        location: SourceFileLocation::new("-", seq, 2, name.len()),
        identifier: name,
        arguments: args
      }
    )
  }

  /// Creates an Instruction type node with associated data at location "-:seq:1-name.len()".
  fn make_instruction_node<'a>(seq: usize, name: &'a str, fields: Vec<InstructionField<'a>>) -> Node<'a> {
    Node::Instruction (
      InstructionData {
        location: SourceFileLocation::new("-", seq, 1, name.len()),
        mnemonic: name,
        fields: fields
      }
    )
  }

  // MARK: - Pass 1 Tests

  #[test]
  fn test_define_labels() {
    let program = vec![
      make_directive_node   (1, "org", vec![Literal::Numeric(0x100)]),
      make_label_node       (2, "label1"),
      make_directive_node   (3, "db", vec![Literal::Numeric(0xFF)]),
      make_label_node       (4, "label2"),
      make_instruction_node (5, "trap", vec![]),
      make_label_node       (6, "label3"),
    ];

    let result = define_labels(&program);

    // Assert that semantic analysis passed.
    if let Err(reason) = result {
      assert!(false, "Unexpected failure in assembler pass 1: {}", reason);
      return;
    }

    // Verify that the
    if let Ok(label_map) = result {
      assert_eq!(label_map.len(), 3);
      assert_eq!(label_map.get("label1").unwrap(), &(0x100.as_u12().unwrap()));
      assert_eq!(label_map.get("label2").unwrap(), &(0x101.as_u12().unwrap()));
      assert_eq!(label_map.get("label3").unwrap(), &(0x103.as_u12().unwrap()));
    }
  }

  #[test]
  fn test_define_labels_does_semantic_analysis_on_org() {
    let program = vec![
      make_directive_node(1, "org", vec![])
    ];

    let result = define_labels(&program);
    assert_eq!(result, Err(String::from("-:1:2-4: error: Incorrect number of parameters (0) for directive .org, expecting 1.")));
  }

  #[test]
  fn test_define_labels_does_semantic_analysis_on_db() {
    let program = vec![
      make_directive_node(1, "db", vec![])
    ];

    let result = define_labels(&program);
    assert_eq!(result, Err(String::from("-:1:2-3: error: Incorrect number of parameters (0) for directive .db, expecting 1 or more.")));
  }

  #[test]
  fn test_define_labels_fails_on_redefinition() {
    let program = vec![
      make_label_node(1, "L1"),
      make_label_node(2, "L1"),
    ];

    let result = define_labels(&program);
    assert_eq!(result, Err(String::from("-:2:1-2: error: Attempted re-definition of label L1.")));
  }

}
<commit_msg>Ensure the last data range is only pushed if non-empty.<commit_after>
use std::collections::BTreeMap;
use std::mem;

use assembler::data_range::DataRange;
use assembler::directive::Directive;
use assembler::instruction::Instruction;
use assembler::parser::Node;
use assembler::source_file_location::SourceFileLocation;
use assembler::u12::*;

// MARK: - Constants

lazy_static! {
  static ref BYTES_PER_INSTRUCTION: U12 = U12::from(2);
}

// MARK: - Helper Methods

fn format_semantic_error<'a>(location: &'a SourceFileLocation, description: String) -> String {
  format!("{}: error: {}", location, description)
}

// MARK: - Pass 1: Define Labels

/**
 In a 2-pass assembler, the first pass is used to resolve the address of all labels
 declared in the assembly. This involves walking the ASL, computing the size of instructions
 and directives in the output stream and using that information to establish the label-address map.
 @param syntax_list The un-filtered syntax list.
 @return The map of labels to their corresponding addresses on success or a string describing
     the reason the first pass failed.
 */
fn define_labels<'a>(syntax_list: &Vec<Node<'a>>) -> Result<BTreeMap<&'a str, U12>, String> {
  let mut label_address_map = BTreeMap::new();
  let mut current_address = U12::zero();

  // Define all labels and process '.org' directives.
  for node in syntax_list.iter() {
    match *node {
      Node::Directive(ref data) => {
        // Validate the directive and that the arguments match the identifier.
        let directive = match Directive::from_identifier_and_parameters(data.identifier, &data.arguments) {
           Ok(result) => result,
          Err(reason) => return Err(format_semantic_error(&data.location, reason))
        };

        // Ensure the directive is not too large to emit.
        let directive_size = match directive.size().as_u12() {
          Some(size) => size,
          None => {
            let reason = format!("Directive ({}) size {} exceeds 4096 bytes.", directive, directive.size());
            return Err(format_semantic_error(&data.location, reason));
          }
        };

        // Offset the current address by the size of the directive being processed.
        current_address = match current_address.checked_add(directive_size) {
          Some(sum) => sum,
          None => {
            let reason = format!("Directive ({}) would cause the 12-bit address counter to overflow.", directive);
            return Err(format_semantic_error(&data.location, reason));
          }
        };

        // The origin directive changes the current address.
        if let Directive::Org(address) = directive {
          current_address = address;
        }
      }

      Node::Label(ref data) => {
        // Map the label to the current address and remove from the ASL.
        if label_address_map.contains_key(&data.identifier) {
          let reason = format!("Attempted re-definition of label {}.", data.identifier);
          return Err(format_semantic_error(&data.location, reason));
        } else {
          label_address_map.insert(data.identifier, current_address);
        }
      }

      Node::Instruction(ref data) => {
        // All Chip8 instructions are the same length.
        current_address = match current_address.checked_add(*BYTES_PER_INSTRUCTION) {
          Some(sum) => sum,
          None => {
            let reason = format!("Instruction would cause address counter to overflow $FFF.");
            return Err(format_semantic_error(&data.location, reason));
          }
        };
      }
    }
  }

  // Semantic analysis for directives and labels is complete.
  Ok(label_address_map)
}

// MARK: - Pass 2: Emit Bytes

fn emit_data_ranges<'a>(syntax_list: Vec<Node<'a>>, label_address_map: &BTreeMap<&'a str, U12>) -> Result<Vec<DataRange>, String> {
  let mut data_ranges = Vec::new();
  let mut current_range = DataRange::new(U12::zero());

  for node in syntax_list {
    match node {

      Node::Directive(data) => {
        match Directive::from_identifier_and_parameters(data.identifier, &data.arguments).unwrap() {

          // Process the origin directive to build a new data range.
          Directive::Org(address) => {
            let new_range = DataRange::new(address);
            let previous_range = mem::replace(&mut current_range, new_range);
            if previous_range.len() > 0 {
              data_ranges.push(previous_range);
            }
          }

          // Emit the directive into the range.
          directive @ _ => {
            assert_eq!(current_range.append(directive.into_vec().as_slice()), true);
          }

        }
      }

      Node::Instruction(data) => {
        // Verify the semantics and append the instruction to the output buffer.
        match Instruction::from_mnemonic_and_parameters(data.mnemonic, &data.fields, label_address_map) {
          Ok(instruction) => {
            assert_eq!(current_range.append(instruction.into_vec().as_slice()), true);
          }
          Err(reason) => {
            return Err(format_semantic_error(&data.location, reason));
          }
        }
      }

      Node::Label(_) => {
        // Processed in Pass 1.
      }

    }
  }

  // Push the last range into the list.
  if current_range.len() > 0 {
    data_ranges.push(current_range);
  }

  Ok(data_ranges)
}

// MARK: - Public API

/**
 Analyze the ASL for the assembly and convert it into an output byte stream.
 */
pub fn assemble<'a>(syntax_list: Vec<Node<'a>>) -> Result<Vec<DataRange>, String> {
  let label_address_map = try!(define_labels(&syntax_list));
  emit_data_ranges(syntax_list, &label_address_map)
}

// MARK: - Tests

#[cfg(test)]
mod tests {

  use assembler::parser::*;
  use assembler::source_file_location::SourceFileLocation;
  use assembler::u12::*;

  use super::define_labels;

  // MARK: - Helpers

  /// Creates a Label type node with associated data at location "-:seq:1-name.len()".
  fn make_label_node<'a>(seq: usize, name: &'a str) -> Node<'a> {
    Node::Label (
      LabelData {
        location: SourceFileLocation::new("-", seq, 1, name.len()),
        identifier: name
      }
    )
  }

  /// Creates a Directive type node with associated data at location "-:seq:2-name.len()+1".
  fn make_directive_node<'a>(seq: usize, name: &'a str, args: Vec<Literal<'a>>) -> Node<'a> {
    Node::Directive (
      DirectiveData {
        location: SourceFileLocation::new("-", seq, 2, name.len()),
        identifier: name,
        arguments: args
      }
    )
  }

  /// Creates an Instruction type node with associated data at location "-:seq:1-name.len()".
  fn make_instruction_node<'a>(seq: usize, name: &'a str, fields: Vec<InstructionField<'a>>) -> Node<'a> {
    Node::Instruction (
      InstructionData {
        location: SourceFileLocation::new("-", seq, 1, name.len()),
        mnemonic: name,
        fields: fields
      }
    )
  }

  // MARK: - Pass 1 Tests

  #[test]
  fn test_define_labels() {
    let program = vec![
      make_directive_node   (1, "org", vec![Literal::Numeric(0x100)]),
      make_label_node       (2, "label1"),
      make_directive_node   (3, "db", vec![Literal::Numeric(0xFF)]),
      make_label_node       (4, "label2"),
      make_instruction_node (5, "trap", vec![]),
      make_label_node       (6, "label3"),
    ];

    let result = define_labels(&program);

    // Assert that semantic analysis passed.
    if let Err(reason) = result {
      assert!(false, "Unexpected failure in assembler pass 1: {}", reason);
      return;
    }

    // Verify that the
    if let Ok(label_map) = result {
      assert_eq!(label_map.len(), 3);
      assert_eq!(label_map.get("label1").unwrap(), &(0x100.as_u12().unwrap()));
      assert_eq!(label_map.get("label2").unwrap(), &(0x101.as_u12().unwrap()));
      assert_eq!(label_map.get("label3").unwrap(), &(0x103.as_u12().unwrap()));
    }
  }

  #[test]
  fn test_define_labels_does_semantic_analysis_on_org() {
    let program = vec![
      make_directive_node(1, "org", vec![])
    ];

    let result = define_labels(&program);
    assert_eq!(result, Err(String::from("-:1:2-4: error: Incorrect number of parameters (0) for directive .org, expecting 1.")));
  }

  #[test]
  fn test_define_labels_does_semantic_analysis_on_db() {
    let program = vec![
      make_directive_node(1, "db", vec![])
    ];

    let result = define_labels(&program);
    assert_eq!(result, Err(String::from("-:1:2-3: error: Incorrect number of parameters (0) for directive .db, expecting 1 or more.")));
  }

  #[test]
  fn test_define_labels_fails_on_redefinition() {
    let program = vec![
      make_label_node(1, "L1"),
      make_label_node(2, "L1"),
    ];

    let result = define_labels(&program);
    assert_eq!(result, Err(String::from("-:2:1-2: error: Attempted re-definition of label L1.")));
  }

}
<|endoftext|>


<commit_before>use calx::{CellVector, FovValue, HexGeom};
use location::Location;
use terraform::TerrainQuery;
use world::World;

#[derive(Clone)]
pub struct SightFov<'a> {
    w: &'a World,
    range: u32,
    pub origin: Location,
    is_edge: bool,
}

impl<'a> SightFov<'a> {
    pub fn new(w: &'a World, range: u32, origin: Location) -> SightFov<'a> {
        SightFov {
            w,
            range,
            origin,
            is_edge: false,
        }
    }
}

impl<'a> PartialEq for SightFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.range == other.range
            && self.origin == other.origin && self.is_edge == other.is_edge
    }
}

impl<'a> Eq for SightFov<'a> {}

impl<'a> FovValue for SightFov<'a> {
    fn advance(&self, offset: CellVector) -> Option<Self> {
        if offset.hex_dist() as u32 > self.range {
            return None;
        }

        if self.is_edge {
            return None;
        }

        let mut ret = self.clone();
        if let Some(dest) = self.w.visible_portal(self.origin + offset) {
            ret.origin = dest - offset;
        }

        if self.w.terrain(ret.origin + offset).blocks_sight() {
            ret.is_edge = true;
        }

        // Stop FOV from proceeding more than one layer past sector edges.
        // (Only use this when gameplay is based on non-scrolling sector-screens.)
        if (self.origin + offset).sector() != self.origin.sector() {
            ret.is_edge = true;
        }

        Some(ret)
    }
}

#[derive(Clone)]
/// Field for spherical explosions that can be blocked by terrain.
pub struct SphereVolumeFov<'a> {
    w: &'a World,
    range: u32,
    pub origin: Location,
}

impl<'a> SphereVolumeFov<'a> {
    pub fn new(w: &'a World, range: u32, origin: Location) -> SphereVolumeFov<'a> {
        SphereVolumeFov { w, range, origin }
    }
}

impl<'a> PartialEq for SphereVolumeFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.range == other.range
            && self.origin == other.origin
    }
}

impl<'a> Eq for SphereVolumeFov<'a> {}

impl<'a> FovValue for SphereVolumeFov<'a> {
    fn advance(&self, offset: CellVector) -> Option<Self> {
        if offset.hex_dist() as u32 > self.range {
            return None;
        }

        let mut ret = self.clone();
        // NB: Sphere volumes don't spread over non-visible portals. Not sure if this is the right
        // choice but it would probably be annoying and surprising if they did.
        if let Some(dest) = self.w.visible_portal(self.origin + offset) {
            ret.origin = dest - offset;
        }

        // Unlike with sight fov, the blocking cells won't be included in the result set.

        // TODO: Stopping criteria should be generalized to a function, don't just assume
        // `blocks_shot` is good.
        if self.w.terrain(self.origin + offset).blocks_shot() {
            return None;
        }

        Some(ret)
    }
}
<commit_msg>Remove unnecessary FOV limiter<commit_after>use calx::{CellVector, FovValue, HexGeom};
use location::Location;
use terraform::TerrainQuery;
use world::World;

#[derive(Clone)]
pub struct SightFov<'a> {
    w: &'a World,
    range: u32,
    pub origin: Location,
    is_edge: bool,
}

impl<'a> SightFov<'a> {
    pub fn new(w: &'a World, range: u32, origin: Location) -> SightFov<'a> {
        SightFov {
            w,
            range,
            origin,
            is_edge: false,
        }
    }
}

impl<'a> PartialEq for SightFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.range == other.range
            && self.origin == other.origin && self.is_edge == other.is_edge
    }
}

impl<'a> Eq for SightFov<'a> {}

impl<'a> FovValue for SightFov<'a> {
    fn advance(&self, offset: CellVector) -> Option<Self> {
        if offset.hex_dist() as u32 > self.range {
            return None;
        }

        if self.is_edge {
            return None;
        }

        let mut ret = self.clone();
        if let Some(dest) = self.w.visible_portal(self.origin + offset) {
            ret.origin = dest - offset;
        }

        if self.w.terrain(ret.origin + offset).blocks_sight() {
            ret.is_edge = true;
        }

        Some(ret)
    }
}

#[derive(Clone)]
/// Field for spherical explosions that can be blocked by terrain.
pub struct SphereVolumeFov<'a> {
    w: &'a World,
    range: u32,
    pub origin: Location,
}

impl<'a> SphereVolumeFov<'a> {
    pub fn new(w: &'a World, range: u32, origin: Location) -> SphereVolumeFov<'a> {
        SphereVolumeFov { w, range, origin }
    }
}

impl<'a> PartialEq for SphereVolumeFov<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.w as *const World == other.w as *const World && self.range == other.range
            && self.origin == other.origin
    }
}

impl<'a> Eq for SphereVolumeFov<'a> {}

impl<'a> FovValue for SphereVolumeFov<'a> {
    fn advance(&self, offset: CellVector) -> Option<Self> {
        if offset.hex_dist() as u32 > self.range {
            return None;
        }

        let mut ret = self.clone();
        // NB: Sphere volumes don't spread over non-visible portals. Not sure if this is the right
        // choice but it would probably be annoying and surprising if they did.
        if let Some(dest) = self.w.visible_portal(self.origin + offset) {
            ret.origin = dest - offset;
        }

        // Unlike with sight fov, the blocking cells won't be included in the result set.

        // TODO: Stopping criteria should be generalized to a function, don't just assume
        // `blocks_shot` is good.
        if self.w.terrain(self.origin + offset).blocks_shot() {
            return None;
        }

        Some(ret)
    }
}
<|endoftext|>


<commit_before>//! Updates all of the licenses from the existing crates into each of their
//! already existing versions.

//
// Usage:
//      cargo run --bin update-licenses

extern crate cargo_registry;
extern crate postgres;

use std::io::prelude::*;

fn main() {
    let conn = cargo_registry::db::connect_now();
    {
        let tx = conn.transaction().unwrap();
        transfer(&tx);
        tx.set_commit();
        tx.finish().unwrap();
    }
}

fn transfer(tx: &postgres::transaction::Transaction) {
    let stmt = tx.prepare("SELECT id, name, license FROM crates").unwrap();
    let rows = stmt.query(&[]).unwrap();

    for row in rows.iter() {
        let id: i32 = row.get("id");
        let name: String = row.get("name");
        let license: String = row.get("license");

        println!(
            "Setting the license for all versions of {} to {}.",
            name,
            license
        );

        let num_updated = tx.execute(
            "UPDATE versions SET license = $1 WHERE crate_id = $2",
            &[&license, &id],
        ).unwrap();
        assert!(num_updated > 0);
    }

    get_confirm("Finish committing?");
}

fn get_confirm(msg: &str) {
    print!("{} [y/N]: ", msg);
    std::io::stdout().flush().unwrap();

    let mut line = String::new();
    std::io::stdin().read_line(&mut line).unwrap();

    if !line.starts_with("y") {
        std::process::exit(0);
    }
}
<commit_msg>Updated 'update-license' binary to handle if the crate doesn't currently have a license.<commit_after>//! Updates all of the licenses from the existing crates into each of their
//! already existing versions.

//
// Usage:
//      cargo run --bin update-licenses

extern crate cargo_registry;
extern crate postgres;

use std::io::prelude::*;

fn main() {
    let conn = cargo_registry::db::connect_now();
    {
        let tx = conn.transaction().unwrap();
        transfer(&tx);
        tx.set_commit();
        tx.finish().unwrap();
    }
}

fn transfer(tx: &postgres::transaction::Transaction) {
    let stmt = tx.prepare("SELECT id, name, license FROM crates").unwrap();
    let rows = stmt.query(&[]).unwrap();

    for row in rows.iter() {
        let id: i32 = row.get("id");
        let name: String = row.get("name");
        let license: Option<String> = row.get("license");

        if let Some(license) = license {
            println!(
                "Setting the license for all versions of {} to {}.",
                name,
                license
            );

            let num_updated = tx.execute(
                "UPDATE versions SET license = $1 WHERE crate_id = $2",
                &[&license, &id],
            ).unwrap();
            assert!(num_updated > 0);
        } else {
            println!(
                "Ignoring crate `{}` because it doesn't have a license.",
                name
            );
        }
    }

    get_confirm("Finish committing?");
}

fn get_confirm(msg: &str) {
    print!("{} [y/N]: ", msg);
    std::io::stdout().flush().unwrap();

    let mut line = String::new();
    std::io::stdin().read_line(&mut line).unwrap();

    if !line.starts_with("y") {
        std::process::exit(0);
    }
}
<|endoftext|>


<commit_before>//! Starts a timely dataflow execution from configuration information and per-worker logic.

use timely_communication::{initialize, Configuration, Allocator, WorkerGuards};
use dataflow::scopes::{Root, Child, Scope};

/// Executes a single-threaded timely dataflow computation.
///
/// The `example` method takes a closure on a `Scope` which it executes to initialize and run a
/// timely dataflow computation on a single thread. This method is intended for use in examples,
/// rather than programs that may need to run across multiple workers.
///
/// The `example` method returns whatever the single worker returns from its closure.
/// This is often nothing, but the worker can return something about the data it saw in order to
/// test computations.
///
/// The method aggressively unwraps returned `Result<_>` types.
///
/// #Examples
///
/// The simplest example creates a stream of data and inspects it.
///
/// ```
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x));
/// });
/// ```
///
/// This next example captures the data and displays them once the computation is complete.
///
/// More precisely, the example captures a stream of events (receiving batches of data,
/// updates to input capabilities) and displays these events.
///
/// ```
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// let data = timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x))
///            .capture()
/// });
///
/// // the extracted data should have data (0..10) at timestamp 0.
/// assert_eq!(data.extract()[0].1, (0..10).collect::<Vec<_>>());
/// ```
pub fn example<T: Send+'static, F>(func: F) -> T
where F: Fn(&mut Child<Root<Allocator>, u64>)->T+Send+Sync+'static {
    let guards = initialize(Configuration::Thread, move |allocator| {
        let mut root = Root::new(allocator);
        let result = root.scoped::<u64,_,_>(|x| func(x));
        while root.step() { }
        result
    });

    guards.unwrap() // assert the computation started correctly
          .join()   // wait for the worker to finish
          .pop()    // grab the known-to-exist result
          .unwrap() // assert that the result exists
          .unwrap() // crack open the result to get a T
}

/// Executes a timely dataflow from a configuration and per-communicator logic.
///
/// The `execute` method takes a `Configuration` and spins up some number of
/// workers threads, each of which execute the supplied closure to construct
/// and run a timely dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// #Examples
/// ```
/// use timely::dataflow::Scope;
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), |root| {
///     root.scoped::<u64,_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
///
/// The following example demonstrates how one can extract data from a multi-worker execution.
/// In a multi-process setting, each process will only receive those records present at workers
/// in the process.
///
/// ```
/// use std::sync::{Arc, Mutex};
/// use timely::dataflow::Scope;
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// let (send, recv) = ::std::sync::mpsc::channel();
/// let send = Arc::new(Mutex::new(send));
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), move |root| {
///     let send = send.lock().unwrap().clone();
///     root.scoped::<u64,_,_>(move |scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x))
///                .capture_into(send);
///     });
/// }).unwrap();
///
/// // the extracted data should have data (0..10) thrice at timestamp 0.
/// assert_eq!(recv.extract()[0].1, (0..30).map(|x| x / 3).collect::<Vec<_>>());
/// ```
pub fn execute<T:Send+'static, F>(config: Configuration, func: F) -> Result<WorkerGuards<T>,String>
where F: Fn(&mut Root<Allocator>)->T+Send+Sync+'static {
    initialize(config, move |allocator| {
        let mut root = Root::new(allocator);
        let result = func(&mut root);
        while root.step() { }
        result
    })
}

/// Executes a timely dataflow from supplied arguments and per-communicator logic.
///
/// The `execute` method takes arguments (typically `std::env::args()`) and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// The arguments `execute` currently understands are:
///
/// `-w, --workers`: number of per-process worker threads.
///
/// `-n, --processes`: number of processes involved in the computation.
///
/// `-p, --process`: identity of this process; from 0 to n-1.
///
/// `-h, --hostfile`: a text file whose lines are "hostname:port" in order of process identity.
/// If not specified, `localhost` will be used, with port numbers increasing from 2101 (chosen
/// arbitrarily).
///
/// #Examples
/// ```
/// use timely::dataflow::*;
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// timely::execute_from_args(std::env::args(), |root| {
///     root.scoped::<u64,_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
/// ```ignore
/// host0% cargo run -- -w 2 -n 4 -h hosts.txt -p 0
/// host1% cargo run -- -w 2 -n 4 -h hosts.txt -p 1
/// host2% cargo run -- -w 2 -n 4 -h hosts.txt -p 2
/// host3% cargo run -- -w 2 -n 4 -h hosts.txt -p 3
/// ```
/// ```ignore
/// % cat hosts.txt
/// host0:port
/// host1:port
/// host2:port
/// host3:port
/// ```
pub fn execute_from_args<I, T:Send+'static, F>(iter: I, func: F) -> Result<WorkerGuards<T>,String>
    where I: Iterator<Item=String>,
          F: Fn(&mut Root<Allocator>)->T+Send+Sync+'static, {
    execute(try!(Configuration::from_args(iter)), func)
 }
<commit_msg>put type constraints in where block<commit_after>//! Starts a timely dataflow execution from configuration information and per-worker logic.

use timely_communication::{initialize, Configuration, Allocator, WorkerGuards};
use dataflow::scopes::{Root, Child, Scope};

/// Executes a single-threaded timely dataflow computation.
///
/// The `example` method takes a closure on a `Scope` which it executes to initialize and run a
/// timely dataflow computation on a single thread. This method is intended for use in examples,
/// rather than programs that may need to run across multiple workers.
///
/// The `example` method returns whatever the single worker returns from its closure.
/// This is often nothing, but the worker can return something about the data it saw in order to
/// test computations.
///
/// The method aggressively unwraps returned `Result<_>` types.
///
/// #Examples
///
/// The simplest example creates a stream of data and inspects it.
///
/// ```
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x));
/// });
/// ```
///
/// This next example captures the data and displays them once the computation is complete.
///
/// More precisely, the example captures a stream of events (receiving batches of data,
/// updates to input capabilities) and displays these events.
///
/// ```
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// let data = timely::example(|scope| {
///     (0..10).to_stream(scope)
///            .inspect(|x| println!("seen: {:?}", x))
///            .capture()
/// });
///
/// // the extracted data should have data (0..10) at timestamp 0.
/// assert_eq!(data.extract()[0].1, (0..10).collect::<Vec<_>>());
/// ```
pub fn example<T, F>(func: F) -> T
where T: Send+'static,
      F: Fn(&mut Child<Root<Allocator>, u64>)->T+Send+Sync+'static {
    let guards = initialize(Configuration::Thread, move |allocator| {
        let mut root = Root::new(allocator);
        let result = root.scoped::<u64,_,_>(|x| func(x));
        while root.step() { }
        result
    });

    guards.unwrap() // assert the computation started correctly
          .join()   // wait for the worker to finish
          .pop()    // grab the known-to-exist result
          .unwrap() // assert that the result exists
          .unwrap() // crack open the result to get a T
}

/// Executes a timely dataflow from a configuration and per-communicator logic.
///
/// The `execute` method takes a `Configuration` and spins up some number of
/// workers threads, each of which execute the supplied closure to construct
/// and run a timely dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// #Examples
/// ```
/// use timely::dataflow::Scope;
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), |root| {
///     root.scoped::<u64,_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
///
/// The following example demonstrates how one can extract data from a multi-worker execution.
/// In a multi-process setting, each process will only receive those records present at workers
/// in the process.
///
/// ```
/// use std::sync::{Arc, Mutex};
/// use timely::dataflow::Scope;
/// use timely::dataflow::operators::{ToStream, Inspect, Capture};
/// use timely::dataflow::operators::capture::Extract;
///
/// // get send and recv endpoints, wrap send to share
/// let (send, recv) = ::std::sync::mpsc::channel();
/// let send = Arc::new(Mutex::new(send));
///
/// // execute a timely dataflow using three worker threads.
/// timely::execute(timely::Configuration::Process(3), move |root| {
///     let send = send.lock().unwrap().clone();
///     root.scoped::<u64,_,_>(move |scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x))
///                .capture_into(send);
///     });
/// }).unwrap();
///
/// // the extracted data should have data (0..10) thrice at timestamp 0.
/// assert_eq!(recv.extract()[0].1, (0..30).map(|x| x / 3).collect::<Vec<_>>());
/// ```
pub fn execute<T, F>(config: Configuration, func: F) -> Result<WorkerGuards<T>,String>
where T:Send+'static,
      F: Fn(&mut Root<Allocator>)->T+Send+Sync+'static {
    initialize(config, move |allocator| {
        let mut root = Root::new(allocator);
        let result = func(&mut root);
        while root.step() { }
        result
    })
}

/// Executes a timely dataflow from supplied arguments and per-communicator logic.
///
/// The `execute` method takes arguments (typically `std::env::args()`) and spins up some number of
/// workers threads, each of which execute the supplied closure to construct and run a timely
/// dataflow computation.
///
/// The closure may return a `T: Send+'static`, and `execute` returns a result
/// containing a `WorkerGuards<T>` (or error information), which can be joined
/// to recover the result `T` values from the local workers.
///
/// The arguments `execute` currently understands are:
///
/// `-w, --workers`: number of per-process worker threads.
///
/// `-n, --processes`: number of processes involved in the computation.
///
/// `-p, --process`: identity of this process; from 0 to n-1.
///
/// `-h, --hostfile`: a text file whose lines are "hostname:port" in order of process identity.
/// If not specified, `localhost` will be used, with port numbers increasing from 2101 (chosen
/// arbitrarily).
///
/// #Examples
/// ```
/// use timely::dataflow::*;
/// use timely::dataflow::operators::{ToStream, Inspect};
///
/// // execute a timely dataflow using command line parameters
/// timely::execute_from_args(std::env::args(), |root| {
///     root.scoped::<u64,_,_>(|scope| {
///         (0..10).to_stream(scope)
///                .inspect(|x| println!("seen: {:?}", x));
///     })
/// }).unwrap();
/// ```
/// ```ignore
/// host0% cargo run -- -w 2 -n 4 -h hosts.txt -p 0
/// host1% cargo run -- -w 2 -n 4 -h hosts.txt -p 1
/// host2% cargo run -- -w 2 -n 4 -h hosts.txt -p 2
/// host3% cargo run -- -w 2 -n 4 -h hosts.txt -p 3
/// ```
/// ```ignore
/// % cat hosts.txt
/// host0:port
/// host1:port
/// host2:port
/// host3:port
/// ```
pub fn execute_from_args<I, T, F>(iter: I, func: F) -> Result<WorkerGuards<T>,String>
    where I: Iterator<Item=String>,
          T:Send+'static,
          F: Fn(&mut Root<Allocator>)->T+Send+Sync+'static, {
    execute(try!(Configuration::from_args(iter)), func)
 }
<|endoftext|>


<commit_before>
include!(concat!(env!("OUT_DIR"), "/exceptional-grammar.rs"));

#[cfg(test)]
mod test_helpers {
    use super::*;
    use ast::*;
    use num::rational::{Ratio};
    use num::{BigInt};

    pub fn v_string(name: &str) -> Literal {
        Literal::CharString(
           name.to_owned()
        )
    }

    pub fn v_ratio(num: i64, denom: i64) -> Literal {
        Literal::Number(
            Ratio::new(
                BigInt::from(num),
                BigInt::from(denom)
            )
        )
    }

    pub fn v_bool(b: bool) -> Literal {
        match b {
            true => Literal::Boolean(true),
            false => Literal::Boolean(false)
        }
    }

    pub fn v_function(args: Vec<String>, statements: Vec<Statement>) -> Literal {
        Literal::Fn(Box::new((args, statements)))
    }

    pub fn s_assign(name: &str, literal: Literal) -> Statement {
        Statement::Assign(
            true,
            name.to_owned(),
            Box::new(
                e_literal(
                    literal
                )
            )
        )
    }

    pub fn s_call(name: &str, args: Vec<Expression>) -> Statement {
        Statement::Call(name.to_owned(), args)
    }

    pub fn e_literal(literal: Literal) -> Expression {
        Expression::Literal(literal)
    }

    pub fn parse_expression(input: &str) -> Expression {
        expression(input).unwrap()
    }

    pub fn parse_statements(input: &str) -> Vec<Statement> {
        statements(input).unwrap()
    }

    pub fn parse_literal(input: &str) -> Literal {
        literal(input).unwrap()
    }
}

#[cfg(test)]
mod test_literals {
    use super::test_helpers::*;

    #[test]
    fn parses_number() {
        assert_eq!(
            parse_literal(&"1234"),
            v_ratio(1234, 1)
        );

        assert_eq!(
            parse_literal(&"0011"),
            v_ratio(11, 1)
        );
    }

    #[test]
    fn parses_strings() {
        assert_eq!(
            parse_literal(&"\"\""),
            v_string(&"")
        );

        assert_eq!(
            parse_literal(&"\"string with more words\""),
            v_string(&"string with more words")
        );
    }

    #[test]
    fn parses_booleans() {
        assert_eq!(
            parse_literal(&"true"),
            v_bool(true)
        );

        assert_eq!(
            parse_literal(&"false"),
            v_bool(false)
        );
    }
}

#[cfg(test)]
mod test_expressions {
    use super::test_helpers::*;

    #[test]
    fn parses_simple_expressions() {
        assert_eq!(
            parse_expression(&"1"),
            e_literal(v_ratio(1, 1))
        );

        assert_eq!(
            parse_expression(&"\"\""),
            e_literal(v_string(&""))
        )
    }

    #[test]
    fn parses_simple_functions() {
        assert_eq!(
            parse_expression(&"def() do end"),
            e_literal(
                v_function(vec![], vec![])
            )
        )
    }

    #[test]
    fn parses_functions_with_args() {
        assert_eq!(
            parse_expression(&"def(a, b) do end"),
            e_literal(
                v_function(vec!["a".to_owned(), "b".to_owned()], vec![])
            )
        )
    }

    #[test]
    fn prases_functions_with_bodies() {
        assert_eq!(
            parse_expression(&"def(a, b) do\nlet c = 1\nend"),
            e_literal(
                v_function(
                    vec!["a".to_owned(), "b".to_owned()],
                    vec![s_assign(&"c", v_ratio(1, 1))]
                )
            )
        )
    }
}

#[cfg(test)]
mod test_statements {
    use super::test_helpers::*;

    #[test]
    fn parses_assigns() {
        assert_eq!(
            parse_statements(&"let a = 1"),
            [s_assign(&"a", v_ratio(1, 1))]
        )
    }

    #[test]
    fn parses_calls() {
        assert_eq!(
            parse_statements("a()"),
            [s_call(&"a", vec![])]
        )
    }

    #[test]
    fn parses_calls_with_simple_args() {
        assert_eq!(
            parse_statements("a(1)"),
            [s_call(&"a", vec![e_literal(v_ratio(1, 1))])]
        )
    }
}
<commit_msg>Rename helper functions<commit_after>
include!(concat!(env!("OUT_DIR"), "/exceptional-grammar.rs"));

#[cfg(test)]
mod test_helpers {
    use super::*;
    use ast::*;
    use num::rational::{Ratio};
    use num::{BigInt};

    pub fn l_string(name: &str) -> Literal {
        Literal::CharString(
           name.to_owned()
        )
    }

    pub fn l_number(num: i64, denom: i64) -> Literal {
        Literal::Number(
            Ratio::new(
                BigInt::from(num),
                BigInt::from(denom)
            )
        )
    }

    pub fn l_bool(b: bool) -> Literal {
        match b {
            true => Literal::Boolean(true),
            false => Literal::Boolean(false)
        }
    }

    pub fn l_function(args: Vec<String>, statements: Vec<Statement>) -> Literal {
        Literal::Fn(Box::new((args, statements)))
    }

    pub fn s_assign(name: &str, literal: Literal) -> Statement {
        Statement::Assign(
            true,
            name.to_owned(),
            Box::new(
                e_literal(
                    literal
                )
            )
        )
    }

    pub fn s_call(name: &str, args: Vec<Expression>) -> Statement {
        Statement::Call(name.to_owned(), args)
    }

    pub fn e_literal(literal: Literal) -> Expression {
        Expression::Literal(literal)
    }

    pub fn parse_expression(input: &str) -> Expression {
        expression(input).unwrap()
    }

    pub fn parse_statements(input: &str) -> Vec<Statement> {
        statements(input).unwrap()
    }

    pub fn parse_literal(input: &str) -> Literal {
        literal(input).unwrap()
    }
}

#[cfg(test)]
mod test_literals {
    use super::test_helpers::*;

    #[test]
    fn parses_number() {
        assert_eq!(
            parse_literal(&"1234"),
            l_number(1234, 1)
        );

        assert_eq!(
            parse_literal(&"0011"),
            l_number(11, 1)
        );
    }

    #[test]
    fn parses_strings() {
        assert_eq!(
            parse_literal(&"\"\""),
            l_string(&"")
        );

        assert_eq!(
            parse_literal(&"\"string with more words\""),
            l_string(&"string with more words")
        );
    }

    #[test]
    fn parses_booleans() {
        assert_eq!(
            parse_literal(&"true"),
            l_bool(true)
        );

        assert_eq!(
            parse_literal(&"false"),
            l_bool(false)
        );
    }
}

#[cfg(test)]
mod test_expressions {
    use super::test_helpers::*;

    #[test]
    fn parses_simple_literal_expressions() {
        assert_eq!(
            parse_expression(&"1"),
            e_literal(l_number(1, 1))
        );

        assert_eq!(
            parse_expression(&"\"\""),
            e_literal(l_string(&""))
        )
    }

    #[test]
    fn parses_simple_functions() {
        assert_eq!(
            parse_expression(&"def() do end"),
            e_literal(
                l_function(vec![], vec![])
            )
        )
    }

    #[test]
    fn parses_functions_with_args() {
        assert_eq!(
            parse_expression(&"def(a, b) do end"),
            e_literal(
                l_function(vec!["a".to_owned(), "b".to_owned()], vec![])
            )
        )
    }

    #[test]
    fn prases_functions_with_bodies() {
        assert_eq!(
            parse_expression(&"def(a, b) do\nlet c = 1\nend"),
            e_literal(
                l_function(
                    vec!["a".to_owned(), "b".to_owned()],
                    vec![s_assign(&"c", l_number(1, 1))]
                )
            )
        )
    }
}

#[cfg(test)]
mod test_statements {
    use super::test_helpers::*;

    #[test]
    fn parses_assigns() {
        assert_eq!(
            parse_statements(&"let a = 1"),
            [s_assign(&"a", l_number(1, 1))]
        )
    }

    #[test]
    fn parses_calls() {
        assert_eq!(
            parse_statements("a()"),
            [s_call(&"a", vec![])]
        )
    }

    #[test]
    fn parses_calls_with_simple_args() {
        assert_eq!(
            parse_statements("a(1)"),
            [s_call(&"a", vec![e_literal(v_ratio(1, 1))])]
        )
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::marker::PhantomData;
use std::ops::RangeFrom;
use {Command, Error, Record};

#[derive(Debug)]
struct Branch<R> {
    parent: usize,
    cursor: usize,
    commands: Box<[Box<dyn Command<R> + 'static>]>,
}

/// A history of commands.
#[derive(Debug)]
pub struct History<R> {
    id: usize,
    next: RangeFrom<usize>,
    record: Record<R>,
    branches: HashMap<usize, Branch<R>>,
}

impl<R> History<R> {
    /// Returns a new history.
    #[inline]
    pub fn new(receiver: impl Into<R>) -> History<R> {
        History {
            id: 0,
            next: 1..,
            record: Record::new(receiver),
            branches: HashMap::new(),
        }
    }

    /// Pushes the command to the top of the history and executes its [`apply`] method.
    /// The command is merged with the previous top command if they have the same [`id`].
    ///
    /// # Errors
    /// If an error occur when executing [`apply`] the error is returned together with the command.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    /// [`id`]: trait.Command.html#method.id
    #[inline]
    pub fn apply(&mut self, cmd: impl Command<R> + 'static) -> Result<Option<usize>, Error<R>>
    where
        R: 'static,
    {
        let commands = self.record.apply(cmd)?;
        let commands: Vec<_> = commands.collect();
        if !commands.is_empty() {
            let id = self.next.next().unwrap();
            self.branches.insert(
                id,
                Branch {
                    parent: self.id,
                    cursor: self.record.cursor(),
                    commands: commands.into_boxed_slice(),
                },
            );
            Ok(Some(id))
        } else {
            Ok(None)
        }
    }

    /// Calls the [`undo`] method for the active command and sets the previous one as the new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`undo`] the error is returned together with the command.
    ///
    /// [`undo`]: trait.Command.html#tymethod.undo
    #[inline]
    #[must_use]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        self.record.undo()
    }

    /// Calls the [`redo`] method for the active command and sets the next one as the
    /// new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`redo`] the error is returned together with the command.
    ///
    /// [`redo`]: trait.Command.html#method.redo
    #[inline]
    #[must_use]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        self.record.redo()
    }

    /// Jumps to the command in `branch` at `cursor`.
    #[inline]
    #[must_use]
    pub fn jump_to(&mut self, branch: usize, cursor: usize) -> Option<Result<(), Error<R>>> {
        if self.id == branch {
            return self.record.set_cursor(cursor);
        }

        let mut dst = &self.branches[&branch];
        let mut path = vec![dst];
        while dst.parent != self.id {
            dst = &self.branches[&dst.parent];
            path.push(dst);
        }

        while let Some(last) = path.pop() {
            let _ = last.parent;
            let _ = last.cursor;
        }

        unimplemented!()
    }
}

impl<R> From<R> for History<R> {
    #[inline]
    fn from(receiver: R) -> Self {
        History::new(receiver)
    }
}

/// Builder for a history.
#[allow(missing_debug_implementations)]
pub struct HistoryBuilder<R> {
    receiver: PhantomData<R>,
}
<commit_msg>Use get instead of []<commit_after>use std::collections::HashMap;
use std::marker::PhantomData;
use std::ops::RangeFrom;
use {Command, Error, Record};

#[derive(Debug)]
struct Branch<R> {
    parent: usize,
    cursor: usize,
    commands: Box<[Box<dyn Command<R> + 'static>]>,
}

/// A history of commands.
#[derive(Debug)]
pub struct History<R> {
    id: usize,
    next: RangeFrom<usize>,
    record: Record<R>,
    branches: HashMap<usize, Branch<R>>,
}

impl<R> History<R> {
    /// Returns a new history.
    #[inline]
    pub fn new(receiver: impl Into<R>) -> History<R> {
        History {
            id: 0,
            next: 1..,
            record: Record::new(receiver),
            branches: HashMap::new(),
        }
    }

    /// Pushes the command to the top of the history and executes its [`apply`] method.
    /// The command is merged with the previous top command if they have the same [`id`].
    ///
    /// # Errors
    /// If an error occur when executing [`apply`] the error is returned together with the command.
    ///
    /// [`apply`]: trait.Command.html#tymethod.apply
    /// [`id`]: trait.Command.html#method.id
    #[inline]
    pub fn apply(&mut self, cmd: impl Command<R> + 'static) -> Result<Option<usize>, Error<R>>
    where
        R: 'static,
    {
        let commands = self.record.apply(cmd)?;
        let commands: Vec<_> = commands.collect();
        if !commands.is_empty() {
            let id = self.next.next().unwrap();
            self.branches.insert(
                id,
                Branch {
                    parent: self.id,
                    cursor: self.record.cursor(),
                    commands: commands.into_boxed_slice(),
                },
            );
            Ok(Some(id))
        } else {
            Ok(None)
        }
    }

    /// Calls the [`undo`] method for the active command and sets the previous one as the new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`undo`] the error is returned together with the command.
    ///
    /// [`undo`]: trait.Command.html#tymethod.undo
    #[inline]
    #[must_use]
    pub fn undo(&mut self) -> Option<Result<(), Error<R>>> {
        self.record.undo()
    }

    /// Calls the [`redo`] method for the active command and sets the next one as the
    /// new active one.
    ///
    /// # Errors
    /// If an error occur when executing [`redo`] the error is returned together with the command.
    ///
    /// [`redo`]: trait.Command.html#method.redo
    #[inline]
    #[must_use]
    pub fn redo(&mut self) -> Option<Result<(), Error<R>>> {
        self.record.redo()
    }

    /// Jumps to the command in `branch` at `cursor`.
    #[inline]
    #[must_use]
    pub fn jump_to(&mut self, branch: usize, cursor: usize) -> Option<Result<(), Error<R>>> {
        if self.id == branch {
            return self.record.set_cursor(cursor);
        }

        let mut dst = self.branches.get(&branch)?;
        let mut path = vec![dst];
        while dst.parent != self.id {
            dst = &self.branches[&dst.parent];
            path.push(dst);
        }

        while let Some(last) = path.pop() {
            let _ = last.parent;
            let _ = last.cursor;
        }

        unimplemented!()
    }
}

impl<R> From<R> for History<R> {
    #[inline]
    fn from(receiver: R) -> Self {
        History::new(receiver)
    }
}

/// Builder for a history.
#[derive(Debug)]
pub struct HistoryBuilder<R> {
    receiver: PhantomData<R>,
}
<|endoftext|>


<commit_before>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
use std::net::{
    Ipv4Addr,
    Ipv6Addr,
};
use std::ptr;
use std::str;

use types::{
    AddressFamily,
    IpAddr,
};
use utils::address_family;

#[repr(C)]
#[derive(Debug)]
#[allow(raw_pointer_derive)]
#[cfg(unix)]
pub struct hostent {
    pub h_name: *mut libc::c_char,
    pub h_aliases: *mut *mut libc::c_char,
    pub h_addrtype: libc::c_int,
    pub h_length: libc::c_int,
    pub h_addr_list: *mut *mut libc::c_char,
}

#[repr(C)]
#[derive(Debug)]
#[allow(raw_pointer_derive)]
#[cfg(windows)]
pub struct hostent {
    pub h_name: *mut libc::c_char,
    pub h_aliases: *mut *mut libc::c_char,
    pub h_addrtype: libc::c_short,
    pub h_length: libc::c_short,
    pub h_addr_list: *mut *mut libc::c_char,
}

impl hostent {
    pub fn hostname(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(self.h_name);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }

    pub fn addresses(&self) -> HostAddressResultsIterator {
        match address_family(self.h_addrtype as libc::c_int) {
            Some(family) => HostAddressResultsIterator {
                family: family,
                next: self.h_addr_list as *const *const _,
                phantom: PhantomData,
            },
            None => HostAddressResultsIterator {
                family: AddressFamily::INET,
                next: ptr::null(),
                phantom: PhantomData,
            }
        }
    }

    pub fn aliases(&self) -> HostAliasResultsIterator {
        HostAliasResultsIterator {
            next: self.h_aliases as *const *const _,
            phantom: PhantomData,
        }
    }
}

impl fmt::Display for hostent {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "Hostname: {}, ", self.hostname()));
        try!(write!(fmt, "Addresses: ["));
        let mut first = true;
        for host_addr in self.addresses() {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{}", prefix, host_addr));
        }
        try!(write!(fmt, "], "));
        try!(write!(fmt, "Aliases: ["));
        let mut first = true;
        for host_alias in self.aliases() {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{}", prefix, host_alias));
        }
        try!(write!(fmt, "]"));
        Ok(())
    }
}

/// An alias, as retrieved from a host lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAliasResult<'a> {
    h_alias: *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

/// An address, as retrieved from a host lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAddressResult<'a> {
    family: AddressFamily,
    h_addr: *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> HostAddressResult<'a> {
    /// Returns the IP address in this `HostResult`.
    pub fn ip_address(&self) -> IpAddr {
        match self.family {
            AddressFamily::INET => {
                let ipv4 = self.ipv4_address();
                IpAddr::V4(ipv4)
            },
            AddressFamily::INET6 => {
                let ipv6 = self.ipv6_addr();
                IpAddr::V6(ipv6)
            },
        }
    }

    fn ipv4_address(&self) -> Ipv4Addr {
        let h_addr = self.h_addr;
        unsafe {
            Ipv4Addr::new(
                *h_addr as u8,
                *h_addr.offset(1) as u8,
                *h_addr.offset(2) as u8,
                *h_addr.offset(3) as u8)
        }
    }

    fn ipv6_addr(&self) -> Ipv6Addr {
        let h_addr = self.h_addr;
        unsafe {
            Ipv6Addr::new(
                ((*h_addr as u16) << 8) + *h_addr.offset(1) as u16,
                ((*h_addr.offset(2) as u16) << 8) + *h_addr.offset(3) as u16,
                ((*h_addr.offset(4) as u16) << 8) + *h_addr.offset(5) as u16,
                ((*h_addr.offset(6) as u16) << 8) + *h_addr.offset(7) as u16,
                ((*h_addr.offset(8) as u16) << 8) + *h_addr.offset(9) as u16,
                ((*h_addr.offset(10) as u16) << 8) + *h_addr.offset(11) as u16,
                ((*h_addr.offset(12) as u16) << 8) + *h_addr.offset(13) as u16,
                ((*h_addr.offset(14) as u16) << 8) + *h_addr.offset(15) as u16)
        }
    }
}

impl<'a> fmt::Display for HostAddressResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.ip_address().fmt(fmt)
    }
}

unsafe impl<'a> Send for HostAddressResult<'a> { }
unsafe impl<'a> Sync for HostAddressResult<'a> { }

#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAddressResultsIterator<'a> {
    family: AddressFamily,
    next: *const *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> Iterator for HostAddressResultsIterator<'a> {
    type Item = HostAddressResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        if self.next.is_null() { return None }
        let h_addr = unsafe { *self.next };
        if h_addr.is_null() {
            None
        } else {
            self.next = unsafe { self.next.offset(1) };
            let addr_result = HostAddressResult {
                family: self.family,
                h_addr: h_addr,
                phantom: PhantomData,
            };
            Some(addr_result)
        }
    }
}

unsafe impl<'a> Send for HostAddressResultsIterator<'a> { }
unsafe impl<'a> Sync for HostAddressResultsIterator<'a> { }

impl<'a> HostAliasResult<'a> {
    /// Returns the alias in this `HostAliasResult`.
    pub fn alias(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(self.h_alias);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }
}

impl<'a> fmt::Display for HostAliasResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.alias().fmt(fmt)
    }
}

unsafe impl<'a> Send for HostAliasResult<'a> { }
unsafe impl<'a> Sync for HostAliasResult<'a> { }

#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAliasResultsIterator<'a> {
    next: *const *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> Iterator for HostAliasResultsIterator<'a> {
    type Item = HostAliasResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let h_alias = unsafe { *self.next };
        if h_alias.is_null() {
            None
        } else {
            self.next = unsafe { self.next.offset(1) };
            let alias_result = HostAliasResult {
                h_alias: h_alias,
                phantom: PhantomData,
            };
            Some(alias_result)
        }
    }
}

unsafe impl<'a> Send for HostAliasResultsIterator<'a> { }
unsafe impl<'a> Sync for HostAliasResultsIterator<'a> { }
<commit_msg>Prefer Option over null pointer<commit_after>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
use std::net::{
    Ipv4Addr,
    Ipv6Addr,
};
use std::str;

use types::{
    AddressFamily,
    IpAddr,
};
use utils::address_family;

#[repr(C)]
#[derive(Debug)]
#[allow(raw_pointer_derive)]
#[cfg(unix)]
pub struct hostent {
    pub h_name: *mut libc::c_char,
    pub h_aliases: *mut *mut libc::c_char,
    pub h_addrtype: libc::c_int,
    pub h_length: libc::c_int,
    pub h_addr_list: *mut *mut libc::c_char,
}

#[repr(C)]
#[derive(Debug)]
#[allow(raw_pointer_derive)]
#[cfg(windows)]
pub struct hostent {
    pub h_name: *mut libc::c_char,
    pub h_aliases: *mut *mut libc::c_char,
    pub h_addrtype: libc::c_short,
    pub h_length: libc::c_short,
    pub h_addr_list: *mut *mut libc::c_char,
}

impl hostent {
    pub fn hostname(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(self.h_name);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }

    pub fn addresses(&self) -> HostAddressResultsIterator {
        HostAddressResultsIterator {
            family: address_family(self.h_addrtype as libc::c_int),
            next: self.h_addr_list as *const *const _,
            phantom: PhantomData,
        }
    }

    pub fn aliases(&self) -> HostAliasResultsIterator {
        HostAliasResultsIterator {
            next: self.h_aliases as *const *const _,
            phantom: PhantomData,
        }
    }
}

impl fmt::Display for hostent {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "Hostname: {}, ", self.hostname()));
        try!(write!(fmt, "Addresses: ["));
        let mut first = true;
        for host_addr in self.addresses() {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{}", prefix, host_addr));
        }
        try!(write!(fmt, "], "));
        try!(write!(fmt, "Aliases: ["));
        let mut first = true;
        for host_alias in self.aliases() {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{}", prefix, host_alias));
        }
        try!(write!(fmt, "]"));
        Ok(())
    }
}

/// An alias, as retrieved from a host lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAliasResult<'a> {
    h_alias: *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

/// An address, as retrieved from a host lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAddressResult<'a> {
    family: AddressFamily,
    h_addr: *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> HostAddressResult<'a> {
    /// Returns the IP address in this `HostResult`.
    pub fn ip_address(&self) -> IpAddr {
        match self.family {
            AddressFamily::INET => {
                let ipv4 = self.ipv4_address();
                IpAddr::V4(ipv4)
            },
            AddressFamily::INET6 => {
                let ipv6 = self.ipv6_addr();
                IpAddr::V6(ipv6)
            },
        }
    }

    fn ipv4_address(&self) -> Ipv4Addr {
        let h_addr = self.h_addr;
        unsafe {
            Ipv4Addr::new(
                *h_addr as u8,
                *h_addr.offset(1) as u8,
                *h_addr.offset(2) as u8,
                *h_addr.offset(3) as u8)
        }
    }

    fn ipv6_addr(&self) -> Ipv6Addr {
        let h_addr = self.h_addr;
        unsafe {
            Ipv6Addr::new(
                ((*h_addr as u16) << 8) + *h_addr.offset(1) as u16,
                ((*h_addr.offset(2) as u16) << 8) + *h_addr.offset(3) as u16,
                ((*h_addr.offset(4) as u16) << 8) + *h_addr.offset(5) as u16,
                ((*h_addr.offset(6) as u16) << 8) + *h_addr.offset(7) as u16,
                ((*h_addr.offset(8) as u16) << 8) + *h_addr.offset(9) as u16,
                ((*h_addr.offset(10) as u16) << 8) + *h_addr.offset(11) as u16,
                ((*h_addr.offset(12) as u16) << 8) + *h_addr.offset(13) as u16,
                ((*h_addr.offset(14) as u16) << 8) + *h_addr.offset(15) as u16)
        }
    }
}

impl<'a> fmt::Display for HostAddressResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.ip_address().fmt(fmt)
    }
}

unsafe impl<'a> Send for HostAddressResult<'a> { }
unsafe impl<'a> Sync for HostAddressResult<'a> { }

#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAddressResultsIterator<'a> {
    family: Option<AddressFamily>,
    next: *const *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> Iterator for HostAddressResultsIterator<'a> {
    type Item = HostAddressResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let h_addr = unsafe { *self.next };
        if h_addr.is_null() {
            None
        } else {
            self.next = unsafe { self.next.offset(1) };
            self.family.map(|family| {
                HostAddressResult {
                    family: family,
                    h_addr: h_addr,
                    phantom: PhantomData,
                }
            })
        }
    }
}

unsafe impl<'a> Send for HostAddressResultsIterator<'a> { }
unsafe impl<'a> Sync for HostAddressResultsIterator<'a> { }

impl<'a> HostAliasResult<'a> {
    /// Returns the alias in this `HostAliasResult`.
    pub fn alias(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(self.h_alias);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }
}

impl<'a> fmt::Display for HostAliasResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.alias().fmt(fmt)
    }
}

unsafe impl<'a> Send for HostAliasResult<'a> { }
unsafe impl<'a> Sync for HostAliasResult<'a> { }

#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAliasResultsIterator<'a> {
    next: *const *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> Iterator for HostAliasResultsIterator<'a> {
    type Item = HostAliasResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let h_alias = unsafe { *self.next };
        if h_alias.is_null() {
            None
        } else {
            self.next = unsafe { self.next.offset(1) };
            let alias_result = HostAliasResult {
                h_alias: h_alias,
                phantom: PhantomData,
            };
            Some(alias_result)
        }
    }
}

unsafe impl<'a> Send for HostAliasResultsIterator<'a> { }
unsafe impl<'a> Sync for HostAliasResultsIterator<'a> { }
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cssparser::Color;
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use gecko_bindings::structs::{nscolor, StyleComplexColor};

impl From<nscolor> for StyleComplexColor {
    fn from(other: nscolor) -> Self {
        StyleComplexColor {
            mColor: other,
            mForegroundRatio: 0,
            mIsAuto: false,
        }
    }
}

impl StyleComplexColor {
    pub fn current_color() -> Self {
        StyleComplexColor {
            mColor: 0,
            mForegroundRatio: 255,
            mIsAuto: false,
        }
    }

    pub fn auto() -> Self {
        StyleComplexColor {
            mColor: 0,
            mForegroundRatio: 255,
            mIsAuto: true,
        }
    }
}

impl From<Color> for StyleComplexColor {
    fn from(other: Color) -> Self {
        match other {
            Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba).into(),
            Color::CurrentColor => StyleComplexColor::current_color(),
        }
    }
}

impl From<StyleComplexColor> for Color {
    fn from(other: StyleComplexColor) -> Self {
        if other.mForegroundRatio == 0 {
            Color::RGBA(convert_nscolor_to_rgba(other.mColor))
        } else if other.mForegroundRatio == 255 {
            Color::CurrentColor
        } else {
            // FIXME #13546 handle interpolation values
            Color::CurrentColor
        }
    }
}
<commit_msg>style: Document the StyleComplexColor sugar.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Rust helpers to interact with Gecko's StyleComplexColor.

use cssparser::Color;
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use gecko_bindings::structs::{nscolor, StyleComplexColor};

impl From<nscolor> for StyleComplexColor {
    fn from(other: nscolor) -> Self {
        StyleComplexColor {
            mColor: other,
            mForegroundRatio: 0,
            mIsAuto: false,
        }
    }
}

impl StyleComplexColor {
    /// Create a `StyleComplexColor` value that represents `currentColor`.
    pub fn current_color() -> Self {
        StyleComplexColor {
            mColor: 0,
            mForegroundRatio: 255,
            mIsAuto: false,
        }
    }

    /// Create a `StyleComplexColor` value that represents `auto`.
    pub fn auto() -> Self {
        StyleComplexColor {
            mColor: 0,
            mForegroundRatio: 255,
            mIsAuto: true,
        }
    }
}

impl From<Color> for StyleComplexColor {
    fn from(other: Color) -> Self {
        match other {
            Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba).into(),
            Color::CurrentColor => StyleComplexColor::current_color(),
        }
    }
}

impl From<StyleComplexColor> for Color {
    fn from(other: StyleComplexColor) -> Self {
        if other.mForegroundRatio == 0 {
            Color::RGBA(convert_nscolor_to_rgba(other.mColor))
        } else if other.mForegroundRatio == 255 {
            Color::CurrentColor
        } else {
            // FIXME #13546 handle interpolation values
            Color::CurrentColor
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;
use std::fs::OpenOptions;
use std::path::Path;

use storage::{Storage, StorageError, Result, ByteEncodable, ByteDecodable};
use chunked_storage::indexing_chunk::HotIndexingChunk;
pub use chunked_storage::indexing_chunk::IndexingChunk;

mod indexing_chunk;

pub const SIZE: usize = 104;
const HOTCHUNKS_FILENAME: &'static str = "hot_chunks.bin";
const ASSOCIATED_FILES: &'static [&'static str; 1] = &[HOTCHUNKS_FILENAME];

pub struct MutChunkRef<'a> {
    chunk: &'a mut HotIndexingChunk,
    archive: &'a mut Box<Storage<IndexingChunk>>,
}

pub struct ChunkRef<'a> {
    read_ptr: usize,
    chunk: &'a HotIndexingChunk,
    archive: &'a Box<Storage<IndexingChunk>>,
}

// The idea here is the abstract the inner workings of chunked storage and indexing chunk from the index
// To do this, we implement Read and Write
impl<'a> io::Write for MutChunkRef<'a> {
    // Fill the HotIndexingChunk
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let bytes_written = try!((&mut self.chunk.data[SIZE - self.chunk.capacity as usize..]).write(buf));
        self.chunk.capacity -= bytes_written as u16;
        if self.chunk.capacity == 0 {
            let id = self.archive.len();

            match self.archive.store(id as u64, self.chunk.archive(id as u32)) {
                Ok(_) => {}
                Err(StorageError::IO(error)) |
                Err(StorageError::ReadError(Some(error))) |
                Err(StorageError::WriteError(Some(error))) => return Err(error),
                _ => return Err(io::Error::last_os_error()),
            }
        }
        Ok(bytes_written)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl<'a> io::Read for ChunkRef<'a> {
    // BULLSHIT. RETHINK THIS!
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut bytes_read = 0;
        loop {
            let chunk_id = self.read_ptr / SIZE;
            if chunk_id < self.chunk.archived_chunks().len() {
                let read = (&self.archive.get(chunk_id as u64).unwrap().get_bytes()[self.read_ptr % SIZE..])
                    .read(&mut buf[bytes_read..])
                    .unwrap();
                if read == 0 {
                    return Ok(bytes_read);
                }
                bytes_read += read;
                self.read_ptr += read;
            } else {
                break;
            }
        }
        let read = (&self.chunk.get_bytes()[self.read_ptr % SIZE..]).read(&mut buf[bytes_read..]).unwrap();
        bytes_read += read;
        self.read_ptr += read;
        Ok(bytes_read)
    }
}

impl<'a> MutChunkRef<'a> {
    #[inline]
    pub fn get_last_doc_id(&self) -> u64 {
        self.chunk.get_last_doc_id()
    }

    pub fn set_last_doc_id(&mut self, new_id: u64) {
        self.chunk.set_last_doc_id(new_id);
    }
}

// TODO: Think about implementing `Persistent` and `Volatile`
pub struct ChunkedStorage {
    hot_chunks: Vec<HotIndexingChunk>, // Size of vocabulary
    archive: Box<Storage<IndexingChunk>>,
}

impl ChunkedStorage {
    pub fn new(capacity: usize, archive: Box<Storage<IndexingChunk>>) -> Self {
        ChunkedStorage {
            hot_chunks: Vec::with_capacity(capacity),
            archive: archive,
        }
    }

    /// Persists hot_chunks to a file.
    /// We currently only need to persist hot_chunks
    /// Archive takes care of the rest
    pub fn persist(&self, target: &Path) -> Result<()> {
        let mut file =
            try!(OpenOptions::new().write(true).create(true).truncate(true).open(target.join(HOTCHUNKS_FILENAME)));
        for chunk in &self.hot_chunks {
            let bytes = chunk.encode();
            try!(file.write(&bytes));
        }
        Ok(())
    }

    pub fn load(source: &Path, archive: Box<Storage<IndexingChunk>>) -> Result<Self> {
        let mut file = try!(OpenOptions::new().read(true).open(source.join(HOTCHUNKS_FILENAME)));
        let mut hot_chunks = Vec::new();
        while let Ok(decoded_chunk) = HotIndexingChunk::decode(&mut file) {
            hot_chunks.push(decoded_chunk);
        }
        Ok(ChunkedStorage {
            hot_chunks: hot_chunks,
            archive: archive,
        })
    }

    pub fn new_chunk(&mut self, term_id: u64) -> MutChunkRef {
        // The following code-uglyness is due to the fact that in indexing one sort thread can
        // overtake the other. That means: ids are not just comming in an incremental order but can jump

        // If the id is larger than the len (e.g. can not be just pushed)
        // Push uninitialized chunks until the desired chunk can be created and pushed
        let diff = term_id as usize - self.hot_chunks.len();
        for _ in 0..diff + 1 {
            self.hot_chunks.push(HotIndexingChunk::new());
        }

        self.hot_chunks[term_id as usize] = HotIndexingChunk::new();
        MutChunkRef {
            chunk: &mut self.hot_chunks[term_id as usize],
            archive: &mut self.archive,
        }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.hot_chunks.len()
    }

    #[inline]
    pub fn get_current(&self, id: u64) -> ChunkRef {
        ChunkRef {
            read_ptr: 0,
            chunk: &self.hot_chunks[id as usize],
            archive: &self.archive,
        }
    }

    #[inline]
    pub fn get_current_mut(&mut self, id: u64) -> MutChunkRef {
        MutChunkRef {
            chunk: &mut self.hot_chunks[id as usize],
            archive: &mut self.archive,
        }
    }

    pub fn associated_files() -> &'static [&'static str] {
        ASSOCIATED_FILES
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::{Read, Write};
    use utils::persistence::Volatile;
    use storage::RamStorage;

    #[test]
    fn overflowing_chunk_ref() {
        let mut store = ChunkedStorage::new(10, Box::new(RamStorage::new()));
        store.new_chunk(0);
        let data = (0..255u8).collect::<Vec<_>>();
        {
            let mut chunk_ref = store.get_current_mut(0);
            chunk_ref.write_all(&data).unwrap();
        }
        let mut read_data = Vec::new();
        {
            let mut chunk_ref = store.get_current(0);
            chunk_ref.read_to_end(&mut read_data).unwrap();
        }
        assert_eq!(data, read_data);
    }

    #[test]
    fn basic_chunk_ref() {
        let mut store = ChunkedStorage::new(10, Box::new(RamStorage::new()));
        store.new_chunk(0);
        let data = (0..20u8).collect::<Vec<_>>();
        {
            let mut chunk_ref = store.get_current_mut(0);
            chunk_ref.write_all(&data).unwrap();
        }
        let mut read_data = Vec::new();
        {
            let mut chunk_ref = store.get_current(0);
            chunk_ref.read_to_end(&mut read_data).unwrap();
        }
        assert_eq!(data, read_data);
    }

    #[test]
    fn repeated_writes() {
        let mut store = ChunkedStorage::new(10, Box::new(RamStorage::new()));
        store.new_chunk(0);
        let data = (0..20u8).collect::<Vec<_>>();
        {
            let mut chunk_ref = store.get_current_mut(0);
            chunk_ref.write_all(&data[0..10]).unwrap();
            chunk_ref.write_all(&data[10..20]).unwrap();
        }
        let mut read_data = Vec::new();
        {
            let mut chunk_ref = store.get_current(0);
            chunk_ref.read_to_end(&mut read_data).unwrap();
        }
        assert_eq!(data, read_data);
    }

    #[test]
    fn repeated_writes_overflowing() {
        let mut store = ChunkedStorage::new(10, Box::new(RamStorage::new()));
        store.new_chunk(0);
        let data = (0..255u8).collect::<Vec<_>>();
        {
            let mut chunk_ref = store.get_current_mut(0);
            chunk_ref.write_all(&data).unwrap();
            chunk_ref.write_all(&data).unwrap();
            chunk_ref.write_all(&data).unwrap();
        }
        let mut read_data = Vec::new();
        {
            let mut chunk_ref = store.get_current(0);
            chunk_ref.read_to_end(&mut read_data).unwrap();
        }
        assert_eq!(data, &read_data[0..255]);
        assert_eq!(data, &read_data[255..510]);
        assert_eq!(data, &read_data[510..765]);
    }
}
<commit_msg>Unit Test for ChunkRef::Read Bug<commit_after>use std::io;
use std::io::Write;
use std::fs::OpenOptions;
use std::path::Path;

use storage::{Storage, StorageError, Result, ByteEncodable, ByteDecodable};
use chunked_storage::indexing_chunk::HotIndexingChunk;
pub use chunked_storage::indexing_chunk::IndexingChunk;

mod indexing_chunk;

pub const SIZE: usize = 104;
const HOTCHUNKS_FILENAME: &'static str = "hot_chunks.bin";
const ASSOCIATED_FILES: &'static [&'static str; 1] = &[HOTCHUNKS_FILENAME];

pub struct MutChunkRef<'a> {
    chunk: &'a mut HotIndexingChunk,
    archive: &'a mut Box<Storage<IndexingChunk>>,
}

pub struct ChunkRef<'a> {
    read_ptr: usize,
    chunk: &'a HotIndexingChunk,
    archive: &'a Box<Storage<IndexingChunk>>,
}

// The idea here is the abstract the inner workings of chunked storage and indexing chunk from the index
// To do this, we implement Read and Write
impl<'a> io::Write for MutChunkRef<'a> {
    // Fill the HotIndexingChunk
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let bytes_written = try!((&mut self.chunk.data[SIZE - self.chunk.capacity as usize..]).write(buf));
        self.chunk.capacity -= bytes_written as u16;
        if self.chunk.capacity == 0 {
            let id = self.archive.len();

            match self.archive.store(id as u64, self.chunk.archive(id as u32)) {
                Ok(_) => {}
                Err(StorageError::IO(error)) |
                Err(StorageError::ReadError(Some(error))) |
                Err(StorageError::WriteError(Some(error))) => return Err(error),
                _ => return Err(io::Error::last_os_error()),
            }
        }
        Ok(bytes_written)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl<'a> io::Read for ChunkRef<'a> {
    // BULLSHIT. RETHINK THIS!
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut bytes_read = 0;
        loop {
            let chunk_id = self.read_ptr / SIZE;
            if chunk_id < self.chunk.archived_chunks().len() {
                let read = (&self.archive.get(chunk_id as u64).unwrap().get_bytes()[self.read_ptr % SIZE..])
                    .read(&mut buf[bytes_read..])
                    .unwrap();
                if read == 0 {
                    return Ok(bytes_read);
                }
                bytes_read += read;
                self.read_ptr += read;
            } else {
                break;
            }
        }
        let read = (&self.chunk.get_bytes()[self.read_ptr % SIZE..]).read(&mut buf[bytes_read..]).unwrap();
        bytes_read += read;
        self.read_ptr += read;
        Ok(bytes_read)
    }
}

impl<'a> MutChunkRef<'a> {
    #[inline]
    pub fn get_last_doc_id(&self) -> u64 {
        self.chunk.get_last_doc_id()
    }

    pub fn set_last_doc_id(&mut self, new_id: u64) {
        self.chunk.set_last_doc_id(new_id);
    }
}

// TODO: Think about implementing `Persistent` and `Volatile`
pub struct ChunkedStorage {
    hot_chunks: Vec<HotIndexingChunk>, // Size of vocabulary
    archive: Box<Storage<IndexingChunk>>,
}

impl ChunkedStorage {
    pub fn new(capacity: usize, archive: Box<Storage<IndexingChunk>>) -> Self {
        ChunkedStorage {
            hot_chunks: Vec::with_capacity(capacity),
            archive: archive,
        }
    }

    /// Persists hot_chunks to a file.
    /// We currently only need to persist hot_chunks
    /// Archive takes care of the rest
    pub fn persist(&self, target: &Path) -> Result<()> {
        let mut file =
            try!(OpenOptions::new().write(true).create(true).truncate(true).open(target.join(HOTCHUNKS_FILENAME)));
        for chunk in &self.hot_chunks {
            let bytes = chunk.encode();
            try!(file.write(&bytes));
        }
        Ok(())
    }

    pub fn load(source: &Path, archive: Box<Storage<IndexingChunk>>) -> Result<Self> {
        let mut file = try!(OpenOptions::new().read(true).open(source.join(HOTCHUNKS_FILENAME)));
        let mut hot_chunks = Vec::new();
        while let Ok(decoded_chunk) = HotIndexingChunk::decode(&mut file) {
            hot_chunks.push(decoded_chunk);
        }
        Ok(ChunkedStorage {
            hot_chunks: hot_chunks,
            archive: archive,
        })
    }

    pub fn new_chunk(&mut self, term_id: u64) -> MutChunkRef {
        // The following code-uglyness is due to the fact that in indexing one sort thread can
        // overtake the other. That means: ids are not just comming in an incremental order but can jump

        // If the id is larger than the len (e.g. can not be just pushed)
        // Push uninitialized chunks until the desired chunk can be created and pushed
        let diff = term_id as usize - self.hot_chunks.len();
        for _ in 0..diff + 1 {
            self.hot_chunks.push(HotIndexingChunk::new());
        }

        self.hot_chunks[term_id as usize] = HotIndexingChunk::new();
        MutChunkRef {
            chunk: &mut self.hot_chunks[term_id as usize],
            archive: &mut self.archive,
        }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.hot_chunks.len()
    }

    #[inline]
    pub fn get_current(&self, id: u64) -> ChunkRef {
        ChunkRef {
            read_ptr: 0,
            chunk: &self.hot_chunks[id as usize],
            archive: &self.archive,
        }
    }

    #[inline]
    pub fn get_current_mut(&mut self, id: u64) -> MutChunkRef {
        MutChunkRef {
            chunk: &mut self.hot_chunks[id as usize],
            archive: &mut self.archive,
        }
    }

    pub fn associated_files() -> &'static [&'static str] {
        ASSOCIATED_FILES
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::{Read, Write};
    use utils::persistence::Volatile;
    use storage::RamStorage;

    #[test]
    fn overflowing_chunk_ref() {
        let mut store = ChunkedStorage::new(10, Box::new(RamStorage::new()));
        store.new_chunk(0);
        let data = (0..255u8).collect::<Vec<_>>();
        {
            let mut chunk_ref = store.get_current_mut(0);
            chunk_ref.write_all(&data).unwrap();
        }
        let mut read_data = Vec::new();
        {
            let mut chunk_ref = store.get_current(0);
            chunk_ref.read_to_end(&mut read_data).unwrap();
        }
        assert_eq!(data, read_data);
    }

    #[test]
    fn basic_chunk_ref() {
        let mut store = ChunkedStorage::new(10, Box::new(RamStorage::new()));
        store.new_chunk(0);
        let data = (0..20u8).collect::<Vec<_>>();
        {
            let mut chunk_ref = store.get_current_mut(0);
            chunk_ref.write_all(&data).unwrap();
        }
        let mut read_data = Vec::new();
        {
            let mut chunk_ref = store.get_current(0);
            chunk_ref.read_to_end(&mut read_data).unwrap();
        }
        assert_eq!(data, read_data);
    }

    #[test]
    fn repeated_writes() {
        let mut store = ChunkedStorage::new(10, Box::new(RamStorage::new()));
        store.new_chunk(0);
        let data = (0..20u8).collect::<Vec<_>>();
        {
            let mut chunk_ref = store.get_current_mut(0);
            chunk_ref.write_all(&data[0..10]).unwrap();
            chunk_ref.write_all(&data[10..20]).unwrap();
        }
        let mut read_data = Vec::new();
        {
            let mut chunk_ref = store.get_current(0);
            chunk_ref.read_to_end(&mut read_data).unwrap();
        }
        assert_eq!(data, read_data);
    }

    #[test]
    fn repeated_writes_overflowing() {
        let mut store = ChunkedStorage::new(10, Box::new(RamStorage::new()));
        store.new_chunk(0);
        let data = (0..255u8).collect::<Vec<_>>();
        {
            let mut chunk_ref = store.get_current_mut(0);
            chunk_ref.write_all(&data).unwrap();
            chunk_ref.write_all(&data).unwrap();
            chunk_ref.write_all(&data).unwrap();
        }
        let mut read_data = Vec::new();
        {
            let mut chunk_ref = store.get_current(0);
            chunk_ref.read_to_end(&mut read_data).unwrap();
        }
        assert_eq!(data, &read_data[0..255]);
        assert_eq!(data, &read_data[255..510]);
        assert_eq!(data, &read_data[510..765]);
    }

    #[test]
    fn multiple_chunks() {
        let mut store = ChunkedStorage::new(10, Box::new(RamStorage::new()));
        for i in 0..100u8 {
            let data = (0..4096).map(|_| i).collect::<Vec<_>>();
            let mut chunk_ref = store.new_chunk(i as u64);
            chunk_ref.write_all(&data).unwrap();
        }
        for i in 0..100u8 {
            let data = (0..4096).map(|_| i).collect::<Vec<_>>();
            let mut chunk_ref = store.get_current(i as u64);
            let mut read_data = Vec::new();
            chunk_ref.read_to_end(&mut read_data).unwrap();
            assert_eq!(data, read_data);
        }
    }

}
<|endoftext|>


<commit_before>use perl_xs::IV;
use perl_xs::G_DISCARD;

static mut COUNTER: IV = 0;

struct Cnt;

impl Cnt {
    fn new() -> Cnt {
        unsafe { COUNTER = 0 };
        Cnt
    }
    fn get() -> IV {
        unsafe { COUNTER }
    }
}

impl Drop for Cnt {
    fn drop(&mut self) {
        unsafe { COUNTER += 1 };
    }
}

xs! {
    package XSTest::Panic;

    sub test_panic(_ctx) {
        let _cnt = Cnt::new();
        croak!("Panic!\n");
    }

    sub test_croak(ctx) {
        let _cnt = Cnt::new();
        ctx.call_pv(cstr!("XSTest::dies"), G_DISCARD);
        42 as IV
    }

    sub unwind_counter(_ctx) {
        Cnt::get()
    }
}
<commit_msg>Fix type inference<commit_after>use perl_xs::IV;
use perl_xs::G_DISCARD;

static mut COUNTER: IV = 0;

struct Cnt;

impl Cnt {
    fn new() -> Cnt {
        unsafe { COUNTER = 0 };
        Cnt
    }
    fn get() -> IV {
        unsafe { COUNTER }
    }
}

impl Drop for Cnt {
    fn drop(&mut self) {
        unsafe { COUNTER += 1 };
    }
}

xs! {
    package XSTest::Panic;

    sub test_panic(_ctx) {
        let _cnt = Cnt::new();
        croak!("Panic!\n");

        #[allow(unreachable_code)]
        ()
    }

    sub test_croak(ctx) {
        let _cnt = Cnt::new();
        ctx.call_pv(cstr!("XSTest::dies"), G_DISCARD);
        42 as IV
    }

    sub unwind_counter(_ctx) {
        Cnt::get()
    }
}
<|endoftext|>