<commit_before>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

use std::ops::{Add, AddAssign, BitAnd, BitOr, Mul, Sub, Shl, ShlAssign, Shr};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

/// An abstraction trait for keeping different sized integers.
pub trait Sample: PartialEq + Eq + Sized + Clone + Copy +
                  Add<Output = Self> + AddAssign + BitAnd<Self, Output = Self> +
                  BitOr<Self, Output = Self> + Mul<Output = Self> +
                  Shl<u32, Output = Self>  + ShlAssign<u32> +
                  Shr<u32, Output = Self> + Shr<i8, Output = Self> +
                  Shr<i32, Output = Self> + Sub<Output = Self> {
  /// The normal size for the current a `Sample`.
  type Normal;

  /// The size, in bits, for the `Sample::Normal`.
  fn size() -> usize;

  /// The size, in bits, for the `Sample`.
  fn size_extended() -> usize;

  /// Convert the extended `Sample` to the normal.
  fn to_normal(sample: Self) -> Option<Self::Normal>;

  /// Convert an i8 into a `Sample`.
  fn from_i8(sample: i8) -> Self;

  /// Convert an i16 into a `Sample`.
  fn from_i16(sample: i16) -> Self;

  /// Convert an i32 into a `Sample`.
  ///
  /// With `Sample` sometimes being smaller than a i32, there is a chance
  /// for this function to return an incorrect number. So when the number is
  /// larger of smaller than the current `Sample`, it returns `None`
  /// otherwise `Some(sample)`.
  fn from_i32(sample: i32) -> Option<Self>;

  /// Convert an i32 into a `Sample`.
  fn from_i32_lossy(sample: i32) -> Self;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<commit_msg>Constrict the dervived trait to a line limit<commit_after>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

use std::ops::{Add, AddAssign, BitAnd, BitOr, Mul, Sub, Shl, ShlAssign, Shr};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

/// An abstraction trait for keeping different sized integers.
pub trait Sample: PartialEq + Eq + Sized + Clone + Copy +
                  Add<Output = Self> + AddAssign +
                  BitAnd<Self, Output = Self> + BitOr<Self, Output = Self> +
                  Mul<Output = Self> + Shl<u32, Output = Self>  +
                  ShlAssign<u32> + Shr<u32, Output = Self> +
                  Shr<i8, Output = Self> + Shr<i32, Output = Self> +
                  Sub<Output = Self> {
  /// The normal size for the current a `Sample`.
  type Normal;

  /// The size, in bits, for the `Sample::Normal`.
  fn size() -> usize;

  /// The size, in bits, for the `Sample`.
  fn size_extended() -> usize;

  /// Convert the extended `Sample` to the normal.
  fn to_normal(sample: Self) -> Option<Self::Normal>;

  /// Convert an i8 into a `Sample`.
  fn from_i8(sample: i8) -> Self;

  /// Convert an i16 into a `Sample`.
  fn from_i16(sample: i16) -> Self;

  /// Convert an i32 into a `Sample`.
  ///
  /// With `Sample` sometimes being smaller than a i32, there is a chance
  /// for this function to return an incorrect number. So when the number is
  /// larger of smaller than the current `Sample`, it returns `None`
  /// otherwise `Some(sample)`.
  fn from_i32(sample: i32) -> Option<Self>;

  /// Convert an i32 into a `Sample`.
  fn from_i32_lossy(sample: i32) -> Self;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<|endoftext|>


<commit_before>/*
* Huffman table generation:
* HuffTable::huff_decode()
* HuffTable::initialize()
* and used data structures are originally grabbed from the IJG software,
* and adapted by Hubert Figuiere.
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Part of the Independent JPEG Group's software.
* See the file Copyright for more details.
*
* Copyright (c) 1993 Brian C. Smith, The Regents of the University
* of California
* All rights reserved.
*
* Copyright (c) 1994 Kongji Huang and Brian C. Smith.
* Cornell University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/

use std::fmt;
use decoders::basics::*;

const HUFF_BITMASK: [u32;32] = [0xffffffff, 0x7fffffff,
                                0x3fffffff, 0x1fffffff,
                                0x0fffffff, 0x07ffffff,
                                0x03ffffff, 0x01ffffff,
                                0x00ffffff, 0x007fffff,
                                0x003fffff, 0x001fffff,
                                0x000fffff, 0x0007ffff,
                                0x0003ffff, 0x0001ffff,
                                0x0000ffff, 0x00007fff,
                                0x00003fff, 0x00001fff,
                                0x00000fff, 0x000007ff,
                                0x000003ff, 0x000001ff,
                                0x000000ff, 0x0000007f,
                                0x0000003f, 0x0000001f,
                                0x0000000f, 0x00000007,
                                0x00000003, 0x00000001];

pub struct HuffTable {
  // These two fields directly represent the contents of a JPEG DHT marker
  pub bits: [u32;17],
  pub huffval: [u32;256],

  // The remaining fields are computed from the above to allow more
  // efficient coding and decoding and thus private
  mincode: [u16;17],
  maxcode: [i32;18],
  valptr: [i16;17],
  numbits: [usize;256],
  bigtable: Vec<i32>,
  precision: usize,
  pub use_bigtable: bool,
  pub dng_compatible: bool,
  pub initialized: bool,
}

impl HuffTable {
  pub fn empty(precision: usize) -> HuffTable {
    HuffTable {
      bits: [0;17],
      huffval: [0;256],
      mincode: [0;17],
      maxcode: [0;18],
      valptr: [0;17],
      numbits: [0;256],
      bigtable: Vec::new(),
      precision: precision,
      use_bigtable: true,
      dng_compatible: true,
      initialized: false,
    }
  }

  pub fn initialize(&mut self, use_bigtable: bool) -> Result<(), String> {
    // Figure C.1: make table of Huffman code length for each symbol
    // Note that this is in code-length order.
    let mut p = 0;
    let mut huffsize: [u8;257] = [0;257];
    for l in 1..17 {
      for _ in 1..((self.bits[l] as usize)+1) {
        huffsize[p] = l as u8;
        p += 1;
        if p > 256 {
          return Err("ljpeg: Code length too long. Corrupt data.".to_string())
        }
      }
    }
    huffsize[p] = 0;
    let lastp = p;

    // Figure C.2: generate the codes themselves
    // Note that this is in code-length order.
    let mut code: u16 = 0;
    let mut si: u32 = huffsize[0] as u32;
    let mut huffcode: [u16;257] = [0;257];
    p = 0;
    while huffsize[p] > 0 {
      while (huffsize[p] as u32) == si {
        huffcode[p] = code;
        p += 1;
        code += 1;
      }
      code <<= 1;
      si += 1;
      if p > 256 {
        return Err("ljpeg: Code length too long. Corrupt data.".to_string())
      }
    }

    //Figure F.15: generate decoding tables
    self.mincode[0] = 0;
    self.maxcode[0] = 0;
    p = 0;
    for l in 1..17 {
      if self.bits[l] > 0 {
        self.valptr[l] = p as i16;
        self.mincode[l] = huffcode[p];
        p += self.bits[l] as usize;
        self.maxcode[l] = huffcode[p - 1] as i32;
      } else {
        self.valptr[l] = 0xff;   // This check must be present to avoid crash on junk
        self.maxcode[l] = -1;
      }
      if p > 256 {
        return Err("ljpeg: Code length too long. Corrupt data.".to_string())
      }
    }

    // We put in this value to ensure HuffDecode terminates
    self.maxcode[17] = 0xFFFFF;

    // Build the numbits, value lookup tables.
    // These table allow us to gather 8 bits from the bits stream,
    // and immediately lookup the size and value of the huffman codes.
    // If size is zero, it means that more than 8 bits are in the huffman
    // code (this happens about 3-4% of the time).
    for p in 0..lastp {
      let size = huffsize[p];
      if size <= 8 {
        let value: i32 = self.huffval[p] as i32;
        let code = huffcode[p];
        let ll: i32 = (code << (8 - size)) as i32;
        let ul: i32 = if size < 8 {
          ll | (HUFF_BITMASK[(24+size) as usize]) as i32
        } else {
          ll
        };
        if ul > 256 || ll > ul {
          return Err("ljpeg: Code length too long. Corrupt data.".to_string())
        }
        for i in ll..(ul+1) {
          self.numbits[i as usize] = (size as usize) | ((value as usize) << 4);
        }
      }
    }

    if use_bigtable {
      try!(self.initialize_bigtable());
    }
    self.initialized = true;
    self.use_bigtable = use_bigtable;
    Ok(())
  }

  fn initialize_bigtable(&mut self) -> Result<(), String> {
    let bits: usize = 14; // HuffDecode functions must be changed, if this is modified.
    let size: usize = 1 << bits;

    self.bigtable = vec![0 as i32;size];
    let mut rv: i32;
    for i in 0..size {
      let input = (i << 2) as u16;
      let mut code: i32 = (input >> 8) as i32;
      let val: u32 = self.numbits[code as usize] as u32;
      let mut l: u32 = val & 15;
      if l > 0 {
        rv = (val >> 4) as i32;
      } else {
        l = 8;
        while code > self.maxcode[l as usize] && l < 16 {
          let temp: i32 = (input >> (15 - l) & 1) as i32;
          code = (code << 1) | temp;
          l += 1;
        }

        //With garbage input we may reach the sentinel value l = 17.
        if l > self.precision as u32 || self.valptr[l as usize] == 0xff {
          self.bigtable[i] = 0xff;
          continue
        } else {
          rv = self.huffval[
            self.valptr[l as usize] as usize +
            (code - (self.mincode[l as usize] as i32)) as usize
          ] as i32;
        }
      }

      if rv == 16 {
        self.bigtable[i] = if self.dng_compatible {
          (-(32768 << 8)) | (16 + l as i32)
        } else {
          (-(32768 << 8)) | l as i32
        };
        continue
      }

      if rv + l as i32 > bits as i32 {
        self.bigtable[i] = 0xff;
        continue
      }

      if rv != 0 {
        let mut x = (input >> (16 - (l as i32) - rv) & ((1 << rv) - 1)) as i32;
        if (x & (1 << (rv - 1))) == 0 {
          x -= (1 << rv) - 1;
        }
        self.bigtable[i] = (x << 8) | ((l as i32) + rv);
      } else {
        self.bigtable[i] = l as i32;
      }
    }
    self.use_bigtable = true;
    Ok(())
  }

  // Taken from Figure F.16: extract next coded symbol from input stream
  pub fn huff_decode(&self, pump: &mut BitPump) -> Result<i32,String> {
    //First attempt to do complete decode, by using the first 14 bits
    let code: i32 = pump.peek_bits(14) as i32;
    if self.use_bigtable {
      let val: i32 = self.bigtable[code as usize];
      if val & 0xff != 0xff {
        pump.consume_bits((val & 0xff) as u32);
        return Ok(val >> 8)
      }
    }

    let len = try!(self.huff_len(pump));
    Ok(self.huff_diff(pump, len))
  }

  pub fn huff_len(&self, pump: &mut BitPump) -> Result<u32,String> {
    let mut code = pump.peek_bits(8) as usize;
    let val = self.numbits[code as usize] as u32;
    let mut l = val & 15;
    if l != 0 {
      pump.consume_bits(l);
      return Ok(val >> 4)
    }
    pump.consume_bits(8);
    l = 8;
    while code as i32 > self.maxcode[l as usize] {
      let temp = pump.get_bits(1) as usize;
      code = (code << 1) | temp;
      l += 1;
    }

    // With garbage input we may reach the sentinel value l = 17.
    if l > self.precision as u32 || self.valptr[l as usize] == 0xff {
      return Err(format!("ljpeg: bad Huffman code: {}", l).to_string())
    } else {
      return Ok(self.huffval[
        self.valptr[l as usize] as usize +
        (code - (self.mincode[l as usize] as usize)) as usize
      ]);
    }
  }

  pub fn huff_diff(&self, pump: &mut BitPump, len: u32) -> i32 {
    match len {
      0 => 0,
      16 => {
        if self.dng_compatible {
          pump.get_bits(16); // consume can fail because we haven't peeked yet
        }
        -32768
      },
      len => {
        // Section F.2.2.1: decode the difference and
        // Figure F.12: extend sign bit
        let mut x: i32 = pump.get_bits(len as u32) as i32;
        if (x & (1 << (len - 1))) == 0 {
          x -= (1 << len) - 1;
        }
        x
      },
    }
  }
}

impl fmt::Debug for HuffTable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    if self.initialized {
      write!(f, "HuffTable {{ bits: {:?} huffval: {:?} }}", self.bits, &self.huffval[..])
    } else {
      write!(f, "HuffTable {{ uninitialized }}")
    }
  }
}

<commit_msg>ljpeg: bigtable init doesn't need to return errors<commit_after>/*
* Huffman table generation:
* HuffTable::huff_decode()
* HuffTable::initialize()
* and used data structures are originally grabbed from the IJG software,
* and adapted by Hubert Figuiere.
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Part of the Independent JPEG Group's software.
* See the file Copyright for more details.
*
* Copyright (c) 1993 Brian C. Smith, The Regents of the University
* of California
* All rights reserved.
*
* Copyright (c) 1994 Kongji Huang and Brian C. Smith.
* Cornell University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/

use std::fmt;
use decoders::basics::*;

const HUFF_BITMASK: [u32;32] = [0xffffffff, 0x7fffffff,
                                0x3fffffff, 0x1fffffff,
                                0x0fffffff, 0x07ffffff,
                                0x03ffffff, 0x01ffffff,
                                0x00ffffff, 0x007fffff,
                                0x003fffff, 0x001fffff,
                                0x000fffff, 0x0007ffff,
                                0x0003ffff, 0x0001ffff,
                                0x0000ffff, 0x00007fff,
                                0x00003fff, 0x00001fff,
                                0x00000fff, 0x000007ff,
                                0x000003ff, 0x000001ff,
                                0x000000ff, 0x0000007f,
                                0x0000003f, 0x0000001f,
                                0x0000000f, 0x00000007,
                                0x00000003, 0x00000001];

pub struct HuffTable {
  // These two fields directly represent the contents of a JPEG DHT marker
  pub bits: [u32;17],
  pub huffval: [u32;256],

  // The remaining fields are computed from the above to allow more
  // efficient coding and decoding and thus private
  mincode: [u16;17],
  maxcode: [i32;18],
  valptr: [i16;17],
  numbits: [usize;256],
  bigtable: Vec<i32>,
  precision: usize,
  pub use_bigtable: bool,
  pub dng_compatible: bool,
  pub initialized: bool,
}

impl HuffTable {
  pub fn empty(precision: usize) -> HuffTable {
    HuffTable {
      bits: [0;17],
      huffval: [0;256],
      mincode: [0;17],
      maxcode: [0;18],
      valptr: [0;17],
      numbits: [0;256],
      bigtable: Vec::new(),
      precision: precision,
      use_bigtable: true,
      dng_compatible: true,
      initialized: false,
    }
  }

  pub fn initialize(&mut self, use_bigtable: bool) -> Result<(), String> {
    // Figure C.1: make table of Huffman code length for each symbol
    // Note that this is in code-length order.
    let mut p = 0;
    let mut huffsize: [u8;257] = [0;257];
    for l in 1..17 {
      for _ in 1..((self.bits[l] as usize)+1) {
        huffsize[p] = l as u8;
        p += 1;
        if p > 256 {
          return Err("ljpeg: Code length too long. Corrupt data.".to_string())
        }
      }
    }
    huffsize[p] = 0;
    let lastp = p;

    // Figure C.2: generate the codes themselves
    // Note that this is in code-length order.
    let mut code: u16 = 0;
    let mut si: u32 = huffsize[0] as u32;
    let mut huffcode: [u16;257] = [0;257];
    p = 0;
    while huffsize[p] > 0 {
      while (huffsize[p] as u32) == si {
        huffcode[p] = code;
        p += 1;
        code += 1;
      }
      code <<= 1;
      si += 1;
      if p > 256 {
        return Err("ljpeg: Code length too long. Corrupt data.".to_string())
      }
    }

    //Figure F.15: generate decoding tables
    self.mincode[0] = 0;
    self.maxcode[0] = 0;
    p = 0;
    for l in 1..17 {
      if self.bits[l] > 0 {
        self.valptr[l] = p as i16;
        self.mincode[l] = huffcode[p];
        p += self.bits[l] as usize;
        self.maxcode[l] = huffcode[p - 1] as i32;
      } else {
        self.valptr[l] = 0xff;   // This check must be present to avoid crash on junk
        self.maxcode[l] = -1;
      }
      if p > 256 {
        return Err("ljpeg: Code length too long. Corrupt data.".to_string())
      }
    }

    // We put in this value to ensure HuffDecode terminates
    self.maxcode[17] = 0xFFFFF;

    // Build the numbits, value lookup tables.
    // These table allow us to gather 8 bits from the bits stream,
    // and immediately lookup the size and value of the huffman codes.
    // If size is zero, it means that more than 8 bits are in the huffman
    // code (this happens about 3-4% of the time).
    for p in 0..lastp {
      let size = huffsize[p];
      if size <= 8 {
        let value: i32 = self.huffval[p] as i32;
        let code = huffcode[p];
        let ll: i32 = (code << (8 - size)) as i32;
        let ul: i32 = if size < 8 {
          ll | (HUFF_BITMASK[(24+size) as usize]) as i32
        } else {
          ll
        };
        if ul > 256 || ll > ul {
          return Err("ljpeg: Code length too long. Corrupt data.".to_string())
        }
        for i in ll..(ul+1) {
          self.numbits[i as usize] = (size as usize) | ((value as usize) << 4);
        }
      }
    }

    if use_bigtable {
      self.initialize_bigtable();
    }
    self.initialized = true;
    self.use_bigtable = use_bigtable;
    Ok(())
  }

  fn initialize_bigtable(&mut self) {
    let bits: usize = 14; // HuffDecode functions must be changed, if this is modified.
    let size: usize = 1 << bits;

    self.bigtable = vec![0 as i32;size];
    let mut rv: i32;
    for i in 0..size {
      let input = (i << 2) as u16;
      let mut code: i32 = (input >> 8) as i32;
      let val: u32 = self.numbits[code as usize] as u32;
      let mut l: u32 = val & 15;
      if l > 0 {
        rv = (val >> 4) as i32;
      } else {
        l = 8;
        while code > self.maxcode[l as usize] && l < 16 {
          let temp: i32 = (input >> (15 - l) & 1) as i32;
          code = (code << 1) | temp;
          l += 1;
        }

        //With garbage input we may reach the sentinel value l = 17.
        if l > self.precision as u32 || self.valptr[l as usize] == 0xff {
          self.bigtable[i] = 0xff;
          continue
        } else {
          rv = self.huffval[
            self.valptr[l as usize] as usize +
            (code - (self.mincode[l as usize] as i32)) as usize
          ] as i32;
        }
      }

      if rv == 16 {
        self.bigtable[i] = if self.dng_compatible {
          (-(32768 << 8)) | (16 + l as i32)
        } else {
          (-(32768 << 8)) | l as i32
        };
        continue
      }

      if rv + l as i32 > bits as i32 {
        self.bigtable[i] = 0xff;
        continue
      }

      if rv != 0 {
        let mut x = (input >> (16 - (l as i32) - rv) & ((1 << rv) - 1)) as i32;
        if (x & (1 << (rv - 1))) == 0 {
          x -= (1 << rv) - 1;
        }
        self.bigtable[i] = (x << 8) | ((l as i32) + rv);
      } else {
        self.bigtable[i] = l as i32;
      }
    }
    self.use_bigtable = true;
  }

  // Taken from Figure F.16: extract next coded symbol from input stream
  pub fn huff_decode(&self, pump: &mut BitPump) -> Result<i32,String> {
    //First attempt to do complete decode, by using the first 14 bits
    let code: i32 = pump.peek_bits(14) as i32;
    if self.use_bigtable {
      let val: i32 = self.bigtable[code as usize];
      if val & 0xff != 0xff {
        pump.consume_bits((val & 0xff) as u32);
        return Ok(val >> 8)
      }
    }

    let len = try!(self.huff_len(pump));
    Ok(self.huff_diff(pump, len))
  }

  pub fn huff_len(&self, pump: &mut BitPump) -> Result<u32,String> {
    let mut code = pump.peek_bits(8) as usize;
    let val = self.numbits[code as usize] as u32;
    let mut l = val & 15;
    if l != 0 {
      pump.consume_bits(l);
      return Ok(val >> 4)
    }
    pump.consume_bits(8);
    l = 8;
    while code as i32 > self.maxcode[l as usize] {
      let temp = pump.get_bits(1) as usize;
      code = (code << 1) | temp;
      l += 1;
    }

    // With garbage input we may reach the sentinel value l = 17.
    if l > self.precision as u32 || self.valptr[l as usize] == 0xff {
      return Err(format!("ljpeg: bad Huffman code: {}", l).to_string())
    } else {
      return Ok(self.huffval[
        self.valptr[l as usize] as usize +
        (code - (self.mincode[l as usize] as usize)) as usize
      ]);
    }
  }

  pub fn huff_diff(&self, pump: &mut BitPump, len: u32) -> i32 {
    match len {
      0 => 0,
      16 => {
        if self.dng_compatible {
          pump.get_bits(16); // consume can fail because we haven't peeked yet
        }
        -32768
      },
      len => {
        // Section F.2.2.1: decode the difference and
        // Figure F.12: extend sign bit
        let mut x: i32 = pump.get_bits(len as u32) as i32;
        if (x & (1 << (len - 1))) == 0 {
          x -= (1 << len) - 1;
        }
        x
      },
    }
  }
}

impl fmt::Debug for HuffTable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    if self.initialized {
      write!(f, "HuffTable {{ bits: {:?} huffval: {:?} }}", self.bits, &self.huffval[..])
    } else {
      write!(f, "HuffTable {{ uninitialized }}")
    }
  }
}

<|endoftext|>


<commit_before>use super::gl;
use std::mem;
use std::raw;

pub trait VertexData: Copy {
    type Binder;
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy)]
pub enum DataType {
    BYTE = gl::BYTE as isize,
    UNSIGNED_BYTE = gl::UNSIGNED_BYTE as isize,
    SHORT = gl::SHORT as isize,
    UNSIGNED_SHORT = gl::UNSIGNED_SHORT as isize,
    FIXED = gl::FIXED as isize,
    FLOAT = gl::FLOAT as isize
}
pub use self::DataType::*;

pub trait VertexPrimitive {
    fn gl_type() -> DataType;
}

pub trait VertexDatum {
    fn gl_type() -> DataType;
    fn components() -> i8;
    fn normalized() -> bool { false }
}

pub trait VertexBytes {
    fn vertex_bytes(&self) -> &[u8];
}

impl<T> VertexBytes for T where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        unsafe {
            mem::transmute(raw::Slice::<Self> {
                data: self,
                len: mem::size_of::<Self>()
            })
        }
    }
}

#[macro_export]
macro_rules! vertex_data {
    ($(
        struct $name:ident {
            $($field_name:ident: $field_type:ty),*
        }
    )+) => {
        mod _glitter_vertex_data {
            $(
                #[allow(non_snake_case)]
                pub mod $name {
                    #[repr(C)]
                    #[derive(Debug, Clone, Copy)]
                    pub struct $name {
                        $($field_name: $field_type),*
                    }

                    pub struct Binder;

                    impl $crate::VertexData for $name {
                        type Binder = Binder;
                    }
                }
            )+
        }

        $(
            #[allow(unused_imports)]
            use self::_glitter_vertex_data::$name::$name;
        )+
    }
}
<commit_msg>Add `VertexPrimitive` impls for some primitive types<commit_after>use super::gl;
use std::mem;
use std::raw;

pub trait VertexData: Copy {
    type Binder;
}

#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy)]
pub enum DataType {
    BYTE = gl::BYTE as isize,
    UNSIGNED_BYTE = gl::UNSIGNED_BYTE as isize,
    SHORT = gl::SHORT as isize,
    UNSIGNED_SHORT = gl::UNSIGNED_SHORT as isize,
    FIXED = gl::FIXED as isize,
    FLOAT = gl::FLOAT as isize
}
pub use self::DataType::*;

pub trait VertexPrimitive {
    fn gl_type() -> DataType;
}

impl VertexPrimitive for i8 {
    fn gl_type() -> DataType { self::BYTE }
}

impl VertexPrimitive for u8 {
    fn gl_type() -> DataType { self::UNSIGNED_BYTE }
}

impl VertexPrimitive for i16 {
    fn gl_type() -> DataType { self::SHORT }
}

impl VertexPrimitive for u16 {
    fn gl_type() -> DataType { self::UNSIGNED_SHORT }
}

impl VertexPrimitive for f32 {
    fn gl_type() -> DataType { self::FLOAT }
}

pub trait VertexDatum {
    fn gl_type() -> DataType;
    fn components() -> i8;
    fn normalized() -> bool { false }
}

pub trait VertexBytes {
    fn vertex_bytes(&self) -> &[u8];
}

impl<T> VertexBytes for T where T: VertexData {
    fn vertex_bytes(&self) -> &[u8] {
        unsafe {
            mem::transmute(raw::Slice::<Self> {
                data: self,
                len: mem::size_of::<Self>()
            })
        }
    }
}

#[macro_export]
macro_rules! vertex_data {
    ($(
        struct $name:ident {
            $($field_name:ident: $field_type:ty),*
        }
    )+) => {
        mod _glitter_vertex_data {
            $(
                #[allow(non_snake_case)]
                pub mod $name {
                    #[repr(C)]
                    #[derive(Debug, Clone, Copy)]
                    pub struct $name {
                        $($field_name: $field_type),*
                    }

                    pub struct Binder;

                    impl $crate::VertexData for $name {
                        type Binder = Binder;
                    }
                }
            )+
        }

        $(
            #[allow(unused_imports)]
            use self::_glitter_vertex_data::$name::$name;
        )+
    }
}
<|endoftext|>


<commit_before>// DOCS

#![crate_name = "vobject"]
#![crate_type = "lib"]
#![license = "MIT"]
#![comment = "Parser for VObject and iCalendar."]

#![feature(phase)]
#[phase(plugin)]
extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};

pub struct Property {
    params: HashMap<String, String>,
    raw_value: String,
}

impl Property {
    fn new(params: HashMap<String, String>, raw_value: String) -> Property {
        Property {
            params: params,
            raw_value: raw_value
        }
    }

    #[doc="Get parameters."]
    pub fn get_params(&self) -> &HashMap<String, String> {
        &self.params
    }

    #[doc="Get value as unparsed string."]
    pub fn get_raw_value(&self) -> &String {
        &self.raw_value
    }

    #[doc="Get value as unescaped string."]
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.get_raw_value())
    }
}

pub struct Component {
    #[doc="The name of the component, such as `VCARD` or `VEVENT`."]
    pub name: String,

    #[doc="The component's properties."]
    pub props: HashMap<String, Vec<Property>>,

    #[doc="The component's child- or sub-components."]
    pub subcomponents: Vec<Component>
}

impl Component {
    fn new(name: String) -> Component {
        Component {
            name: name,
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    #[doc="Retrieve one property (from many) by key.
        Returns `None` if nothing is found."]
    pub fn single_prop(&self, key: &String) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    #[doc="Retrieve a mutable vector of properties for this key.
        Creates one (and inserts it into the component) if none exists."]
    pub fn all_props_mut(&mut self, key: String) -> &mut Vec<Property> {
        match self.props.entry(key) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.set(vec![])
        }
    }

    #[doc="Retrieve properties by key.
        Returns an empty slice if key doesn't exist."]
    pub fn all_props(&self, key: &String) -> &[Property] {
        static EMPTY: &'static [Property] = &[];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

#[pub]
component -> Component
    = name:component_begin
      ps:props
      cs:components?
      component_end {
        let mut rv = Component::new(name);

        match cs {
            Some(components) => { rv.subcomponents = components; },
            None => ()
        };

        for (k, v) in ps.into_iter() {
            rv.all_props_mut(k).push(v);
        };

        rv
    }

component_begin -> String
    = "BEGIN:" v:value __ { v }

component_end -> String
    = "END:" v:value __ { v }

components -> Vec<Component>
    = cs:component ++ eols __ { cs }

props -> Vec<(String, Property)>
    = ps:contentline ++ eols __ { ps }

contentline -> (String, Property)
    = k:name p:params ":" v:value {
        (k, Property::new(p, v))
    }

name -> String
    = !"BEGIN" !"END" iana_token+ { match_str.into_string() }

params -> HashMap<String, String>
    = ps:(";" p:param {p})* {
        let mut rv: HashMap<String, String> = HashMap::new();
        for (k, v) in ps.into_iter() {
            rv.insert(k, v);
        };
        rv
    }

param -> (String, String)
    // FIXME: Doesn't handle comma-separated values
    = k:param_name v:("=" v:param_value { v })? {
        (k, match v {
            Some(x) => x,
            None => "".into_string()
        })
    }

param_name -> String
    = iana_token+ { match_str.into_string() }

param_value -> String
    = x:(quoted_string / param_text) { x }

param_text -> String
    = safe_char* { match_str.into_string() }

value -> String
    = value_char+ { match_str.into_string() }

quoted_string -> String
    = dquote x:quoted_content dquote { x }

quoted_content -> String
    = qsafe_char* { match_str.into_string() }

iana_token = ([a-zA-Z0-9] / "-")+
safe_char = !";" !":" !"," value_char
qsafe_char = !dquote value_char // FIXME

value_char = !eol .

eol = "\n" / "\r\n" / "\r"
dquote = "\""
eols = eol+
whitespace = " " / "\t"
__ = (eol / whitespace)*

"#)

#[doc="Parse a component. The error value is a human-readable message."]
pub fn parse_component(s: &String) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = s
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\r ", "").replace("\r\t", "");

    parser::component(unfolded.as_slice())
}

#[doc="Escape text for a VObject property value."]
pub fn escape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

#[doc="Unescape text from a VObject property value."]
pub fn unescape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}
<commit_msg>nightly fixes<commit_after>// DOCS

#![crate_name = "vobject"]
#![crate_type = "lib"]
#![license = "MIT"]
#![comment = "Parser for VObject and iCalendar."]

#![feature(phase)]
#[phase(plugin)]
extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};

pub struct Property {
    params: HashMap<String, String>,
    raw_value: String,
}

impl Property {
    fn new(params: HashMap<String, String>, raw_value: String) -> Property {
        Property {
            params: params,
            raw_value: raw_value
        }
    }

    #[doc="Get parameters."]
    pub fn get_params(&self) -> &HashMap<String, String> {
        &self.params
    }

    #[doc="Get value as unparsed string."]
    pub fn get_raw_value(&self) -> &String {
        &self.raw_value
    }

    #[doc="Get value as unescaped string."]
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.get_raw_value())
    }
}

pub struct Component {
    #[doc="The name of the component, such as `VCARD` or `VEVENT`."]
    pub name: String,

    #[doc="The component's properties."]
    pub props: HashMap<String, Vec<Property>>,

    #[doc="The component's child- or sub-components."]
    pub subcomponents: Vec<Component>
}

impl Component {
    fn new(name: String) -> Component {
        Component {
            name: name,
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    #[doc="Retrieve one property (from many) by key.
        Returns `None` if nothing is found."]
    pub fn single_prop(&self, key: &String) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    #[doc="Retrieve a mutable vector of properties for this key.
        Creates one (and inserts it into the component) if none exists."]
    pub fn all_props_mut(&mut self, key: String) -> &mut Vec<Property> {
        match self.props.entry(key) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.set(vec![])
        }
    }

    #[doc="Retrieve properties by key.
        Returns an empty slice if key doesn't exist."]
    pub fn all_props(&self, key: &String) -> &[Property] {
        static EMPTY: &'static [Property] = &[];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

#[pub]
component -> Component
    = name:component_begin
      ps:props
      cs:components?
      component_end {
        let mut rv = Component::new(name);

        match cs {
            Some(components) => { rv.subcomponents = components; },
            None => ()
        };

        for (k, v) in ps.into_iter() {
            rv.all_props_mut(k).push(v);
        };

        rv
    }

component_begin -> String
    = "BEGIN:" v:value __ { v }

component_end -> String
    = "END:" v:value __ { v }

components -> Vec<Component>
    = cs:component ++ eols __ { cs }

props -> Vec<(String, Property)>
    = ps:contentline ++ eols __ { ps }

contentline -> (String, Property)
    = k:name p:params ":" v:value {
        (k, Property::new(p, v))
    }

name -> String
    = !"BEGIN" !"END" iana_token+ { match_str.into_string() }

params -> HashMap<String, String>
    = ps:(";" p:param {p})* {
        let mut rv: HashMap<String, String> = HashMap::new();
        for (k, v) in ps.into_iter() {
            rv.insert(k, v);
        };
        rv
    }

param -> (String, String)
    // FIXME: Doesn't handle comma-separated values
    = k:param_name v:("=" v:param_value { v })? {
        (k, match v {
            Some(x) => x,
            None => "".into_string()
        })
    }

param_name -> String
    = iana_token+ { match_str.into_string() }

param_value -> String
    = x:(quoted_string / param_text) { x }

param_text -> String
    = safe_char* { match_str.into_string() }

value -> String
    = value_char+ { match_str.into_string() }

quoted_string -> String
    = dquote x:quoted_content dquote { x }

quoted_content -> String
    = qsafe_char* { match_str.into_string() }

iana_token = ([a-zA-Z0-9] / "-")+
safe_char = !";" !":" !"," value_char
qsafe_char = !dquote value_char // FIXME

value_char = !eol .

eol = "\n" / "\r\n" / "\r"
dquote = "\""
eols = eol+
whitespace = " " / "\t"
__ = (eol / whitespace)*

"#);

#[doc="Parse a component. The error value is a human-readable message."]
pub fn parse_component(s: &String) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = s
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\r ", "").replace("\r\t", "");

    parser::component(unfolded.as_slice())
}

#[doc="Escape text for a VObject property value."]
pub fn escape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

#[doc="Unescape text from a VObject property value."]
pub fn unescape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// 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 std::fmt;
use std::hash::{Hash, Hasher};

use super::inputs::{Input, Position, Span};

/// An `enum` which defines possible errors.
#[derive(Debug)]
pub enum Error<R, I: Input> {
    /// Generated parsing error with expected and unexpected `Rule`s and a position
    ParsingError {
        positives: Vec<R>,
        negatives: Vec<R>,
        pos:       Position<I>
    },
    /// Custom error with a message and a position
    CustomErrorPos {
        message: String,
        pos:     Position<I>
    },
    /// Custom error with a message and a span defined by a start and end position
    CustomErrorSpan {
        message: String,
        span:    Span<I>
    }
}

fn message<R, I: Input>(error: &Error<R, I>) -> &str {
    match error {
        &Error::ParsingError { .. }                 => unimplemented!(),
        &Error::CustomErrorPos { ref message, .. }  => message,
        &Error::CustomErrorSpan { ref message, .. } => message
    }
}

fn underline<R, I: Input>(error: &Error<R, I>, offset: usize) -> String {
    let mut underline = String::new();

    for _ in 0..offset { underline.push(' '); }

    match error {
        &Error::CustomErrorSpan { ref span, .. } => {
            underline.push('^');
            for _ in 2..(span.end() - span.start()) { underline.push('-'); }
            underline.push('^');
        },
        _ => underline.push_str("^---")
    };

    underline
}

// TODO: Replace None with filename.
fn format<R, I: Input>(error: &Error<R, I>) -> String {
    let pos = match *error {
        Error::ParsingError { ref pos, .. }     => pos.clone(),
        Error::CustomErrorPos { ref pos, .. }   => pos.clone(),
        Error::CustomErrorSpan { ref span, .. } => span.clone().split().0.clone()
    };
    let (line, col) = pos.line_col();
    let line_str_len = format!("{}", line).len();

    let mut spacing = String::new();
    for _ in 0..line_str_len { spacing.push(' '); }

    let filename: Option<String> = None; // Will be replaced.

    let mut result = match filename {
        Some(filename) => format!("{}--> {}:{}:{}\n", spacing, filename, line, col),
        None           => format!("{}--> {}:{}\n", spacing, line, col)
    };

    result.push_str(&format!("{} |\n", spacing));
    result.push_str(&format!("{} | ", line));

    let line = pos.line_of();
    result.push_str(&format!("{}\n", line));
    result.push_str(&format!("{} | {}\n", spacing, underline(error, col - 1)));
    result.push_str(&format!("{} |\n", spacing));
    result.push_str(&format!("{} = {}", spacing, message(error)));

    result
}

impl<R, I: Input> fmt::Display for Error<R, I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", format(self))
    }
}

impl<R: Clone, I: Input> Clone for Error<R, I> {
    fn clone(&self) -> Error<R, I> {
        match *self {
            Error::ParsingError { ref positives, ref negatives, ref pos } => {
                Error::ParsingError {
                    positives: positives.clone(),
                    negatives: negatives.clone(),
                    pos:       pos.clone()
                }
            },
            Error::CustomErrorPos { ref message, ref pos } => {
                Error::CustomErrorPos {
                    message: message.clone(),
                    pos:     pos.clone()
                }
            },
            Error::CustomErrorSpan { ref message, ref span } => {
                Error::CustomErrorSpan {
                    message: message.clone(),
                    span:    span.clone()
                }
            }
        }
    }
}

impl<R: PartialEq, I: Input> PartialEq for Error<R, I> {
    fn eq(&self, other: &Error<R, I>) -> bool {
        match *self {
            Error::ParsingError { ref positives, ref negatives, ref pos } => {
                match *other {
                    Error::ParsingError {
                        positives: ref other_positives,
                        negatives: ref other_negatives,
                        pos:       ref other_pos
                    } => {
                        positives == other_positives && negatives == other_negatives &&
                        pos == other_pos
                    },
                    _ => false
                }
            },
            Error::CustomErrorPos { ref message, ref pos } => {
                match *other {
                    Error::CustomErrorPos {
                        message: ref other_message,
                        pos:     ref other_pos
                    } => {
                        message == other_message && pos == other_pos
                    },
                    _ => false
                }
            },
            Error::CustomErrorSpan { ref message, ref span } => {
                match *other {
                    Error::CustomErrorSpan {
                        message: ref other_message,
                        span:    ref other_span
                    } => {
                        message == other_message && span == other_span
                    },
                    _ => false
                }
            }
        }
    }
}

impl<R: Eq, I: Input> Eq for Error<R, I> {}

impl<R: Hash, I: Input> Hash for Error<R, I> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match *self {
            Error::ParsingError { ref positives, ref negatives, ref pos } => {
                positives.hash(state);
                negatives.hash(state);
                pos.hash(state);
            },
            Error::CustomErrorPos { ref message, ref pos } => {
                message.hash(state);
                pos.hash(state);
            },
            Error::CustomErrorSpan { ref message, ref span } => {
                message.hash(state);
                span.hash(state);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use std::rc::Rc;

    use super::*;
    use super::super::inputs::StringInput;
    use super::super::inputs_private::position;

    #[test]
    fn display() {
        let input = StringInput::new("ab\ncd\nef".to_owned());
        let pos = position::new(Rc::new(input), 4);
        let error: Error<(), _> = Error::CustomErrorPos {
            message: "error: big one".to_owned(),
            pos:     pos
        };

        assert_eq!(format!("{}", error), vec![
            " --> 2:2",
            "  |",
            "2 | cd",
            "  |  ^---",
            "  |",
            "  = error: big one"
        ].join("\n"));
    }
}
<commit_msg>Added parsing error formatting.<commit_after>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// 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 std::fmt;
use std::hash::{Hash, Hasher};

use super::inputs::{Input, Position, Span};

/// An `enum` which defines possible errors.
#[derive(Debug)]
pub enum Error<R, I: Input> {
    /// Generated parsing error with expected and unexpected `Rule`s and a position
    ParsingError {
        positives: Vec<R>,
        negatives: Vec<R>,
        pos:       Position<I>
    },
    /// Custom error with a message and a position
    CustomErrorPos {
        message: String,
        pos:     Position<I>
    },
    /// Custom error with a message and a span defined by a start and end position
    CustomErrorSpan {
        message: String,
        span:    Span<I>
    }
}

fn message<R: fmt::Display, I: Input>(error: &Error<R, I>) -> String {
    match error {
        &Error::ParsingError { ref positives, ref negatives, .. } => {
            match (negatives.is_empty(), positives.is_empty()) {
                (false, false) => {
                    format!(
                        "unexpected {}; expected {}",
                        enumerate(negatives),
                        enumerate(positives)
                    )
                },
                (false, true) => format!("unexpected {}", enumerate(negatives)),
                (true, false) => format!("expected {}", enumerate(positives)),
                (true, true) => "inexplicit parsing error".to_owned()
            }
        },
        &Error::CustomErrorPos { ref message, .. }  => message.to_owned(),
        &Error::CustomErrorSpan { ref message, .. } => message.to_owned()
    }
}

fn enumerate<R: fmt::Display>(rules: &Vec<R>) -> String {
    match rules.len() {
        1 => format!("{}", rules[0]),
        2 => format!("{} or {}", rules[0], rules[1]),
        l => {
            let separated = rules.iter()
                                 .take(l - 1)
                                 .map(|r| format!("{}", r))
                                 .collect::<Vec<_>>()
                                 .join(", ");
            format!("{}, or {}", separated, rules[l - 1])
        }
    }
}

fn underline<R: fmt::Display, I: Input>(error: &Error<R, I>, offset: usize) -> String {
    let mut underline = String::new();

    for _ in 0..offset { underline.push(' '); }

    match error {
        &Error::CustomErrorSpan { ref span, .. } => {
            underline.push('^');
            for _ in 2..(span.end() - span.start()) { underline.push('-'); }
            underline.push('^');
        },
        _ => underline.push_str("^---")
    };

    underline
}

// TODO: Replace None with filename.
fn format<R: fmt::Display, I: Input>(error: &Error<R, I>) -> String {
    let pos = match *error {
        Error::ParsingError { ref pos, .. }     => pos.clone(),
        Error::CustomErrorPos { ref pos, .. }   => pos.clone(),
        Error::CustomErrorSpan { ref span, .. } => span.clone().split().0.clone()
    };
    let (line, col) = pos.line_col();
    let line_str_len = format!("{}", line).len();

    let mut spacing = String::new();
    for _ in 0..line_str_len { spacing.push(' '); }

    let filename: Option<String> = None; // Will be replaced.

    let mut result = match filename {
        Some(filename) => format!("{}--> {}:{}:{}\n", spacing, filename, line, col),
        None           => format!("{}--> {}:{}\n", spacing, line, col)
    };

    result.push_str(&format!("{} |\n", spacing));
    result.push_str(&format!("{} | ", line));

    let line = pos.line_of();
    result.push_str(&format!("{}\n", line));
    result.push_str(&format!("{} | {}\n", spacing, underline(error, col - 1)));
    result.push_str(&format!("{} |\n", spacing));
    result.push_str(&format!("{} = {}", spacing, message(error)));

    result
}

impl<R: fmt::Display, I: Input> fmt::Display for Error<R, I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", format(self))
    }
}

impl<R: Clone, I: Input> Clone for Error<R, I> {
    fn clone(&self) -> Error<R, I> {
        match *self {
            Error::ParsingError { ref positives, ref negatives, ref pos } => {
                Error::ParsingError {
                    positives: positives.clone(),
                    negatives: negatives.clone(),
                    pos:       pos.clone()
                }
            },
            Error::CustomErrorPos { ref message, ref pos } => {
                Error::CustomErrorPos {
                    message: message.clone(),
                    pos:     pos.clone()
                }
            },
            Error::CustomErrorSpan { ref message, ref span } => {
                Error::CustomErrorSpan {
                    message: message.clone(),
                    span:    span.clone()
                }
            }
        }
    }
}

impl<R: PartialEq, I: Input> PartialEq for Error<R, I> {
    fn eq(&self, other: &Error<R, I>) -> bool {
        match *self {
            Error::ParsingError { ref positives, ref negatives, ref pos } => {
                match *other {
                    Error::ParsingError {
                        positives: ref other_positives,
                        negatives: ref other_negatives,
                        pos:       ref other_pos
                    } => {
                        positives == other_positives && negatives == other_negatives &&
                        pos == other_pos
                    },
                    _ => false
                }
            },
            Error::CustomErrorPos { ref message, ref pos } => {
                match *other {
                    Error::CustomErrorPos {
                        message: ref other_message,
                        pos:     ref other_pos
                    } => {
                        message == other_message && pos == other_pos
                    },
                    _ => false
                }
            },
            Error::CustomErrorSpan { ref message, ref span } => {
                match *other {
                    Error::CustomErrorSpan {
                        message: ref other_message,
                        span:    ref other_span
                    } => {
                        message == other_message && span == other_span
                    },
                    _ => false
                }
            }
        }
    }
}

impl<R: Eq, I: Input> Eq for Error<R, I> {}

impl<R: Hash, I: Input> Hash for Error<R, I> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match *self {
            Error::ParsingError { ref positives, ref negatives, ref pos } => {
                positives.hash(state);
                negatives.hash(state);
                pos.hash(state);
            },
            Error::CustomErrorPos { ref message, ref pos } => {
                message.hash(state);
                pos.hash(state);
            },
            Error::CustomErrorSpan { ref message, ref span } => {
                message.hash(state);
                span.hash(state);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use std::rc::Rc;

    use super::*;
    use super::super::inputs::StringInput;
    use super::super::inputs_private::position;

    #[test]
    fn display_parsing_error() {
        let input = StringInput::new("ab\ncd\nef".to_owned());
        let pos = position::new(Rc::new(input), 4);
        let error: Error<&str, _> = Error::ParsingError {
            positives: vec!["a", "b", "c"],
            negatives: vec!["d", "e", "f"],
            pos:     pos
        };

        assert_eq!(format!("{}", error), vec![
            " --> 2:2",
            "  |",
            "2 | cd",
            "  |  ^---",
            "  |",
            "  = unexpected d, e, or f; expected a, b, or c"
        ].join("\n"));
    }

    #[test]
    fn display_custom() {
        let input = StringInput::new("ab\ncd\nef".to_owned());
        let pos = position::new(Rc::new(input), 4);
        let error: Error<&str, _> = Error::CustomErrorPos {
            message: "error: big one".to_owned(),
            pos:     pos
        };

        assert_eq!(format!("{}", error), vec![
            " --> 2:2",
            "  |",
            "2 | cd",
            "  |  ^---",
            "  |",
            "  = error: big one"
        ].join("\n"));
    }
}
<|endoftext|>


<commit_before>use ast::*;
use std::collections::HashMap;

pub type Depth = usize;

pub struct LexicalScopes {
    depths: HashMap<VariableUseHandle, Depth>,
}

impl LexicalScopes {
    fn new() -> LexicalScopes {
        LexicalScopes { depths: HashMap::new() }
    }

    pub fn get_depth(&self, handle: &VariableUseHandle) -> Option<&Depth> {
        self.depths.get(handle)
    }
}

#[derive(Debug)]
pub enum LexicalScopesResolutionError {
    ReadLocalInItsOwnInitializer,
    VariableAlreadyExistsInScope,
    ReturnFromTopLevelCode,
}

trait LexicalScopesResolver {
    fn resolve(&self,
               &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError>;
}

#[derive(PartialEq)]
enum VariableDefinition {
    Undefined,
    Declared,
    Defined,
}

#[derive(Clone, Copy, PartialEq)]
enum FunctionType {
    None,
    Function,
}

pub struct ProgramLexicalScopesResolver {
    // Note that this doesn't track globals at all
    scopes: Vec<HashMap<Identifier, VariableDefinition>>,
    current_function: FunctionType,
    lexical_scopes: LexicalScopes,
}

impl ProgramLexicalScopesResolver {
    pub fn new() -> ProgramLexicalScopesResolver {
        ProgramLexicalScopesResolver {
            scopes: vec![],
            current_function: FunctionType::None,
            lexical_scopes: LexicalScopes::new(),
        }
    }

    fn begin_scope(&mut self) -> () {
        self.scopes.push(HashMap::new());
    }

    fn end_scope(&mut self) -> () {
        self.scopes.pop();
    }

    fn declare(&mut self, identifier: &Identifier) -> Result<(), LexicalScopesResolutionError> {
        let scopes = self.scopes.len();
        if scopes == 0 {
            return Ok(());
        };
        if self.scopes[scopes - 1].contains_key(&identifier) {
            Err(LexicalScopesResolutionError::VariableAlreadyExistsInScope)
        } else {
            self.scopes[scopes - 1].insert(*identifier, VariableDefinition::Declared);
            Ok(())
        }
    }

    fn define(&mut self, identifier: &Identifier) -> () {
        let scopes = self.scopes.len();
        if scopes == 0 {
            return;
        };
        self.scopes[scopes - 1].insert(*identifier, VariableDefinition::Defined);
    }

    fn resolve_local(&mut self, handle: VariableUseHandle, identifier: &Identifier) -> () {
        let max_depth = self.scopes.len();
        for depth in 0..max_depth {
            if self.scopes[max_depth - depth - 1].contains_key(identifier) {
                self.lexical_scopes.depths.insert(handle, depth);
                return;
            }
        }
        // If we failed to find it in the locals, it must be a global.
        // It might not be there right now, but it might appear later on.
        // We will know it only at runtime.
        self.lexical_scopes.depths.insert(handle, max_depth);
    }

    pub fn resolve(&mut self, statement: &Statement) -> Result<(), LexicalScopesResolutionError> {
        statement.resolve(self)
    }

    pub fn get_depth(&self, handle: &VariableUseHandle) -> Option<&Depth> {
        self.lexical_scopes.get_depth(handle)
    }
}

impl LexicalScopesResolver for Statement {
    fn resolve(&self,
               resolver: &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError> {
        match *self {
            Statement::Block(ref b) => {
                resolver.begin_scope();
                for statement in &b.statements {
                    try!(statement.resolve(resolver));
                }
                resolver.end_scope();
                Ok(())
            }
            Statement::VariableDefinition(ref identifier) => {
                let _ = try!(resolver.declare(identifier));
                resolver.define(identifier);
                Ok(())
            }
            Statement::VariableDefinitionWithInitalizer(ref identifier, ref initializer) => {
                let _ = try!(resolver.declare(identifier));
                try!(initializer.resolve(resolver));
                resolver.define(identifier);
                Ok(())
            }
            Statement::FunctionDefinition(ref f) => f.resolve(resolver),
            Statement::Class(ref c) => {
                let _ = try!(resolver.declare(&c.name));
                resolver.define(&c.name);
                Ok(())
            }
            Statement::Expression(ref e) => e.resolve(resolver),
            Statement::IfThen(ref s) => {
                s.condition
                    .resolve(resolver)
                    .and_then(|_| s.then_branch.resolve(resolver))
            }
            Statement::IfThenElse(ref s) => {
                s.condition
                    .resolve(resolver)
                    .and_then(|_| s.then_branch.resolve(resolver))
                    .and_then(|_| s.else_branch.resolve(resolver))
            }
            Statement::While(ref s) => {
                s.condition
                    .resolve(resolver)
                    .and_then(|_| s.body.resolve(resolver))
            }
            Statement::Print(ref e) => e.resolve(resolver),
            Statement::Return(ref r) => {
                if resolver.current_function == FunctionType::None {
                    Err(LexicalScopesResolutionError::ReturnFromTopLevelCode)
                } else {
                    match *r {
                        None => Ok(()),
                        Some(ref e) => e.resolve(resolver),
                    }
                }
            }
        }
    }
}

impl LexicalScopesResolver for Expr {
    fn resolve(&self,
               resolver: &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError> {
        match *self {
            Expr::Identifier(ref handle, ref identifier) => {
                let scopes = resolver.scopes.len();
                if scopes != 0 &&
                   resolver.scopes[scopes - 1]
                       .get(&identifier)
                       .unwrap_or(&VariableDefinition::Undefined) ==
                   &VariableDefinition::Declared {
                    Err(LexicalScopesResolutionError::ReadLocalInItsOwnInitializer)
                } else {
                    resolver.resolve_local(*handle, &identifier);
                    Ok(())
                }
            }
            Expr::Assignment(ref assigment) => assigment.resolve(resolver),
            Expr::Literal(_) => Ok(()),
            Expr::Unary(ref e) => e.right.resolve(resolver),
            Expr::Binary(ref e) => {
                e.left
                    .resolve(resolver)
                    .and_then(|_| e.right.resolve(resolver))
            }
            Expr::Logic(ref e) => {
                e.left
                    .resolve(resolver)
                    .and_then(|_| e.right.resolve(resolver))
            }
            Expr::Grouping(ref e) => e.expr.resolve(resolver),
            Expr::Call(ref e) => {
                try!(e.callee.resolve(resolver));
                for argument in e.arguments.iter() {
                    try!(argument.resolve(resolver));
                }
                Ok(())
            }
            Expr::Get(ref g) => unimplemented!(),
        }
    }
}

impl LexicalScopesResolver for Assignment {
    fn resolve(&self,
               resolver: &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError> {
        try!{self.rvalue.resolve(resolver)};
        let Target::Identifier(ref identifier) = self.lvalue;
        resolver.resolve_local(self.handle, identifier);
        Ok(())
    }
}

impl LexicalScopesResolver for FunctionDefinition {
    fn resolve(&self,
               resolver: &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError> {
        let _ = try!(resolver.declare(&self.name));
        let enclosing_function = resolver.current_function;
        resolver.current_function = FunctionType::Function;
        resolver.define(&self.name);
        resolver.begin_scope();
        for argument in self.arguments.iter() {
            let _ = try!(resolver.declare(argument));
            resolver.define(argument);
        }
        let _ = try!(self.body.resolve(resolver));
        resolver.end_scope();
        resolver.current_function = enclosing_function;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use scanner::*;
    use parser::*;
    use lexical_scope_resolver::*;

    #[test]
    fn global_variable() {
        let (tokens, _) = scan(&"var a = 0;{fun f() {print a;}}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        for statement in statements.iter() {
            assert!(lexical_scope_resolver.resolve(&statement).is_ok());
        }
        let lexical_scopes = lexical_scope_resolver.lexical_scopes;
        let mut handle_factory = VariableUseHandleFactory::new();
        let handle = handle_factory.next(); // Use of a in the function
        assert_eq!(Some(&3), lexical_scopes.get_depth(&handle));
    }

    #[test]
    fn captured_variable() {
        let (tokens, _) = scan(&"{var a = 0;fun f() {print a;}}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        for statement in statements.iter() {
            assert!(lexical_scope_resolver.resolve(&statement).is_ok());
        }
        let lexical_scopes = lexical_scope_resolver.lexical_scopes;
        let mut handle_factory = VariableUseHandleFactory::new();
        let handle = handle_factory.next(); // Use of a in the function
        assert_eq!(Some(&2), lexical_scopes.get_depth(&handle));
    }

    #[test]
    fn lexical_capture() {
        let (tokens, _) = scan(&"var a = 0;{fun f() {print a;} var a = 1;}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        for statement in statements.iter() {
            assert!(lexical_scope_resolver.resolve(&statement).is_ok());
        }
        let lexical_scopes = lexical_scope_resolver.lexical_scopes;
        let mut handle_factory = VariableUseHandleFactory::new();
        let handle = handle_factory.next(); // Use of a in the function
        assert_eq!(Some(&3), lexical_scopes.get_depth(&handle));
    }

    #[test]
    fn error_on_shadowing() {
        let (tokens, _) = scan(&"var a = 0;{var a = a;}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        assert!(lexical_scope_resolver.resolve(&statements[0]).is_ok());
        assert!(lexical_scope_resolver.resolve(&statements[1]).is_err());
    }

    #[test]
    fn error_on_local_redeclaration() {
        let (tokens, _) = scan(&"fun bad() {var a = 1;var a = 2;}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        assert!(lexical_scope_resolver.resolve(&statements[0]).is_err());
    }

    #[test]
    fn global_redeclaration_is_allowed() {
        let (tokens, _) = scan(&"var a = 1;var a = 2;");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        assert!(lexical_scope_resolver.resolve(&statements[0]).is_ok());
        assert!(lexical_scope_resolver.resolve(&statements[1]).is_ok());
    }

    #[test]
    fn error_on_return_outside_a_function() {
        let (tokens, _) = scan(&"return;");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        assert!(lexical_scope_resolver.resolve(&statements[0]).is_err());
    }
}
<commit_msg>Resolution for Get expression<commit_after>use ast::*;
use std::collections::HashMap;

pub type Depth = usize;

pub struct LexicalScopes {
    depths: HashMap<VariableUseHandle, Depth>,
}

impl LexicalScopes {
    fn new() -> LexicalScopes {
        LexicalScopes { depths: HashMap::new() }
    }

    pub fn get_depth(&self, handle: &VariableUseHandle) -> Option<&Depth> {
        self.depths.get(handle)
    }
}

#[derive(Debug)]
pub enum LexicalScopesResolutionError {
    ReadLocalInItsOwnInitializer,
    VariableAlreadyExistsInScope,
    ReturnFromTopLevelCode,
}

trait LexicalScopesResolver {
    fn resolve(&self,
               &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError>;
}

#[derive(PartialEq)]
enum VariableDefinition {
    Undefined,
    Declared,
    Defined,
}

#[derive(Clone, Copy, PartialEq)]
enum FunctionType {
    None,
    Function,
}

pub struct ProgramLexicalScopesResolver {
    // Note that this doesn't track globals at all
    scopes: Vec<HashMap<Identifier, VariableDefinition>>,
    current_function: FunctionType,
    lexical_scopes: LexicalScopes,
}

impl ProgramLexicalScopesResolver {
    pub fn new() -> ProgramLexicalScopesResolver {
        ProgramLexicalScopesResolver {
            scopes: vec![],
            current_function: FunctionType::None,
            lexical_scopes: LexicalScopes::new(),
        }
    }

    fn begin_scope(&mut self) -> () {
        self.scopes.push(HashMap::new());
    }

    fn end_scope(&mut self) -> () {
        self.scopes.pop();
    }

    fn declare(&mut self, identifier: &Identifier) -> Result<(), LexicalScopesResolutionError> {
        let scopes = self.scopes.len();
        if scopes == 0 {
            return Ok(());
        };
        if self.scopes[scopes - 1].contains_key(&identifier) {
            Err(LexicalScopesResolutionError::VariableAlreadyExistsInScope)
        } else {
            self.scopes[scopes - 1].insert(*identifier, VariableDefinition::Declared);
            Ok(())
        }
    }

    fn define(&mut self, identifier: &Identifier) -> () {
        let scopes = self.scopes.len();
        if scopes == 0 {
            return;
        };
        self.scopes[scopes - 1].insert(*identifier, VariableDefinition::Defined);
    }

    fn resolve_local(&mut self, handle: VariableUseHandle, identifier: &Identifier) -> () {
        let max_depth = self.scopes.len();
        for depth in 0..max_depth {
            if self.scopes[max_depth - depth - 1].contains_key(identifier) {
                self.lexical_scopes.depths.insert(handle, depth);
                return;
            }
        }
        // If we failed to find it in the locals, it must be a global.
        // It might not be there right now, but it might appear later on.
        // We will know it only at runtime.
        self.lexical_scopes.depths.insert(handle, max_depth);
    }

    pub fn resolve(&mut self, statement: &Statement) -> Result<(), LexicalScopesResolutionError> {
        statement.resolve(self)
    }

    pub fn get_depth(&self, handle: &VariableUseHandle) -> Option<&Depth> {
        self.lexical_scopes.get_depth(handle)
    }
}

impl LexicalScopesResolver for Statement {
    fn resolve(&self,
               resolver: &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError> {
        match *self {
            Statement::Block(ref b) => {
                resolver.begin_scope();
                for statement in &b.statements {
                    try!(statement.resolve(resolver));
                }
                resolver.end_scope();
                Ok(())
            }
            Statement::VariableDefinition(ref identifier) => {
                let _ = try!(resolver.declare(identifier));
                resolver.define(identifier);
                Ok(())
            }
            Statement::VariableDefinitionWithInitalizer(ref identifier, ref initializer) => {
                let _ = try!(resolver.declare(identifier));
                try!(initializer.resolve(resolver));
                resolver.define(identifier);
                Ok(())
            }
            Statement::FunctionDefinition(ref f) => f.resolve(resolver),
            Statement::Class(ref c) => {
                let _ = try!(resolver.declare(&c.name));
                resolver.define(&c.name);
                Ok(())
            }
            Statement::Expression(ref e) => e.resolve(resolver),
            Statement::IfThen(ref s) => {
                s.condition
                    .resolve(resolver)
                    .and_then(|_| s.then_branch.resolve(resolver))
            }
            Statement::IfThenElse(ref s) => {
                s.condition
                    .resolve(resolver)
                    .and_then(|_| s.then_branch.resolve(resolver))
                    .and_then(|_| s.else_branch.resolve(resolver))
            }
            Statement::While(ref s) => {
                s.condition
                    .resolve(resolver)
                    .and_then(|_| s.body.resolve(resolver))
            }
            Statement::Print(ref e) => e.resolve(resolver),
            Statement::Return(ref r) => {
                if resolver.current_function == FunctionType::None {
                    Err(LexicalScopesResolutionError::ReturnFromTopLevelCode)
                } else {
                    match *r {
                        None => Ok(()),
                        Some(ref e) => e.resolve(resolver),
                    }
                }
            }
        }
    }
}

impl LexicalScopesResolver for Expr {
    fn resolve(&self,
               resolver: &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError> {
        match *self {
            Expr::Identifier(ref handle, ref identifier) => {
                let scopes = resolver.scopes.len();
                if scopes != 0 &&
                   resolver.scopes[scopes - 1]
                       .get(&identifier)
                       .unwrap_or(&VariableDefinition::Undefined) ==
                   &VariableDefinition::Declared {
                    Err(LexicalScopesResolutionError::ReadLocalInItsOwnInitializer)
                } else {
                    resolver.resolve_local(*handle, &identifier);
                    Ok(())
                }
            }
            Expr::Assignment(ref assigment) => assigment.resolve(resolver),
            Expr::Literal(_) => Ok(()),
            Expr::Unary(ref e) => e.right.resolve(resolver),
            Expr::Binary(ref e) => {
                e.left
                    .resolve(resolver)
                    .and_then(|_| e.right.resolve(resolver))
            }
            Expr::Logic(ref e) => {
                e.left
                    .resolve(resolver)
                    .and_then(|_| e.right.resolve(resolver))
            }
            Expr::Grouping(ref e) => e.expr.resolve(resolver),
            Expr::Call(ref e) => {
                try!(e.callee.resolve(resolver));
                for argument in e.arguments.iter() {
                    try!(argument.resolve(resolver));
                }
                Ok(())
            }
            Expr::Get(ref g) => {
                try!(g.instance.resolve(resolver));
                Ok(())
            }
        }
    }
}

impl LexicalScopesResolver for Assignment {
    fn resolve(&self,
               resolver: &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError> {
        try!{self.rvalue.resolve(resolver)};
        let Target::Identifier(ref identifier) = self.lvalue;
        resolver.resolve_local(self.handle, identifier);
        Ok(())
    }
}

impl LexicalScopesResolver for FunctionDefinition {
    fn resolve(&self,
               resolver: &mut ProgramLexicalScopesResolver)
               -> Result<(), LexicalScopesResolutionError> {
        let _ = try!(resolver.declare(&self.name));
        let enclosing_function = resolver.current_function;
        resolver.current_function = FunctionType::Function;
        resolver.define(&self.name);
        resolver.begin_scope();
        for argument in self.arguments.iter() {
            let _ = try!(resolver.declare(argument));
            resolver.define(argument);
        }
        let _ = try!(self.body.resolve(resolver));
        resolver.end_scope();
        resolver.current_function = enclosing_function;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use scanner::*;
    use parser::*;
    use lexical_scope_resolver::*;

    #[test]
    fn global_variable() {
        let (tokens, _) = scan(&"var a = 0;{fun f() {print a;}}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        for statement in statements.iter() {
            assert!(lexical_scope_resolver.resolve(&statement).is_ok());
        }
        let lexical_scopes = lexical_scope_resolver.lexical_scopes;
        let mut handle_factory = VariableUseHandleFactory::new();
        let handle = handle_factory.next(); // Use of a in the function
        assert_eq!(Some(&3), lexical_scopes.get_depth(&handle));
    }

    #[test]
    fn captured_variable() {
        let (tokens, _) = scan(&"{var a = 0;fun f() {print a;}}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        for statement in statements.iter() {
            assert!(lexical_scope_resolver.resolve(&statement).is_ok());
        }
        let lexical_scopes = lexical_scope_resolver.lexical_scopes;
        let mut handle_factory = VariableUseHandleFactory::new();
        let handle = handle_factory.next(); // Use of a in the function
        assert_eq!(Some(&2), lexical_scopes.get_depth(&handle));
    }

    #[test]
    fn lexical_capture() {
        let (tokens, _) = scan(&"var a = 0;{fun f() {print a;} var a = 1;}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        for statement in statements.iter() {
            assert!(lexical_scope_resolver.resolve(&statement).is_ok());
        }
        let lexical_scopes = lexical_scope_resolver.lexical_scopes;
        let mut handle_factory = VariableUseHandleFactory::new();
        let handle = handle_factory.next(); // Use of a in the function
        assert_eq!(Some(&3), lexical_scopes.get_depth(&handle));
    }

    #[test]
    fn error_on_shadowing() {
        let (tokens, _) = scan(&"var a = 0;{var a = a;}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        assert!(lexical_scope_resolver.resolve(&statements[0]).is_ok());
        assert!(lexical_scope_resolver.resolve(&statements[1]).is_err());
    }

    #[test]
    fn error_on_local_redeclaration() {
        let (tokens, _) = scan(&"fun bad() {var a = 1;var a = 2;}");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        assert!(lexical_scope_resolver.resolve(&statements[0]).is_err());
    }

    #[test]
    fn global_redeclaration_is_allowed() {
        let (tokens, _) = scan(&"var a = 1;var a = 2;");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        assert!(lexical_scope_resolver.resolve(&statements[0]).is_ok());
        assert!(lexical_scope_resolver.resolve(&statements[1]).is_ok());
    }

    #[test]
    fn error_on_return_outside_a_function() {
        let (tokens, _) = scan(&"return;");
        let statements = Parser::new().parse(&tokens).unwrap();
        let mut lexical_scope_resolver = ProgramLexicalScopesResolver::new();
        assert!(lexical_scope_resolver.resolve(&statements[0]).is_err());
    }
}
<|endoftext|>