<commit_before>use nom::{Err, IResult, Needed};

use std::io;
use std::io::Read;
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::Error),
  Incomplete(usize),
  Consumed(usize),
  EndOfInput,
  Unknown,
}

pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

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

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        if let Err::Position(_, i) = e {
          self.offset += self.len() - i.len();
        }

        Err(ErrorKind::Unknown)
      }
    }
  }
}

pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

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

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

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

  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity();

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      if let Err::Position(_, i) = e {
        Err(ErrorKind::Consumed(buffer.len() - i.len()))
      } else {
        Err(ErrorKind::Unknown)
      }
    }
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(ErrorKind::IO));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        match kind {
          ErrorKind::Incomplete(needed) => self.needed = needed,
          ErrorKind::Consumed(consumed) => buffer.consume(consumed),
          _                             => (),
        }

        Err(kind)
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg>Add test for `ByteStream::len` before parsing<commit_after>use nom::{Err, IResult, Needed};

use std::io;
use std::io::Read;
use std::ptr;
use std::cmp;

use super::StreamProducer;

#[derive(Debug)]
pub enum ErrorKind {
  IO(io::Error),
  Incomplete(usize),
  Consumed(usize),
  EndOfInput,
  Unknown,
}

pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

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

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        if let Err::Position(_, i) = e {
          self.offset += self.len() - i.len();
        }

        Err(ErrorKind::Unknown)
      }
    }
  }
}

pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

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

  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

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

  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity();

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      if let Err::Position(_, i) = e {
        Err(ErrorKind::Consumed(buffer.len() - i.len()))
      } else {
        Err(ErrorKind::Unknown)
      }
    }
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(ErrorKind::IO));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        match kind {
          ErrorKind::Incomplete(needed) => self.needed = needed,
          ErrorKind::Consumed(consumed) => buffer.consume(consumed),
          _                             => (),
        }

        Err(kind)
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::be_u32;

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>


<commit_before>use super::AttestationRecord;
use super::attestation_parent_hashes::{
    attestation_parent_hashes,
    ParentHashesError,
};
use super::db::{
    ClientDB,
    DBError
};
use super::db::stores::{
    BlockStore,
    ValidatorStore,
};
use super::ssz::SszStream;
use super::bls::{
    AggregateSignature,
    AggregatePublicKey,
    PublicKey,
};
use super::utils::hash::canonical_hash;
use super::utils::types::{
    Hash256,
    Bitfield,
};
use std::collections::HashMap;
use std::sync::Arc;

#[derive(Debug,PartialEq)]
pub enum AttestationValidationError {
    SlotTooHigh,
    SlotTooLow,
    JustifiedSlotTooHigh,
    TooManyObliqueHashes,
    BadCurrentHashes,
    BadObliqueHashes,
    BadAttesterMap,
    IntWrapping,
    IncorrectBitField,
    NoSignatures,
    NonZeroTrailingBits,
    AggregateSignatureFail
}

type Slot = u64;
type ShardId = u64;
type AttesterMap = HashMap<(Slot, ShardId), Vec<usize>>;

fn bytes_for_bits(bits: usize) -> usize {
    (bits.saturating_sub(1) / 8) + 1
}

pub fn validate_attestation<T>(a: &AttestationRecord,
                               block_slot: u64,
                               cycle_length: u8,
                               known_last_justified_slot: u64,
                               known_parent_hashes: Arc<Vec<Hash256>>,
                               block_store: BlockStore<T>,
                               attester_map: Arc<AttesterMap>)
    -> Result<bool, AttestationValidationError>
    where T: ClientDB + Sized
{
    /*
     * The attesation slot must not be higher than the block that contained it.
     */
    if a.slot > block_slot {
        return Err(AttestationValidationError::SlotTooHigh);
    }

    /*
     * The slot of this attestation must not be more than cycle_length + 1 distance
     * from the block that contained it.
     *
     * The below code stays overflow-safe as long as cycle length is a < 64 bit integer.
     */
    if a.slot < block_slot.saturating_sub(u64::from(cycle_length) + 1) {
        return Err(AttestationValidationError::SlotTooLow);
    }

    /*
     * The attestation must indicate that its last justified slot is the same as the last justified
     * slot known to us.
     */
    if a.justified_slot > known_last_justified_slot {
        return Err(AttestationValidationError::JustifiedSlotTooHigh);
    }

    /*
     * There is no need to include more oblique parents hashes than there are blocks
     * in a cycle.
     */
    if a.oblique_parent_hashes.len() > usize::from(cycle_length) {
        return Err(AttestationValidationError::TooManyObliqueHashes);
    }

    let attestation_indices = attester_map.get(&(a.slot, a.shard_id.into()))
        .ok_or(AttestationValidationError::BadAttesterMap)?;

    if a.attester_bitfield.num_bytes() !=
        bytes_for_bits(attestation_indices.len())
    {
        return Err(AttestationValidationError::IncorrectBitField);
    }

    let signed_message = {
        let parent_hashes = attestation_parent_hashes(
            cycle_length,
            block_slot,
            a.slot,
            &known_parent_hashes,
            &a.oblique_parent_hashes)?;
        generate_signed_message(
            a.slot,
            &parent_hashes,
            a.shard_id,
            &a.shard_block_hash,
            a.justified_slot)
    };

    Ok(false)
}

fn collect_pub_keys(attestation_indices: &Vec<usize>,
                    bitfield: &Bitfield)
    -> Option<Vec<PublicKey>>
{
    // cats
    None
}

/// Generates the message used to validate the signature provided with an AttestationRecord.
///
/// Ensures that the signer of the message has a view of the chain that is compatible with ours.
fn generate_signed_message(slot: u64,
                           parent_hashes: &[Hash256],
                           shard_id: u16,
                           shard_block_hash: &Hash256,
                           justified_slot: u64)
    -> Vec<u8>
{
    /*
     * Note: it's a little risky here to use SSZ, because the encoding is not necessarily SSZ
     * (for example, SSZ might change whilst this doesn't).
     *
     * I have suggested switching this to ssz here:
     * https://github.com/ethereum/eth2.0-specs/issues/5
     *
     * If this doesn't happen, it would be safer to not use SSZ at all.
     */
    let mut ssz_stream = SszStream::new();
    ssz_stream.append(&slot);
    for h in parent_hashes {
        ssz_stream.append_encoded_raw(&h.to_vec())
    }
    ssz_stream.append(&shard_id);
    ssz_stream.append(shard_block_hash);
    ssz_stream.append(&justified_slot);
    let bytes = ssz_stream.drain();
    canonical_hash(&bytes)
}

impl From<ParentHashesError> for AttestationValidationError {
    fn from(e: ParentHashesError) -> Self {
        match e {
            ParentHashesError::BadCurrentHashes =>
                AttestationValidationError::BadCurrentHashes,
            ParentHashesError::BadObliqueHashes =>
                AttestationValidationError::BadObliqueHashes,
            ParentHashesError::SlotTooLow =>
                AttestationValidationError::SlotTooLow,
            ParentHashesError::SlotTooHigh =>
                AttestationValidationError::SlotTooHigh,
            ParentHashesError::IntWrapping =>
                AttestationValidationError::IntWrapping
        }
    }
}
<commit_msg>Progress further on attestation validation<commit_after>use std::collections::HashSet;
use super::AttestationRecord;
use super::attestation_parent_hashes::{
    attestation_parent_hashes,
    ParentHashesError,
};
use super::db::{
    ClientDB,
    DBError
};
use super::db::stores::{
    BlockStore,
    ValidatorStore,
};
use super::ssz::SszStream;
use super::utils::hash::canonical_hash;
use super::utils::types::{
    Hash256,
};
use std::collections::HashMap;
use std::sync::Arc;
use super::signatures::{
    verify_aggregate_signature_for_indices,
    SignatureVerificationError,
};

#[derive(Debug,PartialEq)]
pub enum AttestationValidationError {
    SlotTooHigh,
    SlotTooLow,
    JustifiedSlotTooHigh,
    UnknownJustifiedBlock,
    TooManyObliqueHashes,
    BadCurrentHashes,
    BadObliqueHashes,
    BadAttesterMap,
    IntWrapping,
    PublicKeyCorrupt,
    NoPublicKeyForValidator,
    IncorrectBitField,
    NoSignatures,
    NonZeroTrailingBits,
    AggregateSignatureFail,
    DBError(String),
}

type Slot = u64;
type ShardId = u64;
type AttesterMap = HashMap<(Slot, ShardId), Vec<usize>>;

fn bytes_for_bits(bits: usize) -> usize {
    (bits.saturating_sub(1) / 8) + 1
}

pub fn validate_attestation<T>(a: &AttestationRecord,
                               block_slot: u64,
                               cycle_length: u8,
                               known_last_justified_slot: u64,
                               known_parent_hashes: Arc<Vec<Hash256>>,
                               block_store: BlockStore<T>,
                               validator_store: ValidatorStore<T>,
                               attester_map: Arc<AttesterMap>)
    -> Result<(bool, Option<HashSet<usize>>), AttestationValidationError>
    where T: ClientDB + Sized
{
    /*
     * The attesation slot must not be higher than the block that contained it.
     */
    if a.slot > block_slot {
        return Err(AttestationValidationError::SlotTooHigh);
    }

    /*
     * The slot of this attestation must not be more than cycle_length + 1 distance
     * from the block that contained it.
     *
     * The below code stays overflow-safe as long as cycle length is a < 64 bit integer.
     */
    if a.slot < block_slot.saturating_sub(u64::from(cycle_length) + 1) {
        return Err(AttestationValidationError::SlotTooLow);
    }

    /*
     * The attestation must indicate that its last justified slot is the same as the last justified
     * slot known to us.
     */
    if a.justified_slot > known_last_justified_slot {
        return Err(AttestationValidationError::JustifiedSlotTooHigh);
    }

    /*
     * There is no need to include more oblique parents hashes than there are blocks
     * in a cycle.
     */
    if a.oblique_parent_hashes.len() > usize::from(cycle_length) {
        return Err(AttestationValidationError::TooManyObliqueHashes);
    }

    /*
     * Retrieve the set of attestation indices for this slot and shard id.
     *
     * This is an array mapping the order that validators will appear in the bitfield to the
     * canonincal index of a validator.
     */
    let attestation_indices = attester_map.get(&(a.slot, a.shard_id.into()))
        .ok_or(AttestationValidationError::BadAttesterMap)?;

    /*
     * The bitfield must be no longer than the minimum required to represent each validator in the
     * attestation indicies for this slot and shard id.
     */
    if a.attester_bitfield.num_bytes() !=
        bytes_for_bits(attestation_indices.len())
    {
        return Err(AttestationValidationError::IncorrectBitField);
    }

    /*
     * If there are excess bits in the bitfield because the number of a validators in not a
     * multiple of 8, reject this attestation record.
     *
     * Allow extra set bits would permit mutliple different byte layouts (and therefore hashes) to
     * refer to the same AttesationRecord.
     */
    let last_byte =
        a.attester_bitfield.get_byte(a.attester_bitfield.num_bytes())
        .ok_or(AttestationValidationError::IncorrectBitField)?;
    if any_of_last_n_bits_are_set(last_byte, a.attester_bitfield.len() % 8) {
        return Err(AttestationValidationError::IncorrectBitField)
    }

    /*
     * The specified justified block hash must be known to us
     */
    if !block_store.block_exists(&a.justified_block_hash)? {
        return Err(AttestationValidationError::UnknownJustifiedBlock)
    }

    let signed_message = {
        let parent_hashes = attestation_parent_hashes(
            cycle_length,
            block_slot,
            a.slot,
            &known_parent_hashes,
            &a.oblique_parent_hashes)?;
        generate_signed_message(
            a.slot,
            &parent_hashes,
            a.shard_id,
            &a.shard_block_hash,
            a.justified_slot)
    };

    let (signature_valid, voted_hashmap) =
        verify_aggregate_signature_for_indices(
            &signed_message,
            &a.aggregate_sig,
            &attestation_indices,
            &a.attester_bitfield,
            &validator_store)?;

    Ok((signature_valid, voted_hashmap))
}

fn any_of_last_n_bits_are_set(byte: &u8, n: usize) -> bool {
    let shift = 8_u8.saturating_sub(n as u8);
    ((!0 >> shift) & byte) > 0
}

/// Generates the message used to validate the signature provided with an AttestationRecord.
///
/// Ensures that the signer of the message has a view of the chain that is compatible with ours.
fn generate_signed_message(slot: u64,
                           parent_hashes: &[Hash256],
                           shard_id: u16,
                           shard_block_hash: &Hash256,
                           justified_slot: u64)
    -> Vec<u8>
{
    /*
     * Note: it's a little risky here to use SSZ, because the encoding is not necessarily SSZ
     * (for example, SSZ might change whilst this doesn't).
     *
     * I have suggested switching this to ssz here:
     * https://github.com/ethereum/eth2.0-specs/issues/5
     *
     * If this doesn't happen, it would be safer to not use SSZ at all.
     */
    let mut ssz_stream = SszStream::new();
    ssz_stream.append(&slot);
    for h in parent_hashes {
        ssz_stream.append_encoded_raw(&h.to_vec())
    }
    ssz_stream.append(&shard_id);
    ssz_stream.append(shard_block_hash);
    ssz_stream.append(&justified_slot);
    let bytes = ssz_stream.drain();
    canonical_hash(&bytes)
}

impl From<ParentHashesError> for AttestationValidationError {
    fn from(e: ParentHashesError) -> Self {
        match e {
            ParentHashesError::BadCurrentHashes
                => AttestationValidationError::BadCurrentHashes,
            ParentHashesError::BadObliqueHashes
                => AttestationValidationError::BadObliqueHashes,
            ParentHashesError::SlotTooLow
                => AttestationValidationError::SlotTooLow,
            ParentHashesError::SlotTooHigh
                => AttestationValidationError::SlotTooHigh,
            ParentHashesError::IntWrapping
                => AttestationValidationError::IntWrapping
        }
    }
}

impl From<DBError> for AttestationValidationError {
    fn from(e: DBError) -> Self {
        AttestationValidationError::DBError(e.message)
    }
}

impl From<SignatureVerificationError> for AttestationValidationError {
    fn from(e: SignatureVerificationError) -> Self {
        match e {
            SignatureVerificationError::BadValidatorIndex
                => AttestationValidationError::BadAttesterMap,
            SignatureVerificationError::PublicKeyCorrupt
                => AttestationValidationError::PublicKeyCorrupt,
            SignatureVerificationError::NoPublicKeyForValidator
                => AttestationValidationError::NoPublicKeyForValidator,
            SignatureVerificationError::DBError(s)
                => AttestationValidationError::DBError(s),
        }
    }
}
<|endoftext|>


<commit_before>use chrono::{NaiveDate};

pub struct NewsItem {
    pub title: String,
    pub date: NaiveDate,
}

<commit_msg>Experimenting with mod and struct<commit_after>pub mod Home {
    use chrono::{NaiveDate};

    pub struct NewsItem {
        pub title: String,
        pub date: NaiveDate,
    }

    fn changeFuncName() -> NewsItem {
        let item :NewsItem = NewsItem{
                                title: String::from("Ethereum bounty contracts have now been added for anyone that would like to try to push the boundaries of human knowledge. The first contract is a competition for the correct solution to a³+b³+c³ = 33. Tweet me if you need assistance using these contracts!"),
                                date: NaiveDate::from_ymd(2019, 1, 22)
                            };
        item
    }

}<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

fn foo<T>() {}

fn main() {
    foo::<f64, bool>(); //~ ERROR E0087
    //~^ NOTE expected
}
<commit_msg>Update E0087.rs<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

fn foo<T>() {}

fn main() {
    foo::<f64, bool>(); //~ ERROR E0087
    //~^ NOTE expected
}
<|endoftext|>


<commit_before>use crate::hir::def::Namespace;
use crate::hir::{self, Local, Pat, Body, HirId};
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::infer::InferCtxt;
use crate::infer::type_variable::TypeVariableOriginKind;
use crate::ty::{self, Ty, Infer, TyVar};
use crate::ty::print::Print;
use syntax::source_map::CompilerDesugaringKind;
use syntax_pos::Span;
use errors::DiagnosticBuilder;

struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
    target_ty: Ty<'tcx>,
    hir_map: &'a hir::map::Map<'gcx>,
    found_local_pattern: Option<&'gcx Pat>,
    found_arg_pattern: Option<&'gcx Pat>,
    found_ty: Option<Ty<'tcx>>,
}

impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
    fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
        let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
            tables.borrow().node_type_opt(hir_id)
        });
        match ty_opt {
            Some(ty) => {
                let ty = self.infcx.resolve_vars_if_possible(&ty);
                if ty.walk().any(|inner_ty| {
                    inner_ty == self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
                        (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
                            self.infcx
                                .type_variables
                                .borrow_mut()
                                .sub_unified(a_vid, b_vid)
                        }
                        _ => false,
                    }
                }) {
                    Some(ty)
                } else {
                    None
                }
            }
            None => None,
        }
    }
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
        NestedVisitorMap::OnlyBodies(&self.hir_map)
    }

    fn visit_local(&mut self, local: &'gcx Local) {
        if let (None, Some(ty)) = (self.found_local_pattern, self.node_matches_type(local.hir_id)) {
            self.found_local_pattern = Some(&*local.pat);
            self.found_ty = Some(ty);
        }
        intravisit::walk_local(self, local);
    }

    fn visit_body(&mut self, body: &'gcx Body) {
        for argument in &body.arguments {
            if let (None, Some(ty)) = (
                self.found_arg_pattern,
                self.node_matches_type(argument.hir_id),
            ) {
                self.found_arg_pattern = Some(&*argument.pat);
                self.found_ty = Some(ty);
            }
        }
        intravisit::walk_body(self, body);
    }
}

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
    pub fn extract_type_name(
        &self,
        ty: Ty<'tcx>,
        highlight: Option<ty::print::RegionHighlightMode>,
    ) -> String {
        if let ty::Infer(ty::TyVar(ty_vid)) = ty.sty {
            let ty_vars = self.type_variables.borrow();
            if let TypeVariableOriginKind::TypeParameterDefinition(name) =
                ty_vars.var_origin(ty_vid).kind {
                return name.to_string();
            }
        }

        let mut s = String::new();
        let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
        if let Some(highlight) = highlight {
            printer.region_highlight_mode = highlight;
        }
        let _ = ty.print(printer);
        s
    }

    pub fn need_type_info_err(
        &self,
        body_id: Option<hir::BodyId>,
        span: Span,
        ty: Ty<'tcx>
    ) -> DiagnosticBuilder<'gcx> {
        let ty = self.resolve_vars_if_possible(&ty);
        let name = self.extract_type_name(&ty, None);

        let mut err_span = span;

        let mut local_visitor = FindLocalByTypeVisitor {
            infcx: &self,
            target_ty: ty,
            hir_map: &self.tcx.hir(),
            found_local_pattern: None,
            found_arg_pattern: None,
            found_ty: None,
        };
        let ty_to_string = |ty: Ty<'tcx>| -> String {
            let mut s = String::new();
            let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
            let ty_vars = self.type_variables.borrow();
            let getter = move |ty_vid| {
                if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
                    *ty_vars.var_origin(ty_vid) {
                    return Some(name.to_string());
                }
                None
            };
            printer.name_resolver = Some(Box::new(&getter));
            let _ = ty.print(printer);
            s
        };

        if let Some(body_id) = body_id {
            let expr = self.tcx.hir().expect_expr_by_hir_id(body_id.hir_id);
            local_visitor.visit_expr(expr);
        }

        // When `name` corresponds to a type argument, show the path of the full type we're
        // trying to infer. In the following example, `ty_msg` contains
        // " in `std::result::Result<i32, E>`":
        // ```
        // error[E0282]: type annotations needed for `std::result::Result<i32, E>`
        //  --> file.rs:L:CC
        //   |
        // L |     let b = Ok(4);
        //   |         -   ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
        //   |         |
        //   |         consider giving `b` the explicit type `std::result::Result<i32, E>`, where
        //   |         the type parameter `E` is specified
        // ```
        let (ty_msg, suffix) = match &local_visitor.found_ty {
            Some(ty) if &ty.to_string() != "_" && name == "_" => {
                let ty = ty_to_string(ty);
                (format!(" for `{}`", ty),
                 format!("the explicit type `{}`, with the type parameters specified", ty))
            }
            Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => {
                let ty = ty_to_string(ty);
                (format!(" for `{}`", ty),
                 format!(
                     "the explicit type `{}`, where the type parameter `{}` is specified",
                    ty,
                    name,
                 ))
            }
            _ => (String::new(), "a type".to_owned()),
        };
        let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];

        if let Some(pattern) = local_visitor.found_arg_pattern {
            err_span = pattern.span;
            // We don't want to show the default label for closures.
            //
            // So, before clearing, the output would look something like this:
            // ```
            // let x = |_| {  };
            //          -  ^^^^ cannot infer type for `[_; 0]`
            //          |
            //          consider giving this closure parameter a type
            // ```
            //
            // After clearing, it looks something like this:
            // ```
            // let x = |_| {  };
            //          ^ consider giving this closure parameter the type `[_; 0]`
            //            with the type parameter `_` specified
            // ```
            labels.clear();
            labels.push((
                pattern.span,
                format!("consider giving this closure parameter {}", suffix),
            ));
        } else if let Some(pattern) = local_visitor.found_local_pattern {
            if let Some(simple_ident) = pattern.simple_ident() {
                match pattern.span.compiler_desugaring_kind() {
                    None => labels.push((
                        pattern.span,
                        format!("consider giving `{}` {}", simple_ident, suffix),
                    )),
                    Some(CompilerDesugaringKind::ForLoop) => labels.push((
                        pattern.span,
                        "the element type for this iterator is not specified".to_owned(),
                    )),
                    _ => {}
                }
            } else {
                labels.push((pattern.span, format!("consider giving this pattern {}", suffix)));
            }
        };

        let mut err = struct_span_err!(
            self.tcx.sess,
            err_span,
            E0282,
            "type annotations needed{}",
            ty_msg,
        );

        for (target_span, label_message) in labels {
            err.span_label(target_span, label_message);
        }

        err
    }

    pub fn need_type_info_err_in_generator(
        &self,
        span: Span,
        ty: Ty<'tcx>
    ) -> DiagnosticBuilder<'gcx> {
        let ty = self.resolve_vars_if_possible(&ty);
        let name = self.extract_type_name(&ty, None);

        let mut err = struct_span_err!(self.tcx.sess,
                       span,
                       E0698,
                       "type inside generator must be known in this context");
        err.span_label(span, InferCtxt::missing_type_msg(&name));
        err
    }

    fn missing_type_msg(type_name: &str) -> String {
        if type_name == "_" {
            "cannot infer type".to_owned()
        } else {
            format!("cannot infer type for `{}`", type_name)
        }
    }
}
<commit_msg>Fix after rebase<commit_after>use crate::hir::def::Namespace;
use crate::hir::{self, Local, Pat, Body, HirId};
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::infer::InferCtxt;
use crate::infer::type_variable::TypeVariableOriginKind;
use crate::ty::{self, Ty, Infer, TyVar};
use crate::ty::print::Print;
use syntax::source_map::CompilerDesugaringKind;
use syntax_pos::Span;
use errors::DiagnosticBuilder;

struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
    target_ty: Ty<'tcx>,
    hir_map: &'a hir::map::Map<'gcx>,
    found_local_pattern: Option<&'gcx Pat>,
    found_arg_pattern: Option<&'gcx Pat>,
    found_ty: Option<Ty<'tcx>>,
}

impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
    fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
        let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
            tables.borrow().node_type_opt(hir_id)
        });
        match ty_opt {
            Some(ty) => {
                let ty = self.infcx.resolve_vars_if_possible(&ty);
                if ty.walk().any(|inner_ty| {
                    inner_ty == self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
                        (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
                            self.infcx
                                .type_variables
                                .borrow_mut()
                                .sub_unified(a_vid, b_vid)
                        }
                        _ => false,
                    }
                }) {
                    Some(ty)
                } else {
                    None
                }
            }
            None => None,
        }
    }
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
        NestedVisitorMap::OnlyBodies(&self.hir_map)
    }

    fn visit_local(&mut self, local: &'gcx Local) {
        if let (None, Some(ty)) = (self.found_local_pattern, self.node_matches_type(local.hir_id)) {
            self.found_local_pattern = Some(&*local.pat);
            self.found_ty = Some(ty);
        }
        intravisit::walk_local(self, local);
    }

    fn visit_body(&mut self, body: &'gcx Body) {
        for argument in &body.arguments {
            if let (None, Some(ty)) = (
                self.found_arg_pattern,
                self.node_matches_type(argument.hir_id),
            ) {
                self.found_arg_pattern = Some(&*argument.pat);
                self.found_ty = Some(ty);
            }
        }
        intravisit::walk_body(self, body);
    }
}

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
    pub fn extract_type_name(
        &self,
        ty: Ty<'tcx>,
        highlight: Option<ty::print::RegionHighlightMode>,
    ) -> String {
        if let ty::Infer(ty::TyVar(ty_vid)) = ty.sty {
            let ty_vars = self.type_variables.borrow();
            if let TypeVariableOriginKind::TypeParameterDefinition(name) =
                ty_vars.var_origin(ty_vid).kind {
                return name.to_string();
            }
        }

        let mut s = String::new();
        let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
        if let Some(highlight) = highlight {
            printer.region_highlight_mode = highlight;
        }
        let _ = ty.print(printer);
        s
    }

    pub fn need_type_info_err(
        &self,
        body_id: Option<hir::BodyId>,
        span: Span,
        ty: Ty<'tcx>
    ) -> DiagnosticBuilder<'gcx> {
        let ty = self.resolve_vars_if_possible(&ty);
        let name = self.extract_type_name(&ty, None);

        let mut err_span = span;

        let mut local_visitor = FindLocalByTypeVisitor {
            infcx: &self,
            target_ty: ty,
            hir_map: &self.tcx.hir(),
            found_local_pattern: None,
            found_arg_pattern: None,
            found_ty: None,
        };
        let ty_to_string = |ty: Ty<'tcx>| -> String {
            let mut s = String::new();
            let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
            let ty_vars = self.type_variables.borrow();
            let getter = move |ty_vid| {
                if let TypeVariableOriginKind::TypeParameterDefinition(name) =
                    ty_vars.var_origin(ty_vid).kind {
                    return Some(name.to_string());
                }
                None
            };
            printer.name_resolver = Some(Box::new(&getter));
            let _ = ty.print(printer);
            s
        };

        if let Some(body_id) = body_id {
            let expr = self.tcx.hir().expect_expr_by_hir_id(body_id.hir_id);
            local_visitor.visit_expr(expr);
        }

        // When `name` corresponds to a type argument, show the path of the full type we're
        // trying to infer. In the following example, `ty_msg` contains
        // " in `std::result::Result<i32, E>`":
        // ```
        // error[E0282]: type annotations needed for `std::result::Result<i32, E>`
        //  --> file.rs:L:CC
        //   |
        // L |     let b = Ok(4);
        //   |         -   ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
        //   |         |
        //   |         consider giving `b` the explicit type `std::result::Result<i32, E>`, where
        //   |         the type parameter `E` is specified
        // ```
        let (ty_msg, suffix) = match &local_visitor.found_ty {
            Some(ty) if &ty.to_string() != "_" && name == "_" => {
                let ty = ty_to_string(ty);
                (format!(" for `{}`", ty),
                 format!("the explicit type `{}`, with the type parameters specified", ty))
            }
            Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => {
                let ty = ty_to_string(ty);
                (format!(" for `{}`", ty),
                 format!(
                     "the explicit type `{}`, where the type parameter `{}` is specified",
                    ty,
                    name,
                 ))
            }
            _ => (String::new(), "a type".to_owned()),
        };
        let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];

        if let Some(pattern) = local_visitor.found_arg_pattern {
            err_span = pattern.span;
            // We don't want to show the default label for closures.
            //
            // So, before clearing, the output would look something like this:
            // ```
            // let x = |_| {  };
            //          -  ^^^^ cannot infer type for `[_; 0]`
            //          |
            //          consider giving this closure parameter a type
            // ```
            //
            // After clearing, it looks something like this:
            // ```
            // let x = |_| {  };
            //          ^ consider giving this closure parameter the type `[_; 0]`
            //            with the type parameter `_` specified
            // ```
            labels.clear();
            labels.push((
                pattern.span,
                format!("consider giving this closure parameter {}", suffix),
            ));
        } else if let Some(pattern) = local_visitor.found_local_pattern {
            if let Some(simple_ident) = pattern.simple_ident() {
                match pattern.span.compiler_desugaring_kind() {
                    None => labels.push((
                        pattern.span,
                        format!("consider giving `{}` {}", simple_ident, suffix),
                    )),
                    Some(CompilerDesugaringKind::ForLoop) => labels.push((
                        pattern.span,
                        "the element type for this iterator is not specified".to_owned(),
                    )),
                    _ => {}
                }
            } else {
                labels.push((pattern.span, format!("consider giving this pattern {}", suffix)));
            }
        };

        let mut err = struct_span_err!(
            self.tcx.sess,
            err_span,
            E0282,
            "type annotations needed{}",
            ty_msg,
        );

        for (target_span, label_message) in labels {
            err.span_label(target_span, label_message);
        }

        err
    }

    pub fn need_type_info_err_in_generator(
        &self,
        span: Span,
        ty: Ty<'tcx>
    ) -> DiagnosticBuilder<'gcx> {
        let ty = self.resolve_vars_if_possible(&ty);
        let name = self.extract_type_name(&ty, None);

        let mut err = struct_span_err!(self.tcx.sess,
                       span,
                       E0698,
                       "type inside generator must be known in this context");
        err.span_label(span, InferCtxt::missing_type_msg(&name));
        err
    }

    fn missing_type_msg(type_name: &str) -> String {
        if type_name == "_" {
            "cannot infer type".to_owned()
        } else {
            format!("cannot infer type for `{}`", type_name)
        }
    }
}
<|endoftext|>


<commit_before>use select::SelectResults;
use computed::ComputedStyle;
use n::h::CssHintLength;
use n::u::float_to_css_fixed;
use values::*;

pub struct CompleteSelectResults {
    inner: SelectResults
}

impl CompleteSelectResults {
    static fn new_root(root: SelectResults) -> CompleteSelectResults {
        CompleteSelectResults {
            inner: move root
        }
    }

    static fn new_from_parent(parent: &CompleteSelectResults,
                              child: SelectResults) -> CompleteSelectResults {
        let mut child = move child;

        // New lifetime
        {
            let parent_computed = parent.computed_style();
            let mut child_computed = child.computed_style();
            let net_parent_computed = &parent_computed.inner.inner;
            let net_child_computed = &mut child_computed.inner;
            // FIXME: Need to get real font sizes
            let cb: n::c::ComputeFontSizeCb = |parent: &Option<n::h::CssHint>|
                    -> n::h::CssHint {
                match *parent {
                    Some(CssHintLength(unit)) => CssHintLength(unit),
                    _ => n::h::CssHintLength(n::t::CssUnitPx(float_to_css_fixed(12.0))),
                }
            };
            n::c::compose(net_parent_computed, net_child_computed, cb, net_child_computed);
        }

        CompleteSelectResults {
            inner: move child
        }
    }

    fn computed_style(&self) -> CompleteStyle/&self {
        CompleteStyle {
            inner: self.inner.computed_style()
        }
    }
}

pub struct CompleteStyle {
    inner: ComputedStyle
}

impl CompleteStyle {

    // CSS 2.1, Section 8 - Box model

    pub fn margin_top() -> CSSMargin {
        strip(self.inner.margin_top())
    }

    pub fn margin_right() -> CSSMargin {
        strip(self.inner.margin_right())
    }

    pub fn margin_bottom() -> CSSMargin {
        strip(self.inner.margin_bottom())
    }

    pub fn margin_left() -> CSSMargin {
        strip(self.inner.margin_left())
    }

    pub fn border_top_width() -> CSSBorderWidth {
        strip(self.inner.border_top_width())
    }

    pub fn border_right_width() -> CSSBorderWidth {
        strip(self.inner.border_right_width())
    }

    pub fn border_bottom_width() -> CSSBorderWidth {
        strip(self.inner.border_bottom_width())
    }

    pub fn border_left_width() -> CSSBorderWidth {
        strip(self.inner.border_left_width())
    }

    pub fn border_top_color() -> Color {
        strip(self.inner.border_top_color())
    }

    pub fn border_top_color() -> Color {
        strip(self.inner.border_top_color())
    }

    pub fn border_right_color() -> Color {
        strip(self.inner.border_right_color())
    }

    pub fn border_bottom_color() -> Color {
        strip(self.inner.border_bottom_color())
    }

    pub fn border_left_color() -> Color {
        strip(self.inner.border_left_color())
    }

    // CSS 2.1, Section 9 - Visual formatting model

    pub fn display(root: bool) -> CSSDisplay {
        strip(self.inner.display(root))
    }

    pub fn position() -> CSSPosition {
        strip(self.inner.position())
    }

    pub fn float() -> CSSFloat {
        strip(self.inner.float())
    }

    // CSS 2.1, Section 10 - Visual formatting model details

    pub fn width() -> CSSWidth {
        strip(self.inner.width())
    }

    pub fn height() -> CSSHeight {
        strip(self.inner.height())
    }

    // CSS 2.1, Section 11 - Visual effects

    // CSS 2.1, Section 12 - Generated content, automatic numbering, and lists

    // CSS 2.1, Section 13 - Paged media

    // CSS 2.1, Section 14 - Colors and Backgrounds

    pub fn background_color() -> Color {
        strip(self.inner.background_color())
    }

    pub fn color() -> Color {
        strip(self.inner.color())
    }

    // CSS 2.1, Section 15 - Fonts

    pub fn font_family() -> ~[CSSFontFamily] {
        strip(self.inner.font_family())
    }

    pub fn font_style() -> CSSFontStyle {
        strip(self.inner.font_style())
    }

    pub fn font_weight() -> CSSFontWeight {
        strip(self.inner.font_weight())
    }

    pub fn font_size() -> CSSFontSize {
        strip(self.inner.font_size())
    }

    // CSS 2.1, Section 16 - Text

    pub fn text_align() -> CSSTextAlign {
        strip(self.inner.text_align())
    }

    // CSS 2.1, Section 17 - Tables

    // CSS 2.1, Section 18 - User interface

}

fn strip<T>(value: CSSValue<T>) -> T {
    match move value {
        Inherit => fail ~"unexpected 'inherit' value in complete style",
        Specified(move v) => move v
    }
}

<commit_msg>Write a better font size computer<commit_after>use select::SelectResults;
use computed::ComputedStyle;
use n::h::CssHintLength;
use n::u::float_to_css_fixed;
use values::*;

pub struct CompleteSelectResults {
    inner: SelectResults
}

impl CompleteSelectResults {
    static fn new_root(root: SelectResults) -> CompleteSelectResults {
        CompleteSelectResults {
            inner: move root
        }
    }

    static fn new_from_parent(parent: &CompleteSelectResults,
                              child: SelectResults) -> CompleteSelectResults {
        let mut child = move child;

        // New lifetime
        {
            let parent_computed = parent.computed_style();
            let mut child_computed = child.computed_style();
            let net_parent_computed = &parent_computed.inner.inner;
            let net_child_computed = &mut child_computed.inner;
            // FIXME: Need to get real font sizes
            let cb: n::c::ComputeFontSizeCb =
                |parent: &Option<n::h::CssHint>, child: &n::h::CssHint| -> n::h::CssHint {
                match *child {
                    CssHintLength(n::t::CssUnitEm(child_em)) => {
                        match *parent {
                            Some(CssHintLength(parent_unit)) => {
                                // CSS3 Values 5.1.1: Multiply parent unit by child unit.
                                let mut new_value =
                                    n::u::css_fixed_to_float(parent_unit.to_css_fixed());
                                new_value *= n::u::css_fixed_to_float(child_em);
                                let unit = parent_unit.modify(n::u::float_to_css_fixed(
                                    new_value));
                                CssHintLength(move unit)
                            }
                            _ => n::h::CssHintLength(n::t::CssUnitEm(child_em)),
                        }
                    }
                    CssHintLength(unit) => CssHintLength(unit),
                    _ => {
                        n::h::CssHintLength(n::t::CssUnitPx(float_to_css_fixed(16.0)))
                    }
                }
            };
            n::c::compose(net_parent_computed, net_child_computed, cb, net_child_computed);
        }

        CompleteSelectResults {
            inner: move child
        }
    }

    fn computed_style(&self) -> CompleteStyle/&self {
        CompleteStyle {
            inner: self.inner.computed_style()
        }
    }
}

pub struct CompleteStyle {
    inner: ComputedStyle
}

impl CompleteStyle {

    // CSS 2.1, Section 8 - Box model

    pub fn margin_top() -> CSSMargin {
        strip(self.inner.margin_top())
    }

    pub fn margin_right() -> CSSMargin {
        strip(self.inner.margin_right())
    }

    pub fn margin_bottom() -> CSSMargin {
        strip(self.inner.margin_bottom())
    }

    pub fn margin_left() -> CSSMargin {
        strip(self.inner.margin_left())
    }

    pub fn border_top_width() -> CSSBorderWidth {
        strip(self.inner.border_top_width())
    }

    pub fn border_right_width() -> CSSBorderWidth {
        strip(self.inner.border_right_width())
    }

    pub fn border_bottom_width() -> CSSBorderWidth {
        strip(self.inner.border_bottom_width())
    }

    pub fn border_left_width() -> CSSBorderWidth {
        strip(self.inner.border_left_width())
    }

    pub fn border_top_color() -> Color {
        strip(self.inner.border_top_color())
    }

    pub fn border_top_color() -> Color {
        strip(self.inner.border_top_color())
    }

    pub fn border_right_color() -> Color {
        strip(self.inner.border_right_color())
    }

    pub fn border_bottom_color() -> Color {
        strip(self.inner.border_bottom_color())
    }

    pub fn border_left_color() -> Color {
        strip(self.inner.border_left_color())
    }

    // CSS 2.1, Section 9 - Visual formatting model

    pub fn display(root: bool) -> CSSDisplay {
        strip(self.inner.display(root))
    }

    pub fn position() -> CSSPosition {
        strip(self.inner.position())
    }

    pub fn float() -> CSSFloat {
        strip(self.inner.float())
    }

    // CSS 2.1, Section 10 - Visual formatting model details

    pub fn width() -> CSSWidth {
        strip(self.inner.width())
    }

    pub fn height() -> CSSHeight {
        strip(self.inner.height())
    }

    // CSS 2.1, Section 11 - Visual effects

    // CSS 2.1, Section 12 - Generated content, automatic numbering, and lists

    // CSS 2.1, Section 13 - Paged media

    // CSS 2.1, Section 14 - Colors and Backgrounds

    pub fn background_color() -> Color {
        strip(self.inner.background_color())
    }

    pub fn color() -> Color {
        strip(self.inner.color())
    }

    // CSS 2.1, Section 15 - Fonts

    pub fn font_family() -> ~[CSSFontFamily] {
        strip(self.inner.font_family())
    }

    pub fn font_style() -> CSSFontStyle {
        strip(self.inner.font_style())
    }

    pub fn font_weight() -> CSSFontWeight {
        strip(self.inner.font_weight())
    }

    pub fn font_size() -> CSSFontSize {
        strip(self.inner.font_size())
    }

    // CSS 2.1, Section 16 - Text

    pub fn text_align() -> CSSTextAlign {
        strip(self.inner.text_align())
    }

    // CSS 2.1, Section 17 - Tables

    // CSS 2.1, Section 18 - User interface

}

fn strip<T>(value: CSSValue<T>) -> T {
    match move value {
        Inherit => fail ~"unexpected 'inherit' value in complete style",
        Specified(move v) => move v
    }
}

<|endoftext|>


<commit_before>//use dom::bindings::clientrect::ClientRect;
use dom::bindings::utils::WrapperCache;

pub struct ClientRect {
    wrapper: WrapperCache,
    top: f32,
    bottom: f32,
    left: f32,
    right: f32,
}

pub impl ClientRect {
    fn new(top: f32, bottom: f32, left: f32, right: f32) -> @mut ClientRect {
        let rect = @mut ClientRect {
            top: top, bottom: bottom, left: left, right: right,
            wrapper: WrapperCache::new()
        };
        rect.init_wrapper();
        rect
    }

    fn Top(&self) -> f32 {
        self.top
    }

    fn Bottom(&self) -> f32 {
        self.bottom
    }

    fn Left(&self) -> f32 {
        self.left
    }

    fn Right(&self) -> f32 {
        self.right
    }

    fn Width(&self) -> f32 {
        f32::abs(self.right - self.left)
    }

    fn Height(&self) -> f32 {
        f32::abs(self.bottom - self.top)
    }
}
<commit_msg>Adjust code style in clientrect<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/. */

use dom::bindings::utils::WrapperCache;

pub struct ClientRect {
    wrapper: WrapperCache,
    top: f32,
    bottom: f32,
    left: f32,
    right: f32,
}

impl ClientRect {
    pub fn new(top: f32, bottom: f32, left: f32, right: f32) -> @mut ClientRect {
        let rect = @mut ClientRect {
            top: top,
            bottom: bottom,
            left: left,
            right: right,
            wrapper: WrapperCache::new()
        };
        rect.init_wrapper();
        rect
    }

    pub fn Top(&self) -> f32 {
        self.top
    }

    pub fn Bottom(&self) -> f32 {
        self.bottom
    }

    pub fn Left(&self) -> f32 {
        self.left
    }

    pub fn Right(&self) -> f32 {
        self.right
    }

    pub fn Width(&self) -> f32 {
        f32::abs(self.right - self.left)
    }

    pub fn Height(&self) -> f32 {
        f32::abs(self.bottom - self.top)
    }
}

<|endoftext|>


<commit_before>//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.
extern crate typed_arena;

use doc::{
    best,
};
use doc::Doc::{
    Append,
    Group,
    Nest,
    Newline,
    Nil,
    Text,
};
use std::io;
use std::borrow::Cow;
use std::ops::Deref;

use typed_arena::Arena;

mod doc;

pub type Doc<'a, B> = doc::Doc<'a, B>;

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct BoxDoc<'a>(Box<doc::Doc<'a, BoxDoc<'a>>>);

impl<'a> BoxDoc<'a> {
    fn new(doc: doc::Doc<'a, BoxDoc<'a>>) -> BoxDoc<'a> {
        BoxDoc(Box::new(doc))
    }
}

impl<'a> Deref for BoxDoc<'a> {
    type Target = doc::Doc<'a, BoxDoc<'a>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

pub struct DocBuilder<'a, A: ?Sized>(pub &'a A, pub doc::Doc<'a, A::Doc>)
    where A: Allocator<'a> + 'a;

impl <'a, A> Into<doc::Doc<'a, A::Doc>> for DocBuilder<'a, A>
    where A: Allocator<'a>
{
    fn into(self) -> doc::Doc<'a, A::Doc> {
        self.1
    }
}

pub trait Allocator<'a> {
    type Doc: Deref<Target = doc::Doc<'a, Self::Doc>> + Clone;
    fn alloc(&'a self, doc::Doc<'a, Self::Doc>) -> Self::Doc;

    #[inline]
    fn nil(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Nil)
    }

    #[inline]
    fn newline(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Newline)
    }

    #[inline]
    fn as_string<T: ToString>(&'a self, t: T) -> DocBuilder<'a, Self> {
        self.text(t.to_string())
    }

    #[inline]
    fn text<T: Into<Cow<'a, str>>>(&'a self, data: T) -> DocBuilder<'a, Self> {
        DocBuilder(self, Text(data.into()))
    }

    #[inline]
    fn concat<I>(&'a self, docs: I) -> DocBuilder<'a, Self>
    where I: IntoIterator<Item = doc::Doc<'a, Self::Doc>>
    {
        docs.into_iter().fold(self.nil(), |a, b| a.append(b))
    }
}

impl<'a, 's, A: ?Sized> DocBuilder<'a, A> where A: Allocator<'a> {
    #[inline]
    pub fn append<B>(self, that: B) -> DocBuilder<'a, A>
    where B: Into<doc::Doc<'a, A::Doc>>,
    {
        let DocBuilder(allocator, this) = self;
        let that = that.into();
        let doc = match this {
            Nil  => that,
            _ => match that {
                Nil  => this,
                _ => Append(allocator.alloc(this), allocator.alloc(that)),
            }
        };
        DocBuilder(allocator, doc)
    }

    #[inline]
    pub fn group(self) -> DocBuilder<'a, A>
    {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Group(allocator.alloc(this)))
    }

    #[inline]
    pub fn nest(self, offset: usize) -> DocBuilder<'a, A>
    {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Nest(offset, allocator.alloc(this)))
    }
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct RefDoc<'a>(&'a doc::Doc<'a, RefDoc<'a>>);

impl<'a> Deref for RefDoc<'a> {
    type Target = doc::Doc<'a, RefDoc<'a>>;

    fn deref(&self) -> &doc::Doc<'a, RefDoc<'a>> {
        &self.0
    }
}

impl<'a> Allocator<'a> for Arena<doc::Doc<'a, RefDoc<'a>>> {
    type Doc = RefDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        RefDoc(Arena::alloc(self, doc))
    }
}

pub struct BoxAllocator;

impl<'a> Allocator<'a> for BoxAllocator {
    type Doc = BoxDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        BoxDoc::new(doc)
    }
}
impl<'a> BoxDoc<'a> {
    #[inline]
    pub fn nil() -> BoxDoc<'a> {
        BoxDoc::new(Nil)
    }

    #[inline]
    pub fn append(self, that: BoxDoc<'a>) -> BoxDoc<'a> {
        match &*self {
            &Nil  => that,
            _ => match &*that {
                &Nil  => self,
                _ => BoxDoc::new(Append(self, that)),
            }
        }
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> BoxDoc<'a> {
        BoxDoc::text(t.to_string())
    }

    #[inline]
    pub fn concat<I>(&'a self, docs: I) -> BoxDoc<'a>
    where I: IntoIterator<Item = BoxDoc<'a>>
    {
        docs.into_iter().fold(BoxDoc::nil(), |a, b| a.append(b))
    }

    #[inline]
    pub fn group(self) -> BoxDoc<'a> {
        BoxDoc::new(Group(self))
    }

    #[inline]
    pub fn nest(self, offset: usize) -> BoxDoc<'a> {
        BoxDoc::new(Nest(offset, self))
    }

    #[inline]
    pub fn newline() -> BoxDoc<'a> {
        BoxDoc::new(Newline)
    }

    #[inline]
    pub fn render<W: io::Write>(&self, width: usize, out: &mut W) -> io::Result<()> {
        let &BoxDoc(ref doc) = self;
        best(doc, width, out).and_then(|()| out.write_all(b"\n"))
    }

    #[inline]
    pub fn text<T: Into<Cow<'a, str>>>(data: T) -> BoxDoc<'a> {
        BoxDoc::new(Text(data.into()))
    }
}
<commit_msg>Delay boxing of boxed docs until it is actually necessary<commit_after>//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.
extern crate typed_arena;

use doc::Doc::{
    Append,
    Group,
    Nest,
    Newline,
    Nil,
    Text,
};
use std::borrow::Cow;
use std::ops::Deref;

use typed_arena::Arena;

mod doc;

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct BoxDoc<'a>(Box<doc::Doc<'a, BoxDoc<'a>>>);

impl<'a> BoxDoc<'a> {
    fn new(doc: doc::Doc<'a, BoxDoc<'a>>) -> BoxDoc<'a> {
        BoxDoc(Box::new(doc))
    }
}

impl<'a> Deref for BoxDoc<'a> {
    type Target = doc::Doc<'a, BoxDoc<'a>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

pub struct DocBuilder<'a, A: ?Sized>(pub &'a A, pub doc::Doc<'a, A::Doc>)
    where A: Allocator<'a> + 'a;

impl <'a, A> Into<doc::Doc<'a, A::Doc>> for DocBuilder<'a, A>
    where A: Allocator<'a>
{
    fn into(self) -> doc::Doc<'a, A::Doc> {
        self.1
    }
}

pub trait Allocator<'a> {
    type Doc: Deref<Target = doc::Doc<'a, Self::Doc>> + Clone;
    fn alloc(&'a self, doc::Doc<'a, Self::Doc>) -> Self::Doc;

    #[inline]
    fn nil(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Nil)
    }

    #[inline]
    fn newline(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Newline)
    }

    #[inline]
    fn as_string<T: ToString>(&'a self, t: T) -> DocBuilder<'a, Self> {
        self.text(t.to_string())
    }

    #[inline]
    fn text<T: Into<Cow<'a, str>>>(&'a self, data: T) -> DocBuilder<'a, Self> {
        DocBuilder(self, Text(data.into()))
    }

    #[inline]
    fn concat<I>(&'a self, docs: I) -> DocBuilder<'a, Self>
    where I: IntoIterator<Item = doc::Doc<'a, Self::Doc>>
    {
        docs.into_iter().fold(self.nil(), |a, b| a.append(b))
    }
}

impl<'a, 's, A: ?Sized> DocBuilder<'a, A> where A: Allocator<'a> {
    #[inline]
    pub fn append<B>(self, that: B) -> DocBuilder<'a, A>
    where B: Into<doc::Doc<'a, A::Doc>>,
    {
        let DocBuilder(allocator, this) = self;
        let that = that.into();
        let doc = match this {
            Nil  => that,
            _ => match that {
                Nil  => this,
                _ => Append(allocator.alloc(this), allocator.alloc(that)),
            }
        };
        DocBuilder(allocator, doc)
    }

    #[inline]
    pub fn group(self) -> DocBuilder<'a, A>
    {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Group(allocator.alloc(this)))
    }

    #[inline]
    pub fn nest(self, offset: usize) -> DocBuilder<'a, A>
    {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Nest(offset, allocator.alloc(this)))
    }
}

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct RefDoc<'a>(&'a doc::Doc<'a, RefDoc<'a>>);

impl<'a> Deref for RefDoc<'a> {
    type Target = doc::Doc<'a, RefDoc<'a>>;

    fn deref(&self) -> &doc::Doc<'a, RefDoc<'a>> {
        &self.0
    }
}

impl<'a> Allocator<'a> for Arena<doc::Doc<'a, RefDoc<'a>>> {
    type Doc = RefDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        RefDoc(Arena::alloc(self, doc))
    }
}

pub struct BoxAllocator;

static BOX_ALLOCATOR: BoxAllocator = BoxAllocator;

impl<'a> Allocator<'a> for BoxAllocator {
    type Doc = BoxDoc<'a>;

    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        BoxDoc::new(doc)
    }
}

pub type Doc<'a> = doc::Doc<'a, BoxDoc<'a>>;

impl<'a> Doc<'a> {
    #[inline]
    pub fn nil() -> Doc<'a> {
        Nil
    }

    #[inline]
    pub fn append(self, that: Doc<'a>) -> Doc<'a> {
        DocBuilder(&BOX_ALLOCATOR, self).append(that).into()
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> Doc<'a> {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat<I>(&'a self, docs: I) -> Doc<'a>
    where I: IntoIterator<Item = Doc<'a>>
    {
        docs.into_iter().fold(Doc::nil(), |a, b| a.append(b))
    }

    #[inline]
    pub fn group(self) -> Doc<'a> {
        DocBuilder(&BOX_ALLOCATOR, self).group().into()
    }

    #[inline]
    pub fn nest(self, offset: usize) -> Doc<'a> {
        DocBuilder(&BOX_ALLOCATOR, self).nest(offset).into()
    }

    #[inline]
    pub fn newline() -> Doc<'a> {
        Newline
    }

    #[inline]
    pub fn text<T: Into<Cow<'a, str>>>(data: T) -> Doc<'a> {
        Text(data.into())
    }
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(core)]
#![feature(old_io)]

//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.

use doc::{
    best,
};
use doc::Doc::{
    Append,
    Group,
    Nest,
    Newline,
    Nil,
    Text,
};
use std::old_io as io;
use std::borrow::{
    IntoCow,
};

mod doc;

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Doc<'a>(doc::Doc<'a>);

impl<'a> Doc<'a> {
    #[inline]
    pub fn nil() -> Doc<'a> {
        Doc(Nil)
    }

    #[inline]
    pub fn append(self, that: Doc<'a>) -> Doc<'a> {
        let Doc(ldoc) = self;
        let Doc(rdoc) = that;
        let res = match ldoc {
            Nil  => rdoc,
            ldoc => match rdoc {
                Nil  => ldoc,
                rdoc => Append(Box::new(ldoc), Box::new(rdoc)),
            }
        };
        Doc(res)
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> Doc<'a> {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat(ds: &[Doc<'a>]) -> Doc<'a> {
        ds.iter().fold(Doc::nil(), |a, b| a.append(b.clone()))
    }

    #[inline]
    pub fn group(self) -> Doc<'a> {
        let Doc(doc) = self;
        Doc(Group(Box::new(doc)))
    }

    #[inline]
    pub fn nest(self, off: usize) -> Doc<'a> {
        let Doc(doc) = self;
        Doc(Nest(off, Box::new(doc)))
    }

    #[inline]
    pub fn newline() -> Doc<'a> {
        Doc(Newline)
    }

    #[inline]
    pub fn render<W: io::Writer>(&self, width: usize, out: &mut W) -> io::IoResult<()> {
        let &Doc(ref doc) = self;
        best(doc, width, out).and_then(|()| out.write_line(""))
    }

    #[inline]
    pub fn text<T: IntoCow<'a, String, str>>(data: T) -> Doc<'a> {
        Doc(Text(data.into_cow()))
    }
}
<commit_msg>Disable feature core<commit_after>#![feature(collections)]
#![feature(old_io)]

//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.

use doc::{
    best,
};
use doc::Doc::{
    Append,
    Group,
    Nest,
    Newline,
    Nil,
    Text,
};
use std::old_io as io;
use std::borrow::{
    IntoCow,
};

mod doc;

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Doc<'a>(doc::Doc<'a>);

impl<'a> Doc<'a> {
    #[inline]
    pub fn nil() -> Doc<'a> {
        Doc(Nil)
    }

    #[inline]
    pub fn append(self, that: Doc<'a>) -> Doc<'a> {
        let Doc(ldoc) = self;
        let Doc(rdoc) = that;
        let res = match ldoc {
            Nil  => rdoc,
            ldoc => match rdoc {
                Nil  => ldoc,
                rdoc => Append(Box::new(ldoc), Box::new(rdoc)),
            }
        };
        Doc(res)
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> Doc<'a> {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn concat(ds: &[Doc<'a>]) -> Doc<'a> {
        ds.iter().fold(Doc::nil(), |a, b| a.append(b.clone()))
    }

    #[inline]
    pub fn group(self) -> Doc<'a> {
        let Doc(doc) = self;
        Doc(Group(Box::new(doc)))
    }

    #[inline]
    pub fn nest(self, off: usize) -> Doc<'a> {
        let Doc(doc) = self;
        Doc(Nest(off, Box::new(doc)))
    }

    #[inline]
    pub fn newline() -> Doc<'a> {
        Doc(Newline)
    }

    #[inline]
    pub fn render<W: io::Writer>(&self, width: usize, out: &mut W) -> io::IoResult<()> {
        let &Doc(ref doc) = self;
        best(doc, width, out).and_then(|()| out.write_line(""))
    }

    #[inline]
    pub fn text<T: IntoCow<'a, String, str>>(data: T) -> Doc<'a> {
        Doc(Text(data.into_cow()))
    }
}
<|endoftext|>


<commit_before>use std::fmt::Display;
use std::iter::Iterator;

use buffer::Buffer;
use widgets::{Widget, Block};
use layout::Rect;
use style::Style;

pub enum Row<'i, D, I>
where
    D: Iterator<Item = I>,
    I: Display,
{
    Data(D),
    StyledData(D, &'i Style),
}

/// A widget to display data in formatted column
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, border, Table};
/// # use tui::style::{Style, Color};
/// # fn main() {
/// let row_style = Style::default().fg(Color::White);
/// Table::default()
///     .block(Block::default().title("Table"))
///     .header(&["Col1", "Col2", "Col3"])
///     .header_style(Style::default().fg(Color::Yellow))
///     .widths(&[5, 5, 10])
///     .style(Style::default().fg(Color::White))
///     .column_spacing(1)
///     .rows(&[(&["Row11", "Row12", "Row13"], &row_style),
///             (&["Row21", "Row22", "Row23"], &row_style),
///             (&["Row31", "Row32", "Row33"], &row_style)]);
/// # }
/// ```
pub struct Table<'a, 'i, T, H, I, D, R>
where
    T: Display,
    H: Iterator<Item = T>,
    I: Display,
    D: Iterator<Item = I>,
    R: Iterator<Item = Row<'i, D, I>>,
{
    /// A block to wrap the widget in
    block: Option<Block<'a>>,
    /// Base style for the widget
    style: Style,
    /// Header row for all columns
    header: H,
    /// Style for the header
    header_style: Style,
    /// Width of each column (if the total width is greater than the widget width some columns may
    /// not be displayed)
    widths: &'a [u16],
    /// Space between each column
    column_spacing: u16,
    /// Data to display in each row
    rows: R,
}

impl<'a, 'i, T, H, I, D, R> Default for Table<'a, 'i, T, H, I, D, R>
where
    T: Display,
    H: Iterator<Item = T> + Default,
    I: Display,
    D: Iterator<Item = I>,
    R: Iterator<Item = Row<'i, D, I>>
        + Default,
{
    fn default() -> Table<'a, 'i, T, H, I, D, R> {
        Table {
            block: None,
            style: Style::default(),
            header: H::default(),
            header_style: Style::default(),
            widths: &[],
            rows: R::default(),
            column_spacing: 1,
        }
    }
}

impl<'a, 'i, T, H, I, D, R> Table<'a, 'i, T, H, I, D, R>
where
    T: Display,
    H: Iterator<Item = T>,
    I: Display,
    D: Iterator<Item = I>,
    R: Iterator<Item = Row<'i, D, I>>,
{
    pub fn new(header: H, rows: R) -> Table<'a, 'i, T, H, I, D, R> {
        Table {
            block: None,
            style: Style::default(),
            header: header,
            header_style: Style::default(),
            widths: &[],
            rows: rows,
            column_spacing: 1,
        }
    }
    pub fn block(&'a mut self, block: Block<'a>) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.block = Some(block);
        self
    }

    pub fn header<II>(&mut self, header: II) -> &mut Table<'a, 'i, T, H, I, D, R>
    where
        II: IntoIterator<Item = T, IntoIter = H>,
    {
        self.header = header.into_iter();
        self
    }

    pub fn header_style(&mut self, style: Style) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.header_style = style;
        self
    }

    pub fn widths(&mut self, widths: &'a [u16]) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.widths = widths;
        self
    }

    pub fn rows<II>(&mut self, rows: II) -> &mut Table<'a, 'i, T, H, I, D, R>
    where
        II: IntoIterator<Item = Row<'i, D, I>, IntoIter = R>,
    {
        self.rows = rows.into_iter();
        self
    }

    pub fn style(&mut self, style: Style) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.style = style;
        self
    }

    pub fn column_spacing(&mut self, spacing: u16) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.column_spacing = spacing;
        self
    }
}

impl<'a, 'i, T, H, I, D, R> Widget for Table<'a, 'i, T, H, I, D, R>
where
    T: Display,
    H: Iterator<Item = T>,
    I: Display,
    D: Iterator<Item = I>,
    R: Iterator<Item = Row<'i, D, I>>,
{
    fn draw(&mut self, area: &Rect, buf: &mut Buffer) {

        // Render block if necessary and get the drawing area
        let table_area = match self.block {
            Some(ref mut b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => *area,
        };

        // Set the background
        self.background(&table_area, buf, self.style.bg);

        // Save the widths of the columns that will fit in the given area
        let mut x = 0;
        let mut widths = Vec::with_capacity(self.widths.len());
        for width in self.widths.iter() {
            if x + width < table_area.width {
                widths.push(*width);
            }
            x += *width;
        }

        let mut y = table_area.top();

        // Draw the header
        if y < table_area.bottom() {
            x = table_area.left();
            for (w, t) in widths.iter().zip(self.header.by_ref()) {
                buf.set_string(x, y, &format!("{}", t), &self.header_style);
                x += *w + self.column_spacing;
            }
        }
        y += 2;

        // Draw rows
        let default_style = Style::default();
        if y < table_area.bottom() {
            let remaining = (table_area.bottom() - y) as usize;
            for (i, row) in self.rows.by_ref().take(remaining).enumerate() {
                let (data, style) = match row {
                    Row::Data(d) => (d, &default_style),
                    Row::StyledData(d, s) => (d, s),
                };
                x = table_area.left();
                for (w, elt) in widths.iter().zip(data) {
                    buf.set_stringn(x, y + i as u16, &format!("{}", elt), *w as usize, style);
                    x += *w + self.column_spacing;
                }
            }
        }
    }
}
<commit_msg>[widgets] Fix table doc test<commit_after>use std::fmt::Display;
use std::iter::Iterator;

use buffer::Buffer;
use widgets::{Widget, Block};
use layout::Rect;
use style::Style;

/// Holds data to be displayed in a Table widget
pub enum Row<'i, D, I>
where
    D: Iterator<Item = I>,
    I: Display,
{
    Data(D),
    StyledData(D, &'i Style),
}

/// A widget to display data in formatted columns
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, border, Table, Row};
/// # use tui::style::{Style, Color};
/// # fn main() {
/// let row_style = Style::default().fg(Color::White);
/// Table::new(
///         ["Col1", "Col2", "Col3"].into_iter(),
///         vec![
///             Row::StyledData(["Row11", "Row12", "Row13"].into_iter(), &row_style),
///             Row::StyledData(["Row21", "Row22", "Row23"].into_iter(), &row_style),
///             Row::StyledData(["Row31", "Row32", "Row33"].into_iter(), &row_style),
///             Row::Data(["Row41", "Row42", "Row43"].into_iter())
///         ].into_iter()
///     )
///     .block(Block::default().title("Table"))
///     .header_style(Style::default().fg(Color::Yellow))
///     .widths(&[5, 5, 10])
///     .style(Style::default().fg(Color::White))
///     .column_spacing(1);
/// # }
/// ```
pub struct Table<'a, 'i, T, H, I, D, R>
where
    T: Display,
    H: Iterator<Item = T>,
    I: Display,
    D: Iterator<Item = I>,
    R: Iterator<Item = Row<'i, D, I>>,
{
    /// A block to wrap the widget in
    block: Option<Block<'a>>,
    /// Base style for the widget
    style: Style,
    /// Header row for all columns
    header: H,
    /// Style for the header
    header_style: Style,
    /// Width of each column (if the total width is greater than the widget width some columns may
    /// not be displayed)
    widths: &'a [u16],
    /// Space between each column
    column_spacing: u16,
    /// Data to display in each row
    rows: R,
}

impl<'a, 'i, T, H, I, D, R> Default for Table<'a, 'i, T, H, I, D, R>
where
    T: Display,
    H: Iterator<Item = T> + Default,
    I: Display,
    D: Iterator<Item = I>,
    R: Iterator<Item = Row<'i, D, I>>
        + Default,
{
    fn default() -> Table<'a, 'i, T, H, I, D, R> {
        Table {
            block: None,
            style: Style::default(),
            header: H::default(),
            header_style: Style::default(),
            widths: &[],
            rows: R::default(),
            column_spacing: 1,
        }
    }
}

impl<'a, 'i, T, H, I, D, R> Table<'a, 'i, T, H, I, D, R>
where
    T: Display,
    H: Iterator<Item = T>,
    I: Display,
    D: Iterator<Item = I>,
    R: Iterator<Item = Row<'i, D, I>>,
{
    pub fn new(header: H, rows: R) -> Table<'a, 'i, T, H, I, D, R> {
        Table {
            block: None,
            style: Style::default(),
            header: header,
            header_style: Style::default(),
            widths: &[],
            rows: rows,
            column_spacing: 1,
        }
    }
    pub fn block(&'a mut self, block: Block<'a>) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.block = Some(block);
        self
    }

    pub fn header<II>(&mut self, header: II) -> &mut Table<'a, 'i, T, H, I, D, R>
    where
        II: IntoIterator<Item = T, IntoIter = H>,
    {
        self.header = header.into_iter();
        self
    }

    pub fn header_style(&mut self, style: Style) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.header_style = style;
        self
    }

    pub fn widths(&mut self, widths: &'a [u16]) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.widths = widths;
        self
    }

    pub fn rows<II>(&mut self, rows: II) -> &mut Table<'a, 'i, T, H, I, D, R>
    where
        II: IntoIterator<Item = Row<'i, D, I>, IntoIter = R>,
    {
        self.rows = rows.into_iter();
        self
    }

    pub fn style(&mut self, style: Style) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.style = style;
        self
    }

    pub fn column_spacing(&mut self, spacing: u16) -> &mut Table<'a, 'i, T, H, I, D, R> {
        self.column_spacing = spacing;
        self
    }
}

impl<'a, 'i, T, H, I, D, R> Widget for Table<'a, 'i, T, H, I, D, R>
where
    T: Display,
    H: Iterator<Item = T>,
    I: Display,
    D: Iterator<Item = I>,
    R: Iterator<Item = Row<'i, D, I>>,
{
    fn draw(&mut self, area: &Rect, buf: &mut Buffer) {

        // Render block if necessary and get the drawing area
        let table_area = match self.block {
            Some(ref mut b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => *area,
        };

        // Set the background
        self.background(&table_area, buf, self.style.bg);

        // Save widths of the columns that will fit in the given area
        let mut x = 0;
        let mut widths = Vec::with_capacity(self.widths.len());
        for width in self.widths.iter() {
            if x + width < table_area.width {
                widths.push(*width);
            }
            x += *width;
        }

        let mut y = table_area.top();

        // Draw header
        if y < table_area.bottom() {
            x = table_area.left();
            for (w, t) in widths.iter().zip(self.header.by_ref()) {
                buf.set_string(x, y, &format!("{}", t), &self.header_style);
                x += *w + self.column_spacing;
            }
        }
        y += 2;

        // Draw rows
        let default_style = Style::default();
        if y < table_area.bottom() {
            let remaining = (table_area.bottom() - y) as usize;
            for (i, row) in self.rows.by_ref().take(remaining).enumerate() {
                let (data, style) = match row {
                    Row::Data(d) => (d, &default_style),
                    Row::StyledData(d, s) => (d, s),
                };
                x = table_area.left();
                for (w, elt) in widths.iter().zip(data) {
                    buf.set_stringn(x, y + i as u16, &format!("{}", elt), *w as usize, style);
                    x += *w + self.column_spacing;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use data::Array;
use line::Line;
#[allow(dead_code)]
pub struct Regression {
    pub x: Array,
    pub y: Array,
    lsrl: Option<Line>,
    r_value: Option<f32>,
}
impl Regression {
    pub fn new( a1: Array, a2: Array ) -> Regression {
        assert!( a1.data.len() == a2.data.len() );
        Regression {
            x: a1,
            y: a2,
            lsrl: None,
            r_value: None,
        }
    }
    pub fn from( v1: Vec<f32>, v2: Vec<f32> ) -> Regression {
        Regression::new( Array::new(v1), Array::new(v2) )
    }
    pub fn r_value( &mut self ) -> f32 {
        assert!( self.x.len() == self.y.len() );
        match self.r_value {
            Some( r ) => return r,
            None => {
                let mut sum = 0_f32;
                for i in 0..self.x.len() {
                    sum += ( self.x[i] - self.x.mean() ) * ( self.y[i] - self.y.mean() );
                }
                let coef_n = 1f32 / self.x.len() as f32;
                self.r_value = Some( coef_n * (sum / ( self.x.stdev() * self.y.stdev() ) ) );
                return self.r_value.unwrap();
            },
        }
    }
    pub fn least_squares(&mut self) -> Line {
        match self.lsrl {
            Some( line ) => return line,
            None => {
                let b = self.r_value() * ( self.y.stdev() / self.x.stdev() );
                let m = self.y.mean() - ( b * self.x.mean() );
                self.lsrl = Some( Line::new( m, b ) );
                return self.lsrl.unwrap();
            }
        }
    }
}
#[test]
fn regression_construction() {
    let a1 = Array::new( vec![ 1_f32, 2.4, 4.5 ] );
    let cloned_a1 = a1.data.clone();
    let a2 = Array::new( vec![ 2_f32, 2.33, 5.67 ] );
    let reg = Regression::new( a1, a2 );
    assert!( reg.x.data == cloned_a1 );
}
#[test]
fn regression_r_value() {
    let a1 = Array::new( vec![ 1_f32, 2.0, 3.0, 4.0 ] );
    let a2 = Array::new( vec![ 1_f32, 2.0, 3.0, 4.0 ] );
    let mut reg = Regression::new( a1, a2 );
    assert!( reg.r_value() == 1_f32 );
    let mut reg2 = Regression::from( vec![ 1.0f32,2.0,3.0,4.0,65.0,23.0 ], vec![ 23.3f32,12.2,13.4,12.0,23.44,14.3 ] );
    assert!( reg2.r_value() == 0.5504537f32 );
}
#[test]
fn regression_least_squares() {
    let mut reg = Regression::from( vec![1.0f32,2.0,3.0,4.0], vec![2.3, 3.55, 4.56, 3.45] );
    let line = reg.least_squares();
    assert!( line.slope ==  2.35f32 );
    assert!( line.y_int == 0.44600004f32 );
}
<commit_msg>Added residual calculations.<commit_after>use data::Array;
use line::Line;
pub struct Regression {
    pub x: Array,
    pub y: Array,
    lsrl: Option<Line>,
    r_value: Option<f32>,
}
impl Regression {
    pub fn new( a1: Array, a2: Array ) -> Regression {
        assert!( a1.data.len() == a2.data.len() );
        Regression {
            x: a1,
            y: a2,
            lsrl: None,
            r_value: None,
        }
    }
    pub fn from( v1: Vec<f32>, v2: Vec<f32> ) -> Regression {
        Regression::new( Array::new(v1), Array::new(v2) )
    }
    pub fn r_value( &mut self ) -> f32 {
        assert!( self.x.len() == self.y.len() );
        match self.r_value {
            Some( r ) => return r,
            None => {
                let mut sum = 0_f32;
                for i in 0..self.x.len() {
                    sum += ( self.x[i] - self.x.mean() ) * ( self.y[i] - self.y.mean() );
                }
                let coef_n = 1f32 / self.x.len() as f32;
                self.r_value = Some( coef_n * (sum / ( self.x.stdev() * self.y.stdev() ) ) );
                return self.r_value.unwrap();
            },
        }
    }
    pub fn least_squares(&mut self) -> Line {
        match self.lsrl {
            Some( line ) => return line,
            None => {
                let b = self.r_value() * ( self.y.stdev() / self.x.stdev() );
                let m = self.y.mean() - ( b * self.x.mean() );
                self.lsrl = Some( Line::new( m, b ) );
                return self.lsrl.unwrap();
            }
        }
    }
    // TODO: write unit test for residuals
    pub fn least_squares_residuals(&mut self) -> Array {
        let line = self.least_squares();
        let mut v: Vec<f32> = vec![];
        for i in 0..self.x.len() {
            v.push( self.y[i] - line.get( self.x[i] ) );
        }
        Array::new( v )
    }
}
#[test]
fn regression_construction() {
    let a1 = Array::new( vec![ 1_f32, 2.4, 4.5 ] );
    let cloned_a1 = a1.data.clone();
    let a2 = Array::new( vec![ 2_f32, 2.33, 5.67 ] );
    let reg = Regression::new( a1, a2 );
    assert!( reg.x.data == cloned_a1 );
}
#[test]
fn regression_r_value() {
    let a1 = Array::new( vec![ 1_f32, 2.0, 3.0, 4.0 ] );
    let a2 = Array::new( vec![ 1_f32, 2.0, 3.0, 4.0 ] );
    let mut reg = Regression::new( a1, a2 );
    assert!( reg.r_value() == 1_f32 );
    let mut reg2 = Regression::from( vec![ 1.0f32,2.0,3.0,4.0,65.0,23.0 ], vec![ 23.3f32,12.2,13.4,12.0,23.44,14.3 ] );
    assert!( reg2.r_value() == 0.5504537f32 );
}
#[test]
fn regression_least_squares() {
    let mut reg = Regression::from( vec![1.0f32,2.0,3.0,4.0], vec![2.3, 3.55, 4.56, 3.45] );
    let line = reg.least_squares();
    assert!( line.slope ==  2.35f32 );
    assert!( line.y_int == 0.44600004f32 );
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use base_db::SourceDatabaseExt;

use super::*;

fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: &str) {
    let (mut db, pos) = TestDB::with_position(ra_fixture_initial);
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            db.crate_def_map(krate);
        });
        assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
    db.set_file_text(pos.file_id, Arc::new(ra_fixture_change.to_string()));

    {
        let events = db.log_executed(|| {
            db.crate_def_map(krate);
        });
        assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
}

#[test]
fn typing_inside_a_function_should_not_invalidate_def_map() {
    check_def_map_is_not_recomputed(
        r"
        //- /lib.rs
        mod foo;$0

        use crate::foo::bar::Baz;

        enum E { A, B }
        use E::*;

        fn foo() -> i32 {
            1 + 1
        }

        #[cfg(never)]
        fn no() {}
        //- /foo/mod.rs
        pub mod bar;

        //- /foo/bar.rs
        pub struct Baz;
        ",
        r"
        mod foo;

        use crate::foo::bar::Baz;

        enum E { A, B }
        use E::*;

        fn foo() -> i32 { 92 }

        #[cfg(never)]
        fn no() {}
        ",
    );
}

#[test]
fn typing_inside_a_macro_should_not_invalidate_def_map() {
    let (mut db, pos) = TestDB::with_position(
        r"
        //- /lib.rs
        macro_rules! m {
            ($ident:ident) => {
                fn f() {
                    $ident + $ident;
                };
            }
        }
        mod foo;

        //- /foo/mod.rs
        pub mod bar;

        //- /foo/bar.rs
        $0
        m!(X);
        ",
    );
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 1);
        });
        assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
    db.set_file_text(pos.file_id, Arc::new("m!(Y);".to_string()));

    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 1);
        });
        assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
}
<commit_msg>internal: add failing incremental test<commit_after>use std::sync::Arc;

use base_db::SourceDatabaseExt;

use super::*;

fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: &str) {
    let (mut db, pos) = TestDB::with_position(ra_fixture_initial);
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            db.crate_def_map(krate);
        });
        assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
    db.set_file_text(pos.file_id, Arc::new(ra_fixture_change.to_string()));

    {
        let events = db.log_executed(|| {
            db.crate_def_map(krate);
        });
        assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
}

#[test]
fn typing_inside_a_function_should_not_invalidate_def_map() {
    check_def_map_is_not_recomputed(
        r"
        //- /lib.rs
        mod foo;$0

        use crate::foo::bar::Baz;

        enum E { A, B }
        use E::*;

        fn foo() -> i32 {
            1 + 1
        }

        #[cfg(never)]
        fn no() {}
        //- /foo/mod.rs
        pub mod bar;

        //- /foo/bar.rs
        pub struct Baz;
        ",
        r"
        mod foo;

        use crate::foo::bar::Baz;

        enum E { A, B }
        use E::*;

        fn foo() -> i32 { 92 }

        #[cfg(never)]
        fn no() {}
        ",
    );
}

#[test]
fn typing_inside_a_macro_should_not_invalidate_def_map() {
    let (mut db, pos) = TestDB::with_position(
        r"
        //- /lib.rs
        macro_rules! m {
            ($ident:ident) => {
                fn f() {
                    $ident + $ident;
                };
            }
        }
        mod foo;

        //- /foo/mod.rs
        pub mod bar;

        //- /foo/bar.rs
        $0
        m!(X);
        ",
    );
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 1);
        });
        assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
    db.set_file_text(pos.file_id, Arc::new("m!(Y);".to_string()));

    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 1);
        });
        assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
    }
}

#[test]
fn typing_inside_a_function_doe_should_not_invalidate_expansions() {
    let (mut db, pos) = TestDB::with_position(
        r#"
//- /lib.rs
macro_rules! m {
    ($ident:ident) => {
        fn $ident() { };
    }
}
mod foo;

//- /foo/mod.rs
pub mod bar;

//- /foo/bar.rs
m!(X);
fn quux() { 1$0 }
m!(Y);
m!(Z);
"#,
    );
    let krate = db.test_crate();
    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 4);
        });
        let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
        assert_eq!(n_recalculated_item_trees, 6);
    }

    let new_text = r#"
m!(X);
fn quux() { 92 }
m!(Y);
m!(Z);
"#;
    db.set_file_text(pos.file_id, Arc::new(new_text.to_string()));

    {
        let events = db.log_executed(|| {
            let crate_def_map = db.crate_def_map(krate);
            let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
            assert_eq!(module_data.scope.resolutions().count(), 4);
        });
        let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
        assert_eq!(n_recalculated_item_trees, 1);
    }
}
<|endoftext|>