<commit_before>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use metadata::StreamInfo;
use utility::{crc8, crc16, to_u32};

pub fn frame_parser<'a>(input: &'a [u8], stream_info: &StreamInfo)
                        -> IResult<'a, &'a [u8], Frame> {
  let result = chain!(input,
    frame_header: apply!(header, stream_info) ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  );

  match result {
    IResult::Done(i, frame)   => {
      // All frame bytes before the crc-16
      let end         = (input.len() - i.len()) - 2;
      let Footer(crc) = frame.footer;

      if crc16(&input[0..end]) == crc {
        IResult::Done(i, frame)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
  match be_u8(input) {
    IResult::Done(i, byte)    => {
      let block_byte  = byte >> 4;
      let sample_byte = byte & 0x0f;
      let is_valid    = block_byte != 0b0000 && sample_byte != 0b1111;

      if is_valid {
        IResult::Done(i, (block_byte, sample_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, u8)> {
  match be_u8(input) {
    IResult::Done(i, byte)    => {
      let channel_byte       = byte >> 4;
      let channel_assignment = match channel_byte {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let size_byte = (byte >> 1) & 0b0111;

      // Checks the validity of:
      //
      // * (4 bits) channel assignment
      // * (3 bits) sample size
      // * (1 bit) last bit
      //
      // All these checks are whether of not they are reserved and should
      // return an error if so.
      let is_valid = channel_byte < 0b1011 &&
                     (size_byte != 0b0011 && size_byte != 0b0111) &&
                     (byte & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, size_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn number_type(input: &[u8], is_sample: bool,
               (size, value): (usize, u8))
               -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in 0..size {
        let byte = bytes[i] as u64;

        if byte >= 0b10000000 && byte <= 0b10111111 {
          result = (result << 6) + (byte & 0b00111111);
        } else {
          is_error = true;
          break;
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn header<'a>(input: &'a [u8], stream_info: &StreamInfo)
              -> IResult<'a, &'a [u8], Header> {
  let result = chain!(input,
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(number_type, is_variable_block_size, number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)       = tuple0;
      let (channel_assignment, size_byte) = tuple1;

      let block_size = match block_byte {
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(block_byte as u32 - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(block_byte as u32 - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => stream_info.sample_rate,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        _      => unreachable!(),
      };

      let bits_per_sample = match size_byte {
        0b0000 => stream_info.bits_per_sample as usize,
        0b0001 => 8,
        0b0010 => 12,
        0b0100 => 16,
        0b0101 => 20,
        0b0110 => 24,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  );

  match result {
    IResult::Done(i, frame_header) => {
      // All header bytes before the crc-8
      let end = (input.len() - i.len()) - 1;

      if crc8(&input[0..end]) == frame_header.crc {
        IResult::Done(i, frame_header)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)          => IResult::Error(error),
    IResult::Incomplete(need)      => IResult::Incomplete(need),
  }
}

named!(footer <&[u8], Footer>, map!(be_u16, Footer));
<commit_msg>Make parsers header and footer public for testing<commit_after>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use metadata::StreamInfo;
use utility::{crc8, crc16, to_u32};

pub fn frame_parser<'a>(input: &'a [u8], stream_info: &StreamInfo)
                        -> IResult<'a, &'a [u8], Frame> {
  let result = chain!(input,
    frame_header: apply!(header, stream_info) ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  );

  match result {
    IResult::Done(i, frame)   => {
      // All frame bytes before the crc-16
      let end         = (input.len() - i.len()) - 2;
      let Footer(crc) = frame.footer;

      if crc16(&input[0..end]) == crc {
        IResult::Done(i, frame)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      (bytes[1] as u16) >> 2;
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
  match be_u8(input) {
    IResult::Done(i, byte)    => {
      let block_byte  = byte >> 4;
      let sample_byte = byte & 0x0f;
      let is_valid    = block_byte != 0b0000 && sample_byte != 0b1111;

      if is_valid {
        IResult::Done(i, (block_byte, sample_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, u8)> {
  match be_u8(input) {
    IResult::Done(i, byte)    => {
      let channel_byte       = byte >> 4;
      let channel_assignment = match channel_byte {
        0b0000...0b0111 => ChannelAssignment::Independent,
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let size_byte = (byte >> 1) & 0b0111;

      // Checks the validity of:
      //
      // * (4 bits) channel assignment
      // * (3 bits) sample size
      // * (1 bit) last bit
      //
      // All these checks are whether of not they are reserved and should
      // return an error if so.
      let is_valid = channel_byte < 0b1011 &&
                     (size_byte != 0b0011 && size_byte != 0b0111) &&
                     (byte & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, size_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn number_type(input: &[u8], is_sample: bool,
               (size, value): (usize, u8))
               -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in 0..size {
        let byte = bytes[i] as u64;

        if byte >= 0b10000000 && byte <= 0b10111111 {
          result = (result << 6) + (byte & 0b00111111);
        } else {
          is_error = true;
          break;
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100 => opt!(input, map!(take!(1), to_u32)),
    0b1101 => opt!(input, map!(take!(2), to_u32)),
    0b1110 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

pub fn header<'a>(input: &'a [u8], stream_info: &StreamInfo)
                  -> IResult<'a, &'a [u8], Header> {
  let result = chain!(input,
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(number_type, is_variable_block_size, number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)       = tuple0;
      let (channel_assignment, size_byte) = tuple1;

      let block_size = match block_byte {
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(block_byte as u32 - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(block_byte as u32 - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => stream_info.sample_rate,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        _      => unreachable!(),
      };

      let bits_per_sample = match size_byte {
        0b0000 => stream_info.bits_per_sample as usize,
        0b0001 => 8,
        0b0010 => 12,
        0b0100 => 16,
        0b0101 => 20,
        0b0110 => 24,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  );

  match result {
    IResult::Done(i, frame_header) => {
      // All header bytes before the crc-8
      let end = (input.len() - i.len()) - 1;

      if crc8(&input[0..end]) == frame_header.crc {
        IResult::Done(i, frame_header)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)          => IResult::Error(error),
    IResult::Incomplete(need)      => IResult::Incomplete(need),
  }
}

named!(pub footer <&[u8], Footer>, map!(be_u16, Footer));
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use irc::client::prelude::*;

use plugin::*;
use FrippyClient;

use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::ResultExt;

#[derive(PluginName, Default, Debug)]
pub struct Help<C> {
    phantom: PhantomData<C>,
}

impl<C: FrippyClient> Help<C> {
    pub fn new() -> Self {
        Help {
            phantom: PhantomData,
        }
    }
}

impl<C: FrippyClient> Plugin for Help<C> {
    type Client = C;
    fn execute(&self, _: &Self::Client, _: &Message) -> ExecutionStatus {
        ExecutionStatus::Done
    }

    fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
        panic!("Help should not use threading")
    }

    fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
        client
            .send_notice(
                &command.source,
                "Available commands: help, tell, factoids, remind, quote\r\n\
                 For more detailed help call help on the specific command.\r\n\
                 Example: 'remind help'",
            )
            .context(FrippyErrorKind::Connection)?;

        Ok(())
    }

    fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
        Err(String::from("Help has not been added yet."))
    }
}
<commit_msg>Help: Mention Unicode Plugin<commit_after>use std::marker::PhantomData;

use irc::client::prelude::*;

use plugin::*;
use FrippyClient;

use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::ResultExt;

#[derive(PluginName, Default, Debug)]
pub struct Help<C> {
    phantom: PhantomData<C>,
}

impl<C: FrippyClient> Help<C> {
    pub fn new() -> Self {
        Help {
            phantom: PhantomData,
        }
    }
}

impl<C: FrippyClient> Plugin for Help<C> {
    type Client = C;
    fn execute(&self, _: &Self::Client, _: &Message) -> ExecutionStatus {
        ExecutionStatus::Done
    }

    fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
        panic!("Help should not use threading")
    }

    fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
        client
            .send_notice(
                &command.source,
                "Available commands: help, tell, factoids, remind, quote, unicode\r\n\
                 For more detailed help call help on the specific command.\r\n\
                 Example: 'remind help'",
            )
            .context(FrippyErrorKind::Connection)?;

        Ok(())
    }

    fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
        Err(String::from("Help has not been added yet."))
    }
}
<|endoftext|>


<commit_before><commit_msg>Return the norm of Jacobian<commit_after><|endoftext|>


<commit_before>use create::Regexp;

pub enum Inst {
    Char(char),
    Match,
    Jump(usize),
    Split(usize, usize)
}

pub fn compile_regexp(regexp: Regexp) -> Vec<Inst> {
    let mut insts = compile_regexp_offset(regexp, 0);
    insts.push(Inst::Match);
    insts
}

fn compile_regexp_offset(regexp: Regexp, offset: usize) -> Vec<Inst> {
    let mut insts = Vec::new();
    use create::Regexp::*;
    use self::Inst::{Jump,Split};
    match regexp {
        Char(c) => {
            let char_inst = Inst::Char(c);
            insts.push(char_inst);
        },
        Concatenation(regexps) => {
            let mut num_insts = 0;
            for sub_regexp in regexps {
                let mut sub_insts = compile_regexp_offset(sub_regexp,
                                                          offset + num_insts);
                num_insts += sub_insts.len();
                insts.append(&mut sub_insts);
            }
        },
        Alternation(regexps) => {
            let mut alternatives_insts: Vec<Vec<Inst>> = Vec::new();
            for sub_regexp in regexps {
                let sub_insts = compile_regexp_offset(sub_regexp, offset);
                alternatives_insts.push(sub_insts);
            }
            let total_len = alternatives_insts.iter()
                .fold(0, |sum,x| sum + x.len())
                + alternatives_insts.len() - 1; // + alternates_insts.len() to account
                                              // for the Jump instruction we add
            for sub_insts in &mut alternatives_insts {
                let jump_to_end = Jump(total_len + offset);
                sub_insts.push(jump_to_end);
            }
        },
        Optional(inner_regexp) => {
            let mut inner_insts = compile_regexp_offset(*inner_regexp,
                                                        offset + 1);
            let split_inst = Split(offset + 1, offset + inner_insts.len() + 1);
            insts.push(split_inst);
            insts.append(&mut inner_insts);
        },
        Repeated(inner_regexp) => {
            let mut inner_insts = compile_regexp_offset(*inner_regexp,
                                                        offset);
            let split_inst = Split(offset, offset + inner_insts.len() + 2);
            insts.append(&mut inner_insts);
            insts.push(split_inst);
        },
        OptionalRepeated(inner_regexp) => {
            let mut inner_insts = compile_regexp_offset(*inner_regexp,
                                                        offset + 1);
            let split_inst = Split(offset, offset + inner_insts.len() + 2);
            let jump_inst = Jump(offset);
            insts.push(split_inst);
            insts.append(&mut inner_insts);
            insts.push(jump_inst);
        }
    }
    insts
}

// struct State {
//     c: Option<char>,
//     action: Action
// }

// enum Action {
//     AdvanceTo(Vec<Box<State>>),
//     Match
// }

// fn construct_state_tree<'a>(regexp: Regexp) -> Box<State> {
//     let match_state = Box::new(State {c: None, action: Action::Match });
//     construct_state_tree_next(regexp, match_state)
// }

// fn construct_state_tree_next<'a>(regexp: Regexp, next: Box<State>) -> Box<State> {
//     let match_state = Box::new(State {c: None, action: Action::Match });
//     use self::Action::*;
//     if let Regexp::Concatenation(regexps) = regexp {
//         let mut concated_states: Vec<Box<State>> = Vec::new();
//         for inner_regexp in regexps {
//             let sub_state = construct_state_tree(inner_regexp);
//             concated_states.push(sub_state);
//         }
//         let mut prev_last = next;
//         while concated_states.len() > 0 {
//             let mut last = concated_states.pop().unwrap();
//             match last.action {
//                 AdvanceTo(ref mut next_states) => {
//                     next_states.push(prev_last);
//                 },
//                 Match => panic!("Illegal State: Sub-state of concatenation cannot \
//                                  contain Match")
//             }
//             prev_last = last;
//         }
//         prev_last
//     } else if let Regexp::Alternation(regexps) = regexp {
//         let mut parts: Vec<Box<State>> = Vec::new();
//         for inner_regexp in regexps {
//             let sub_state =
//                 construct_state_tree_next(inner_regexp, next);
//             parts.push(sub_state);
//         }
//         let wrapping_state = State { c: None, action: AdvanceTo(parts) };
//         Box::new(wrapping_state)
//     } else {
//         panic!("Error");
//     }
//     match regexp {
//         Regexp::Concatenation(regexps) => {
//             let mut concated_states: Vec<Box<State>> = Vec::new();
//             for inner_regexp in regexps {
//                 let sub_state = construct_state_tree(inner_regexp);
//                 concated_states.push(sub_state);
//             }
//             let mut prev_last = next;
//             while concated_states.len() > 0 {
//                 let mut last = concated_states.pop().unwrap();
//                 match last.action {
//                     AdvanceTo(ref mut next_states) => {
//                         next_states.push(prev_last);
//                     },
//                     Match => panic!("Illegal State: Sub-state of concatenation cannot \
//                                      contain Match")
//                 }
//                 prev_last = last;
//             }
//             prev_last
//         },
//         Regexp::Alternation(regexps) => {
//             let mut parts: Vec<Box<State>> = Vec::new();
//             for inner_regexp in regexps {
//                 let sub_state =
//                     construct_state_tree_next(inner_regexp, next);
//                 parts.push(sub_state);
//             }
//             let wrapping_state = State { c: None, action: AdvanceTo(parts) };
//             Box::new(wrapping_state)
//         }
//         Regexp::Char(c) => Box::new(State {c: Some(c), action: AdvanceTo(vec![next])}),
//         Regexp::Optional(inner_regexp) => {
//             let inner_state = construct_state_tree_next(*inner_regexp, next);
//             let optional_state = Box::new(State { c: None,
//                                              action: AdvanceTo(vec![inner_state,
//                                                                     next])});
//             optional_state
//         },
//         Regexp::Repeated(inner_regexp) => {
//             let inner_state = construct_state_tree_next(*inner_regexp, next);
//             let mut repeated_state = Box::new(State { c: None,
//                                              action: AdvanceTo(vec![inner_state,
//                                                                     next])});
//             match repeated_state.action {
//                 AdvanceTo(ref mut next_states) => next_states.push(repeated_state),
//                 Match => unreachable!()
//             }
//             repeated_state
//         },
//         _ => panic!("Hello")

//     }
// }
<commit_msg>Added ThreadState functionality<commit_after>use create::Regexp;

pub enum Inst {
    Char(char),
    Match,
    Jump(usize),
    Split(usize, usize)
}

pub struct ThreadState {
    /// The compiled regexp program
    insts: Vec<Inst>,
    /// The program counters; indexes into insts
    pcs: Vec<usize>
}

impl ThreadState {
    pub fn from_regexp(regexp: Regexp) -> ThreadState {
        ThreadState { insts: compile_regexp(regexp),
                      pcs: vec![0] }
    }
}

pub fn update_threadstate(thread_state: &mut ThreadState, c: char) {
    let mut new_pcs = Vec::new();
    for index in &thread_state.pcs {
        let inst = &(thread_state.insts[*index]);
        match *inst {
            Inst::Char(inst_char) => if c == inst_char {
                new_pcs.push(index+1);
            },
            Inst::Match => (),
            Inst::Jump(jump_index) => new_pcs.push(jump_index),
            Inst::Split(s1_index, s2_index) => {
                new_pcs.push(s1_index);
                new_pcs.push(s2_index);
            }
        }
    }
    thread_state.pcs = new_pcs;
}

pub fn compile_regexp(regexp: Regexp) -> Vec<Inst> {
    let mut insts = compile_regexp_offset(regexp, 0);
    insts.push(Inst::Match);
    insts
}

fn compile_regexp_offset(regexp: Regexp, offset: usize) -> Vec<Inst> {
    let mut insts = Vec::new();
    use create::Regexp::*;
    use self::Inst::{Jump,Split};
    match regexp {
        Char(c) => {
            let char_inst = Inst::Char(c);
            insts.push(char_inst);
        },
        Concatenation(regexps) => {
            let mut num_insts = 0;
            for sub_regexp in regexps {
                let mut sub_insts = compile_regexp_offset(sub_regexp,
                                                          offset + num_insts);
                num_insts += sub_insts.len();
                insts.append(&mut sub_insts);
            }
        },
        Alternation(regexps) => {
            let mut alternatives_insts: Vec<Vec<Inst>> = Vec::new();
            for sub_regexp in regexps {
                let sub_insts = compile_regexp_offset(sub_regexp, offset);
                alternatives_insts.push(sub_insts);
            }
            let total_len = alternatives_insts.iter()
                .fold(0, |sum,x| sum + x.len())
                + alternatives_insts.len() - 1; // + alternates_insts.len() to account
                                              // for the Jump instruction we add
            for sub_insts in &mut alternatives_insts {
                let jump_to_end = Jump(total_len + offset);
                sub_insts.push(jump_to_end);
            }
        },
        Optional(inner_regexp) => {
            let mut inner_insts = compile_regexp_offset(*inner_regexp,
                                                        offset + 1);
            let split_inst = Split(offset + 1, offset + inner_insts.len() + 1);
            insts.push(split_inst);
            insts.append(&mut inner_insts);
        },
        Repeated(inner_regexp) => {
            let mut inner_insts = compile_regexp_offset(*inner_regexp,
                                                        offset);
            let split_inst = Split(offset, offset + inner_insts.len() + 2);
            insts.append(&mut inner_insts);
            insts.push(split_inst);
        },
        OptionalRepeated(inner_regexp) => {
            let mut inner_insts = compile_regexp_offset(*inner_regexp,
                                                        offset + 1);
            let split_inst = Split(offset, offset + inner_insts.len() + 2);
            let jump_inst = Jump(offset);
            insts.push(split_inst);
            insts.append(&mut inner_insts);
            insts.push(jump_inst);
        }
    }
    insts
}

// struct State {
//     c: Option<char>,
//     action: Action
// }

// enum Action {
//     AdvanceTo(Vec<Box<State>>),
//     Match
// }

// fn construct_state_tree<'a>(regexp: Regexp) -> Box<State> {
//     let match_state = Box::new(State {c: None, action: Action::Match });
//     construct_state_tree_next(regexp, match_state)
// }

// fn construct_state_tree_next<'a>(regexp: Regexp, next: Box<State>) -> Box<State> {
//     let match_state = Box::new(State {c: None, action: Action::Match });
//     use self::Action::*;
//     if let Regexp::Concatenation(regexps) = regexp {
//         let mut concated_states: Vec<Box<State>> = Vec::new();
//         for inner_regexp in regexps {
//             let sub_state = construct_state_tree(inner_regexp);
//             concated_states.push(sub_state);
//         }
//         let mut prev_last = next;
//         while concated_states.len() > 0 {
//             let mut last = concated_states.pop().unwrap();
//             match last.action {
//                 AdvanceTo(ref mut next_states) => {
//                     next_states.push(prev_last);
//                 },
//                 Match => panic!("Illegal State: Sub-state of concatenation cannot \
//                                  contain Match")
//             }
//             prev_last = last;
//         }
//         prev_last
//     } else if let Regexp::Alternation(regexps) = regexp {
//         let mut parts: Vec<Box<State>> = Vec::new();
//         for inner_regexp in regexps {
//             let sub_state =
//                 construct_state_tree_next(inner_regexp, next);
//             parts.push(sub_state);
//         }
//         let wrapping_state = State { c: None, action: AdvanceTo(parts) };
//         Box::new(wrapping_state)
//     } else {
//         panic!("Error");
//     }
//     match regexp {
//         Regexp::Concatenation(regexps) => {
//             let mut concated_states: Vec<Box<State>> = Vec::new();
//             for inner_regexp in regexps {
//                 let sub_state = construct_state_tree(inner_regexp);
//                 concated_states.push(sub_state);
//             }
//             let mut prev_last = next;
//             while concated_states.len() > 0 {
//                 let mut last = concated_states.pop().unwrap();
//                 match last.action {
//                     AdvanceTo(ref mut next_states) => {
//                         next_states.push(prev_last);
//                     },
//                     Match => panic!("Illegal State: Sub-state of concatenation cannot \
//                                      contain Match")
//                 }
//                 prev_last = last;
//             }
//             prev_last
//         },
//         Regexp::Alternation(regexps) => {
//             let mut parts: Vec<Box<State>> = Vec::new();
//             for inner_regexp in regexps {
//                 let sub_state =
//                     construct_state_tree_next(inner_regexp, next);
//                 parts.push(sub_state);
//             }
//             let wrapping_state = State { c: None, action: AdvanceTo(parts) };
//             Box::new(wrapping_state)
//         }
//         Regexp::Char(c) => Box::new(State {c: Some(c), action: AdvanceTo(vec![next])}),
//         Regexp::Optional(inner_regexp) => {
//             let inner_state = construct_state_tree_next(*inner_regexp, next);
//             let optional_state = Box::new(State { c: None,
//                                              action: AdvanceTo(vec![inner_state,
//                                                                     next])});
//             optional_state
//         },
//         Regexp::Repeated(inner_regexp) => {
//             let inner_state = construct_state_tree_next(*inner_regexp, next);
//             let mut repeated_state = Box::new(State { c: None,
//                                              action: AdvanceTo(vec![inner_state,
//                                                                     next])});
//             match repeated_state.action {
//                 AdvanceTo(ref mut next_states) => next_states.push(repeated_state),
//                 Match => unreachable!()
//             }
//             repeated_state
//         },
//         _ => panic!("Hello")

//     }
// }
<|endoftext|>


<commit_before>use deuterium::*;

#[test]
fn update() {

    let jedi_table = TableDef::new("jedi");
    let name = NamedField::<String>::field_of("name", &jedi_table);

    let query = jedi_table.delete().all();
    assert_sql!(query, "DELETE FROM jedi;")

    let query = jedi_table.delete();
    assert_sql!(query, "DELETE FROM jedi WHERE true = false;")

    let query = jedi_table.delete().where_(name.is("Anakin Skywalker".to_string()));
    assert_sql!(query, "DELETE FROM jedi WHERE name = 'Anakin Skywalker';");

    let table_b = TableDef::new("table_b");
    let name_b = NamedField::<String>::field_of("name", &table_b).qual();

    let query = jedi_table
        .delete()
        .only()
        .using(&table_b)
        .where_(name.qual().is(name_b.qual()));

    assert_sql!(query, "DELETE FROM ONLY jedi USING table_b WHERE jedi.name = table_b.name;");

}<commit_msg>test: fix test method name<commit_after>use deuterium::*;

#[test]
fn delete() {

    let jedi_table = TableDef::new("jedi");
    let name = NamedField::<String>::field_of("name", &jedi_table);

    let query = jedi_table.delete().all();
    assert_sql!(query, "DELETE FROM jedi;")

    let query = jedi_table.delete();
    assert_sql!(query, "DELETE FROM jedi WHERE true = false;")

    let query = jedi_table.delete().where_(name.is("Anakin Skywalker".to_string()));
    assert_sql!(query, "DELETE FROM jedi WHERE name = 'Anakin Skywalker';");

    let table_b = TableDef::new("table_b");
    let name_b = NamedField::<String>::field_of("name", &table_b).qual();

    let query = jedi_table
        .delete()
        .only()
        .using(&table_b)
        .where_(name.qual().is(name_b.qual()));

    assert_sql!(query, "DELETE FROM ONLY jedi USING table_b WHERE jedi.name = table_b.name;");

}<|endoftext|>


<commit_before>extern crate hyper;
extern crate patron;

static CLIENT_ID: &'static str = "39515280290e3b9c67eb";
static CLIENT_SECRET: &'static str = "53742fb491d5c17170c60c3330553f226c0fc469";

#[test]
#[ignore]
fn get_commits() {

  let client: patron::Client = patron::from_str("https://api.github.com")
    .add_header(hyper::header::UserAgent("patron".to_string()))
    .add_query_param("client_id", CLIENT_ID)
    .add_query_param("client_secret", CLIENT_SECRET)
    .build()
    .unwrap();

  let commits = client.get("/repos/scull7/patron/commits")
    //.add_query_param("until", "2017-04-27T23:20:00Z")
    .send()
    .expect("Failed to retrieve commits");

  println!("Commits: {:?}", commits);

}
<commit_msg>github test passes<commit_after>extern crate hyper;
extern crate patron;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

static CLIENT_ID: &'static str = "39515280290e3b9c67eb";
static CLIENT_SECRET: &'static str = "53742fb491d5c17170c60c3330553f226c0fc469";

#[derive(Debug, Deserialize)]
struct User {
  name: String,
  email: String,
  date: String,
}

#[derive(Debug, Deserialize)]
struct CommitInfo {
  comment_count: u64,
  message: String,
  author: User,
  committer: User,
}

#[derive(Debug, Deserialize)]
struct Commit {
  url: String,
  sha: String,
  commit: CommitInfo,
}

#[test]
fn get_commits() {

  let client: patron::Client = patron::from_str("https://api.github.com")
    .add_header(hyper::header::UserAgent("patron".to_string()))
    .add_query_param("client_id", CLIENT_ID)
    .add_query_param("client_secret", CLIENT_SECRET)
    .build()
    .unwrap();

  let commits: Vec<Commit> =
    serde_json::from_value(
      client
        .get("/repos/scull7/patron/commits")
        .add_query_param("until", "2017-04-27T23:20:00Z")
        .send()
        .expect("Failed to retrieve commits")
        .json()
        .unwrap(),
    )
        .unwrap();

  println!("Commits: {:?}", commits);

  assert_eq!(commits.len(), 13);
  assert!(
    commits
      .iter()
      .all(|c| c.commit.author.name == "Nathan Sculli")
  );

}
<|endoftext|>


<commit_before>use std::fmt;

use std::collections::HashMap;
use std::hash::{Hash, Hasher};

/// A kind of annotation that can be set on an expression.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum AnnotationKind {
    BuilderImplementation,
    Predicate,
    Vectorize,
    TileSize,
    GrainSize,
    AlwaysUseRuntime,
    Size,
    BranchSelectivity,
    NumKeys,
}

impl fmt::Display for AnnotationKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}",
               match *self {
                   AnnotationKind::BuilderImplementation => "impl",
                   AnnotationKind::TileSize => "tile_size",
                   AnnotationKind::GrainSize => "grain_size",
                   AnnotationKind::Size => "size",
                   AnnotationKind::BranchSelectivity => "branch_selectivity",
                   AnnotationKind::NumKeys => "num_keys",
                   AnnotationKind::Predicate => "predicate",
                   AnnotationKind::Vectorize => "vectorize",
                   AnnotationKind::AlwaysUseRuntime => "always_use_runtime",
               })
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// A annotation value for the way a builder is implemented.
pub enum BuilderImplementationKind {
    Local,
    Global,
}

impl fmt::Display for BuilderImplementationKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use annotations::BuilderImplementationKind::*;
        let text = match *self {
            Local => "local",
            Global => "global",
        };
        f.write_str(text)
    }
}

/// An internal representation of annotation values.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
enum AnnotationValue {
    VBuilderImplementation(BuilderImplementationKind),
    VTileSize(i32),
    VGrainSize(i32),
    VSize(i64),
    VNumKeys(i64),
    VBranchSelectivity(i32), // Fractions of 10,000
    VPredicate,
    VVectorize,
    VAlwaysUseRuntime,
}

impl fmt::Display for AnnotationValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       write!(f, "{}",
              match *self {
                   AnnotationValue::VBuilderImplementation(ref kind) => format!("{}", kind),
                   AnnotationValue::VTileSize(ref v) => format!("{}", v),
                   AnnotationValue::VGrainSize(ref v) => format!("{}", v),
                   AnnotationValue::VSize(ref v) => format!("{}", v),
                   AnnotationValue::VBranchSelectivity(ref v) => format!("{}", v),
                   AnnotationValue::VNumKeys(ref v) => format!("{}", v),
                   // These are flags, so their existence indicates that the value is `true`.
                   AnnotationValue::VPredicate => "true".to_string(),
                   AnnotationValue::VVectorize => "true".to_string(),
                   AnnotationValue::VAlwaysUseRuntime => "true".to_string(),
               })
    }
}

#[derive(Clone, Debug)]
pub struct Annotations {
    values: HashMap<AnnotationKind, AnnotationValue>,
}

impl Annotations {
    pub fn new() -> Annotations {
        return Annotations {
            values: HashMap::new(),
        };
    }

    pub fn builder_implementation(&self) -> Option<BuilderImplementationKind> {
        if let Some(s) = self.values.get(&AnnotationKind::BuilderImplementation) {
            if let AnnotationValue::VBuilderImplementation(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_builder_implementation(&mut self, value: BuilderImplementationKind) {
        self.values.insert(AnnotationKind::BuilderImplementation, AnnotationValue::VBuilderImplementation(value));
    }

    pub fn tile_size(&self) -> Option<i32> {
        if let Some(s) = self.values.get(&AnnotationKind::TileSize) {
            if let AnnotationValue::VTileSize(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_tile_size(&mut self, value: i32) {
        self.values.insert(AnnotationKind::TileSize, AnnotationValue::VTileSize(value));
    }

    pub fn grain_size(&self) -> Option<i32> {
        if let Some(s) = self.values.get(&AnnotationKind::GrainSize) {
            if let AnnotationValue::VGrainSize(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_grain_size(&mut self, value: i32) {
        self.values.insert(AnnotationKind::GrainSize, AnnotationValue::VGrainSize(value));
    }

    pub fn size(&self) -> Option<i64> {
        if let Some(s) = self.values.get(&AnnotationKind::Size) {
            if let AnnotationValue::VSize(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_size(&mut self, value: i64) {
        self.values.insert(AnnotationKind::Size, AnnotationValue::VSize(value));
    }

    pub fn num_keys(&self) -> Option<i64> {
        if let Some(s) = self.values.get(&AnnotationKind::NumKeys) {
            if let AnnotationValue::VNumKeys(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_num_keys(&mut self, value: i64) {
        self.values.insert(AnnotationKind::NumKeys, AnnotationValue::VNumKeys(value));
    }

    pub fn branch_selectivity(&self) -> Option<i32> {
        if let Some(s) = self.values.get(&AnnotationKind::BranchSelectivity) {
            if let AnnotationValue::VBranchSelectivity(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_branch_selectivity(&mut self, value: i32) {
        self.values.insert(AnnotationKind::BranchSelectivity, AnnotationValue::VBranchSelectivity(value));
    }

    pub fn predicate(&self) -> bool {
        return self.values.contains_key(&AnnotationKind::Predicate);
    }

    pub fn set_predicate(&mut self, val: bool) {
        if val {
            self.values.insert(AnnotationKind::Predicate, AnnotationValue::VPredicate);
        } else {
            self.values.remove(&AnnotationKind::Predicate);
        }
    }

    pub fn vectorize(&self) -> bool {
        return self.values.contains_key(&AnnotationKind::Vectorize);
    }

    pub fn set_vectorize(&mut self, val: bool) {
        if val {
            self.values.insert(AnnotationKind::Vectorize, AnnotationValue::VVectorize);
        } else {
            self.values.remove(&AnnotationKind::Vectorize);
        }
    }

    pub fn always_use_runtime(&self) -> bool {
        return self.values.contains_key(&AnnotationKind::AlwaysUseRuntime);
    }

    pub fn set_always_use_runtime(&mut self, val: bool) {
        if val {
            self.values.insert(AnnotationKind::AlwaysUseRuntime, AnnotationValue::VAlwaysUseRuntime);
        } else {
            self.values.remove(&AnnotationKind::AlwaysUseRuntime);
        }
    }

    pub fn is_empty(&self) -> bool {
        return self.values.is_empty();
    }
}

impl PartialEq for Annotations {
    fn eq(&self, other: &Annotations) -> bool {
        if self.values.len() != other.values.len() {
            return false;
        }
        for (key, val) in self.values.iter() {
            let val2 = other.values.get(key);
            if val2.is_none() {
                return false;
            } else if val != val2.unwrap() {
                return false;
            }
        }
        return true;
    }
}

impl Eq for Annotations {}

impl Hash for Annotations {
    fn hash<H: Hasher>(&self, state: &mut H) {
        for (ref key, ref value) in self.values.iter() {
            key.hash(state);
            value.hash(state);
        }
    }
}

impl fmt::Display for Annotations {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut annotations = Vec::new();
        for (ref kind, ref value) in self.values.iter() {
            annotations.push(format!("{}:{}", kind, value));
        }

        // Sort the annotations alphabetically when displaying them so the result is deterministic.
        annotations.sort();

        if annotations.len() == 0 {
            write!(f, "")
        } else {
            write!(f, "@({})", annotations.join(","))
        }
    }
}
<commit_msg>Fix for hashing annotations (#263)<commit_after>use std::fmt;

use std::collections::BTreeMap;

/// A kind of annotation that can be set on an expression.
#[derive(Clone, Debug, Ord, PartialOrd, PartialEq, Eq, Hash)]
pub enum AnnotationKind {
    BuilderImplementation,
    Predicate,
    Vectorize,
    TileSize,
    GrainSize,
    AlwaysUseRuntime,
    Size,
    BranchSelectivity,
    NumKeys,
}

impl fmt::Display for AnnotationKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}",
               match *self {
                   AnnotationKind::BuilderImplementation => "impl",
                   AnnotationKind::TileSize => "tile_size",
                   AnnotationKind::GrainSize => "grain_size",
                   AnnotationKind::Size => "size",
                   AnnotationKind::BranchSelectivity => "branch_selectivity",
                   AnnotationKind::NumKeys => "num_keys",
                   AnnotationKind::Predicate => "predicate",
                   AnnotationKind::Vectorize => "vectorize",
                   AnnotationKind::AlwaysUseRuntime => "always_use_runtime",
               })
    }
}

#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
/// A annotation value for the way a builder is implemented.
pub enum BuilderImplementationKind {
    Local,
    Global,
}

impl fmt::Display for BuilderImplementationKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use annotations::BuilderImplementationKind::*;
        let text = match *self {
            Local => "local",
            Global => "global",
        };
        f.write_str(text)
    }
}

/// An internal representation of annotation values.
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
enum AnnotationValue {
    VBuilderImplementation(BuilderImplementationKind),
    VTileSize(i32),
    VGrainSize(i32),
    VSize(i64),
    VNumKeys(i64),
    VBranchSelectivity(i32), // Fractions of 10,000
    VPredicate,
    VVectorize,
    VAlwaysUseRuntime,
}

impl fmt::Display for AnnotationValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       write!(f, "{}",
              match *self {
                   AnnotationValue::VBuilderImplementation(ref kind) => format!("{}", kind),
                   AnnotationValue::VTileSize(ref v) => format!("{}", v),
                   AnnotationValue::VGrainSize(ref v) => format!("{}", v),
                   AnnotationValue::VSize(ref v) => format!("{}", v),
                   AnnotationValue::VBranchSelectivity(ref v) => format!("{}", v),
                   AnnotationValue::VNumKeys(ref v) => format!("{}", v),
                   // These are flags, so their existence indicates that the value is `true`.
                   AnnotationValue::VPredicate => "true".to_string(),
                   AnnotationValue::VVectorize => "true".to_string(),
                   AnnotationValue::VAlwaysUseRuntime => "true".to_string(),
               })
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Annotations {
    values: BTreeMap<AnnotationKind, AnnotationValue>,
}

impl Annotations {
    pub fn new() -> Annotations {
        return Annotations {
            values: BTreeMap::new(),
        };
    }

    pub fn builder_implementation(&self) -> Option<BuilderImplementationKind> {
        if let Some(s) = self.values.get(&AnnotationKind::BuilderImplementation) {
            if let AnnotationValue::VBuilderImplementation(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_builder_implementation(&mut self, value: BuilderImplementationKind) {
        self.values.insert(AnnotationKind::BuilderImplementation, AnnotationValue::VBuilderImplementation(value));
    }

    pub fn tile_size(&self) -> Option<i32> {
        if let Some(s) = self.values.get(&AnnotationKind::TileSize) {
            if let AnnotationValue::VTileSize(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_tile_size(&mut self, value: i32) {
        self.values.insert(AnnotationKind::TileSize, AnnotationValue::VTileSize(value));
    }

    pub fn grain_size(&self) -> Option<i32> {
        if let Some(s) = self.values.get(&AnnotationKind::GrainSize) {
            if let AnnotationValue::VGrainSize(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_grain_size(&mut self, value: i32) {
        self.values.insert(AnnotationKind::GrainSize, AnnotationValue::VGrainSize(value));
    }

    pub fn size(&self) -> Option<i64> {
        if let Some(s) = self.values.get(&AnnotationKind::Size) {
            if let AnnotationValue::VSize(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_size(&mut self, value: i64) {
        self.values.insert(AnnotationKind::Size, AnnotationValue::VSize(value));
    }

    pub fn num_keys(&self) -> Option<i64> {
        if let Some(s) = self.values.get(&AnnotationKind::NumKeys) {
            if let AnnotationValue::VNumKeys(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_num_keys(&mut self, value: i64) {
        self.values.insert(AnnotationKind::NumKeys, AnnotationValue::VNumKeys(value));
    }

    pub fn branch_selectivity(&self) -> Option<i32> {
        if let Some(s) = self.values.get(&AnnotationKind::BranchSelectivity) {
            if let AnnotationValue::VBranchSelectivity(ref s) = *s {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_branch_selectivity(&mut self, value: i32) {
        self.values.insert(AnnotationKind::BranchSelectivity, AnnotationValue::VBranchSelectivity(value));
    }

    pub fn predicate(&self) -> bool {
        return self.values.contains_key(&AnnotationKind::Predicate);
    }

    pub fn set_predicate(&mut self, val: bool) {
        if val {
            self.values.insert(AnnotationKind::Predicate, AnnotationValue::VPredicate);
        } else {
            self.values.remove(&AnnotationKind::Predicate);
        }
    }

    pub fn vectorize(&self) -> bool {
        return self.values.contains_key(&AnnotationKind::Vectorize);
    }

    pub fn set_vectorize(&mut self, val: bool) {
        if val {
            self.values.insert(AnnotationKind::Vectorize, AnnotationValue::VVectorize);
        } else {
            self.values.remove(&AnnotationKind::Vectorize);
        }
    }

    pub fn always_use_runtime(&self) -> bool {
        return self.values.contains_key(&AnnotationKind::AlwaysUseRuntime);
    }

    pub fn set_always_use_runtime(&mut self, val: bool) {
        if val {
            self.values.insert(AnnotationKind::AlwaysUseRuntime, AnnotationValue::VAlwaysUseRuntime);
        } else {
            self.values.remove(&AnnotationKind::AlwaysUseRuntime);
        }
    }

    pub fn is_empty(&self) -> bool {
        return self.values.is_empty();
    }
}

impl fmt::Display for Annotations {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut annotations = Vec::new();
        for (ref kind, ref value) in self.values.iter() {
            annotations.push(format!("{}:{}", kind, value));
        }

        // Sort the annotations alphabetically when displaying them so the result is deterministic.
        annotations.sort();

        if annotations.len() == 0 {
            write!(f, "")
        } else {
            write!(f, "@({})", annotations.join(","))
        }
    }
}
<|endoftext|>


<commit_before>use ::cairo;
use ::glib::translate::*;
use ::glib_sys;
use ::libc;

use std::f64::consts::*;

use cairo::MatrixTrait;
use cssparser::{Parser, ParserInput, Token, ParseError as CssParseError};

use error::*;
use parsers::{Parse, ParseError, optional_comma};

impl Parse for cairo::Matrix {
    type Data = ();
    type Err = AttributeError;

    fn parse (s: &str, _: ()) -> Result<cairo::Matrix, AttributeError> {
        parse_transform (s)
    }
}

// This parser is for the "transform" attribute in SVG.
// Its operataion and grammar are described here:
// https://www.w3.org/TR/SVG/coords.html#TransformAttribute

pub fn parse_transform(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let matrix = parse_transform_list(s)?;

    matrix.try_invert ().map (|_| matrix)
        .map_err (|_| AttributeError::Value ("invalid transformation matrix".to_string ()))
}

fn parse_transform_list(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let mut matrix = cairo::Matrix::identity();

    loop {
        let m = parse_transform_command(&mut parser)?;
        matrix = cairo::Matrix::multiply(&m, &matrix);

        if parser.is_exhausted() {
            break;
        }

        optional_comma(&mut parser);
    }

    Ok(matrix)
}

fn make_expected_function_error() -> AttributeError {
    AttributeError::from(ParseError::new("expected matrix|translate|scale|rotate|skewX|skewY"))
}

fn parse_transform_command(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match parser.next()?.clone() {
        Token::Function(ref name) => parse_transform_function(name, parser),

        Token::Ident(ref name) => {
            parser.expect_parenthesis_block()?;
            parse_transform_function(name, parser)
        },

        _ => Err(make_expected_function_error()),
    }
}

fn parse_transform_function(name: &str, parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match name {
        "matrix"    => parse_matrix_args(parser),
        "translate" => parse_translate_args(parser),
        "scale"     => parse_scale_args(parser),
        "rotate"    => parse_rotate_args(parser),
        "skewX"     => parse_skewx_args(parser),
        "skewY"     => parse_skewy_args(parser),
        _           => Err(make_expected_function_error()),
    }
}

fn parse_matrix_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let xx = p.expect_number()? as f64;
        optional_comma(p);

        let yx = p.expect_number()? as f64;
        optional_comma(p);

        let xy = p.expect_number()? as f64;
        optional_comma(p);

        let yy = p.expect_number()? as f64;
        optional_comma(p);

        let x0 = p.expect_number()? as f64;
        optional_comma(p);

        let y0 = p.expect_number()? as f64;

        Ok(cairo::Matrix::new(xx, yx, xy, yy, x0, y0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_translate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let tx = p.expect_number()?;

        let ty = p.try(|p| -> Result<f32, CssParseError<()>> {
            optional_comma(p);
            Ok(p.expect_number()?)
        }).unwrap_or(0.0);

        Ok(cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx as f64, ty as f64))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_scale_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let x = p.expect_number()?;

        let y = p.try(|p| -> Result<f32, CssParseError<()>> {
            optional_comma(p);
            Ok(p.expect_number()?)
        }).unwrap_or(x);

        Ok(cairo::Matrix::new(x as f64, 0.0, 0.0, y as f64, 0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_rotate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let angle = p.expect_number()? as f64 * PI / 180.0;
        let (s, c) = angle.sin_cos();

        let (tx, ty) = p.try(|p| -> Result<_, CssParseError<()>> {
            optional_comma(p);
            let tx = p.expect_number()? as f64;

            optional_comma(p);
            let ty = p.expect_number()? as f64;

            Ok((tx, ty))
        }).unwrap_or((0.0, 0.0));

        let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

        m = cairo::Matrix::multiply (&cairo::Matrix::new (c, s, -s, c, 0.0, 0.0), &m);
        m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
        Ok(m)
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_skewx_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let a = p.expect_number()? as f64 * PI / 180.0;
        Ok(cairo::Matrix::new (1.0,      0.0,
                               a.tan (), 1.0,
                               0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_skewy_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let a = p.expect_number()? as f64 * PI / 180.0;
        Ok(cairo::Matrix::new (1.0,  a.tan (),
                               0.0,  1.0,
                               0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

#[cfg(test)]
fn make_rotation_matrix (angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
    let angle = angle_degrees * PI / 180.0;

    let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

    let mut r = cairo::Matrix::identity ();
    r.rotate (angle);
    m = cairo::Matrix::multiply (&r, &m);

    m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
    m
}

#[no_mangle]
pub extern fn rsvg_parse_transform (out_matrix: *mut cairo::Matrix, s: *const libc::c_char) -> glib_sys::gboolean {
    assert! (!out_matrix.is_null ());
    assert! (!s.is_null ());

    let string = unsafe { String::from_glib_none (s) };
    let matrix: &mut cairo::Matrix = unsafe { &mut *out_matrix };

    match parse_transform (&string) {
        Ok (m) => {
            *matrix = m;
            true.to_glib ()
        },

        Err (_) => {
            *matrix = cairo::Matrix::identity ();
            false.to_glib ()
        }
    }
}

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

    #[test]
    fn parses_valid_transform () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }

    fn assert_parse_error(s: &str) {
        match parse_transform(s) {
            Err(AttributeError::Parse(_)) => {},
            _ => { panic!(); }
        }
    }

    #[test]
    fn syntax_error_yields_parse_error () {
        assert_parse_error("foo");
        assert_parse_error("matrix (1 2 3 4 5)");
        assert_parse_error("translate(1 2 3 4 5)");
        assert_parse_error("translate (1,)");
        assert_parse_error("scale (1,)");
        assert_parse_error("skewX (1,2)");
        assert_parse_error("skewY ()");
        assert_parse_error("skewY");
    }

    #[test]
    fn invalid_transform_yields_value_error () {
        match parse_transform ("matrix (0 0 0 0 0 0)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), translate (10, 10)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), skewX (90)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }
    }
}

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

    #[test]
    fn parses_matrix () {
        assert_eq! (parse_transform ("matrix (1 2 3 4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_transform ("matrix(1,2,3,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_transform ("matrix (1,2.25,-3.25e2,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.25, -325.0, 4.0, 5.0, 6.0));
    }

    #[test]
    fn parses_translate () {
        assert_eq! (parse_transform ("translate(-1 -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_transform ("translate(-1, -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_transform ("translate(-1)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, 0.0));
    }

    #[test]
    fn parses_scale() {
        assert_eq! (parse_transform ("scale (-1)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -1.0, 0.0, 0.0));

        assert_eq! (parse_transform ("scale(-1 -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_transform ("scale(-1, -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));
    }

    #[test]
    fn parses_rotate () {
        assert_eq! (parse_transform ("rotate (30)").unwrap (), make_rotation_matrix (30.0, 0.0, 0.0));
        assert_eq! (parse_transform ("rotate (30,-1,-2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
        assert_eq! (parse_transform ("rotate(30, -1, -2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
    }

    fn make_skew_x_matrix (angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new (1.0,      0.0,
                            a.tan (), 1.0,
                            0.0, 0.0)
    }

    fn make_skew_y_matrix (angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix (angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    fn parses_skew_x () {
        assert_eq! (parse_transform ("skewX (30)").unwrap (), make_skew_x_matrix (30.0));
    }

    #[test]
    fn parses_skew_y () {
        assert_eq! (parse_transform ("skewY (30)").unwrap (), make_skew_y_matrix (30.0));
    }

    #[test]
    fn parses_transform_list () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        assert_eq! (parse_transform ("scale(10)rotate(30, 10, 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &s));

        assert_eq! (parse_transform ("translate(20, 30), scale (10)").unwrap (),
                    cairo::Matrix::multiply (&s, &t));

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }
}
<commit_msg>rsvg_parse_transform(): Don't copy the incoming string<commit_after>use ::cairo;
use ::glib::translate::*;
use ::glib_sys;
use ::libc;

use std::f64::consts::*;

use cairo::MatrixTrait;
use cssparser::{Parser, ParserInput, Token, ParseError as CssParseError};

use error::*;
use parsers::{Parse, ParseError, optional_comma};
use util::utf8_cstr;

impl Parse for cairo::Matrix {
    type Data = ();
    type Err = AttributeError;

    fn parse (s: &str, _: ()) -> Result<cairo::Matrix, AttributeError> {
        parse_transform (s)
    }
}

// This parser is for the "transform" attribute in SVG.
// Its operataion and grammar are described here:
// https://www.w3.org/TR/SVG/coords.html#TransformAttribute

pub fn parse_transform(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let matrix = parse_transform_list(s)?;

    matrix.try_invert ().map (|_| matrix)
        .map_err (|_| AttributeError::Value ("invalid transformation matrix".to_string ()))
}

fn parse_transform_list(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let mut matrix = cairo::Matrix::identity();

    loop {
        let m = parse_transform_command(&mut parser)?;
        matrix = cairo::Matrix::multiply(&m, &matrix);

        if parser.is_exhausted() {
            break;
        }

        optional_comma(&mut parser);
    }

    Ok(matrix)
}

fn make_expected_function_error() -> AttributeError {
    AttributeError::from(ParseError::new("expected matrix|translate|scale|rotate|skewX|skewY"))
}

fn parse_transform_command(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match parser.next()?.clone() {
        Token::Function(ref name) => parse_transform_function(name, parser),

        Token::Ident(ref name) => {
            parser.expect_parenthesis_block()?;
            parse_transform_function(name, parser)
        },

        _ => Err(make_expected_function_error()),
    }
}

fn parse_transform_function(name: &str, parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match name {
        "matrix"    => parse_matrix_args(parser),
        "translate" => parse_translate_args(parser),
        "scale"     => parse_scale_args(parser),
        "rotate"    => parse_rotate_args(parser),
        "skewX"     => parse_skewx_args(parser),
        "skewY"     => parse_skewy_args(parser),
        _           => Err(make_expected_function_error()),
    }
}

fn parse_matrix_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let xx = p.expect_number()? as f64;
        optional_comma(p);

        let yx = p.expect_number()? as f64;
        optional_comma(p);

        let xy = p.expect_number()? as f64;
        optional_comma(p);

        let yy = p.expect_number()? as f64;
        optional_comma(p);

        let x0 = p.expect_number()? as f64;
        optional_comma(p);

        let y0 = p.expect_number()? as f64;

        Ok(cairo::Matrix::new(xx, yx, xy, yy, x0, y0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_translate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let tx = p.expect_number()?;

        let ty = p.try(|p| -> Result<f32, CssParseError<()>> {
            optional_comma(p);
            Ok(p.expect_number()?)
        }).unwrap_or(0.0);

        Ok(cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx as f64, ty as f64))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_scale_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let x = p.expect_number()?;

        let y = p.try(|p| -> Result<f32, CssParseError<()>> {
            optional_comma(p);
            Ok(p.expect_number()?)
        }).unwrap_or(x);

        Ok(cairo::Matrix::new(x as f64, 0.0, 0.0, y as f64, 0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_rotate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let angle = p.expect_number()? as f64 * PI / 180.0;
        let (s, c) = angle.sin_cos();

        let (tx, ty) = p.try(|p| -> Result<_, CssParseError<()>> {
            optional_comma(p);
            let tx = p.expect_number()? as f64;

            optional_comma(p);
            let ty = p.expect_number()? as f64;

            Ok((tx, ty))
        }).unwrap_or((0.0, 0.0));

        let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

        m = cairo::Matrix::multiply (&cairo::Matrix::new (c, s, -s, c, 0.0, 0.0), &m);
        m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
        Ok(m)
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_skewx_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let a = p.expect_number()? as f64 * PI / 180.0;
        Ok(cairo::Matrix::new (1.0,      0.0,
                               a.tan (), 1.0,
                               0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

fn parse_skewy_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser.parse_nested_block(|p| {
        let a = p.expect_number()? as f64 * PI / 180.0;
        Ok(cairo::Matrix::new (1.0,  a.tan (),
                               0.0,  1.0,
                               0.0, 0.0))
    }).map_err(CssParseError::<()>::basic)
        .map_err(|e| AttributeError::from(e))
}

#[cfg(test)]
fn make_rotation_matrix (angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
    let angle = angle_degrees * PI / 180.0;

    let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

    let mut r = cairo::Matrix::identity ();
    r.rotate (angle);
    m = cairo::Matrix::multiply (&r, &m);

    m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
    m
}

#[no_mangle]
pub extern fn rsvg_parse_transform (out_matrix: *mut cairo::Matrix, s: *const libc::c_char) -> glib_sys::gboolean {
    assert! (!out_matrix.is_null ());
    assert! (!s.is_null ());

    let string = unsafe { utf8_cstr(s) };
    let matrix: &mut cairo::Matrix = unsafe { &mut *out_matrix };

    match parse_transform (string) {
        Ok (m) => {
            *matrix = m;
            true.to_glib ()
        },

        Err (_) => {
            *matrix = cairo::Matrix::identity ();
            false.to_glib ()
        }
    }
}

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

    #[test]
    fn parses_valid_transform () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }

    fn assert_parse_error(s: &str) {
        match parse_transform(s) {
            Err(AttributeError::Parse(_)) => {},
            _ => { panic!(); }
        }
    }

    #[test]
    fn syntax_error_yields_parse_error () {
        assert_parse_error("foo");
        assert_parse_error("matrix (1 2 3 4 5)");
        assert_parse_error("translate(1 2 3 4 5)");
        assert_parse_error("translate (1,)");
        assert_parse_error("scale (1,)");
        assert_parse_error("skewX (1,2)");
        assert_parse_error("skewY ()");
        assert_parse_error("skewY");
    }

    #[test]
    fn invalid_transform_yields_value_error () {
        match parse_transform ("matrix (0 0 0 0 0 0)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), translate (10, 10)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), skewX (90)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }
    }
}

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

    #[test]
    fn parses_matrix () {
        assert_eq! (parse_transform ("matrix (1 2 3 4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_transform ("matrix(1,2,3,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_transform ("matrix (1,2.25,-3.25e2,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.25, -325.0, 4.0, 5.0, 6.0));
    }

    #[test]
    fn parses_translate () {
        assert_eq! (parse_transform ("translate(-1 -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_transform ("translate(-1, -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_transform ("translate(-1)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, 0.0));
    }

    #[test]
    fn parses_scale() {
        assert_eq! (parse_transform ("scale (-1)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -1.0, 0.0, 0.0));

        assert_eq! (parse_transform ("scale(-1 -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_transform ("scale(-1, -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));
    }

    #[test]
    fn parses_rotate () {
        assert_eq! (parse_transform ("rotate (30)").unwrap (), make_rotation_matrix (30.0, 0.0, 0.0));
        assert_eq! (parse_transform ("rotate (30,-1,-2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
        assert_eq! (parse_transform ("rotate(30, -1, -2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
    }

    fn make_skew_x_matrix (angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new (1.0,      0.0,
                            a.tan (), 1.0,
                            0.0, 0.0)
    }

    fn make_skew_y_matrix (angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix (angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    fn parses_skew_x () {
        assert_eq! (parse_transform ("skewX (30)").unwrap (), make_skew_x_matrix (30.0));
    }

    #[test]
    fn parses_skew_y () {
        assert_eq! (parse_transform ("skewY (30)").unwrap (), make_skew_y_matrix (30.0));
    }

    #[test]
    fn parses_transform_list () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        assert_eq! (parse_transform ("scale(10)rotate(30, 10, 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &s));

        assert_eq! (parse_transform ("translate(20, 30), scale (10)").unwrap (),
                    cairo::Matrix::multiply (&s, &t));

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar, quote, rustc_private, box_patterns)]
extern crate rustc_plugin;
#[macro_use] pub extern crate syntax;
#[macro_use] extern crate syntax_pos;
extern crate rustc_errors as errors;

extern crate peg;

use syntax::ast;
use syntax::codemap;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager, DummyResult};
use syntax::tokenstream::TokenTree;
use syntax::parse;
use syntax::parse::token;
use syntax::fold::Folder;
use syntax::util::small_vector::SmallVector;
use rustc_plugin::Registry;
use std::io::Read;
use std::fs::File;
use std::path::Path;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(
            token::intern("peg"),
            syntax::ext::base::IdentTT(Box::new(expand_peg_str), None, false));

    reg.register_syntax_extension(
            token::intern("peg_file"),
            syntax::ext::base::IdentTT(Box::new(expand_peg_file), None, false));
}

fn expand_peg_str<'s>(cx: &'s mut ExtCtxt, sp: codemap::Span, ident: ast::Ident, tts: Vec<TokenTree>) -> Box<MacResult + 's> {
    let source = match parse_arg(cx, &tts) {
        Some(source) => source,
        None => return DummyResult::any(sp),
    };

    expand_peg(cx, sp, ident, &source)
}

fn expand_peg_file<'s>(cx: &'s mut ExtCtxt, sp: codemap::Span, ident: ast::Ident, tts: Vec<TokenTree>) -> Box<MacResult + 's> {
    let fname = match parse_arg(cx, &tts) {
        Some(fname) => fname,
        None => return DummyResult::any(sp),
    };

    let path = Path::new(&cx.codemap().span_to_filename(sp)).parent().unwrap().join(&fname);

    let mut source = String::new();
    if let Err(e) = File::open(&path).map(|mut f| f.read_to_string(&mut source)) {
        cx.span_err(sp, &e.to_string());
        return DummyResult::any(sp);
    }

    cx.codemap().new_filemap(format!("{}", path.display()), None, "".to_string());

    expand_peg(cx, sp, ident, &source)
}

fn expand_peg(cx: &mut ExtCtxt, sp: codemap::Span, ident: ast::Ident, source: &str) -> Box<MacResult + 'static> {
    let code = match peg::compile(&source) {
        Ok(code) => code,
        Err(..) => {
          cx.span_err(sp, "PEG compilation failed");
          return DummyResult::any(sp)
        }
    };

    let mut p = parse::new_parser_from_source_str(&cx.parse_sess, "<peg expansion>".into(), code);
    let tts = panictry!(p.parse_all_token_trees());

    let module = quote_item! { cx,
        mod $ident {
            $tts
        }
    }.unwrap();

    MacEager::items(SmallVector::one(module))
}

fn parse_arg(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<String> {
    use syntax::print::pprust;

    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.to_vec());
    // The `expand_expr` method is called so that any macro calls in the
    // parsed expression are expanded.
    let arg = cx.expander().fold_expr(panictry!(parser.parse_expr()));
    match arg.node {
        ast::ExprKind::Lit(ref spanned) => {
            match spanned.node {
                ast::LitKind::Str(ref n, _) => {
                    if !parser.eat(&token::Eof) {
                        cx.span_err(parser.span,
                                    "expected only one string literal");
                        return None
                    }
                    return Some(n.to_string())
                }
                _ => {}
            }
        }
        _ => {}
    }

    let err = format!("expected string literal but got `{}`",
                      pprust::expr_to_string(&*arg));
    cx.span_err(parser.span, &err);
    None
}
<commit_msg>rust: token::intern -> Symbol::intern<commit_after>#![feature(plugin_registrar, quote, rustc_private, box_patterns)]
extern crate rustc_plugin;
#[macro_use] pub extern crate syntax;
#[macro_use] extern crate syntax_pos;
extern crate rustc_errors as errors;

extern crate peg;

use syntax::ast;
use syntax::codemap;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager, DummyResult};
use syntax::tokenstream::TokenTree;
use syntax::parse;
use syntax::parse::token;
use syntax::symbol::Symbol;
use syntax::fold::Folder;
use syntax::util::small_vector::SmallVector;
use rustc_plugin::Registry;
use std::io::Read;
use std::fs::File;
use std::path::Path;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(
            Symbol::intern("peg"),
            syntax::ext::base::IdentTT(Box::new(expand_peg_str), None, false));

    reg.register_syntax_extension(
            Symbol::intern("peg_file"),
            syntax::ext::base::IdentTT(Box::new(expand_peg_file), None, false));
}

fn expand_peg_str<'s>(cx: &'s mut ExtCtxt, sp: codemap::Span, ident: ast::Ident, tts: Vec<TokenTree>) -> Box<MacResult + 's> {
    let source = match parse_arg(cx, &tts) {
        Some(source) => source,
        None => return DummyResult::any(sp),
    };

    expand_peg(cx, sp, ident, &source)
}

fn expand_peg_file<'s>(cx: &'s mut ExtCtxt, sp: codemap::Span, ident: ast::Ident, tts: Vec<TokenTree>) -> Box<MacResult + 's> {
    let fname = match parse_arg(cx, &tts) {
        Some(fname) => fname,
        None => return DummyResult::any(sp),
    };

    let path = Path::new(&cx.codemap().span_to_filename(sp)).parent().unwrap().join(&fname);

    let mut source = String::new();
    if let Err(e) = File::open(&path).map(|mut f| f.read_to_string(&mut source)) {
        cx.span_err(sp, &e.to_string());
        return DummyResult::any(sp);
    }

    cx.codemap().new_filemap(format!("{}", path.display()), None, "".to_string());

    expand_peg(cx, sp, ident, &source)
}

fn expand_peg(cx: &mut ExtCtxt, sp: codemap::Span, ident: ast::Ident, source: &str) -> Box<MacResult + 'static> {
    let code = match peg::compile(&source) {
        Ok(code) => code,
        Err(..) => {
          cx.span_err(sp, "PEG compilation failed");
          return DummyResult::any(sp)
        }
    };

    let mut p = parse::new_parser_from_source_str(&cx.parse_sess, "<peg expansion>".into(), code);
    let tts = panictry!(p.parse_all_token_trees());

    let module = quote_item! { cx,
        mod $ident {
            $tts
        }
    }.unwrap();

    MacEager::items(SmallVector::one(module))
}

fn parse_arg(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<String> {
    use syntax::print::pprust;

    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), tts.to_vec());
    // The `expand_expr` method is called so that any macro calls in the
    // parsed expression are expanded.
    let arg = cx.expander().fold_expr(panictry!(parser.parse_expr()));
    match arg.node {
        ast::ExprKind::Lit(ref spanned) => {
            match spanned.node {
                ast::LitKind::Str(ref n, _) => {
                    if !parser.eat(&token::Eof) {
                        cx.span_err(parser.span,
                                    "expected only one string literal");
                        return None
                    }
                    return Some(n.to_string())
                }
                _ => {}
            }
        }
        _ => {}
    }

    let err = format!("expected string literal but got `{}`",
                      pprust::expr_to_string(&*arg));
    cx.span_err(parser.span, &err);
    None
}
<|endoftext|>


<commit_before>
#![feature(box_syntax,box_patterns)]
#[macro_use]
extern crate "seax_svm" as svm;

use svm::slist::Stack;
use svm::slist::List::{Cons,Nil};
use svm::cell::Atom::*;
use svm::cell::SVMCell::*;
use svm::Inst::*;
use std::io;

/// SVM integration tests.
///
/// These are based on the sample programs in Zach Allaun's Clojure SECD
/// [implementation](https://github.com/zachallaun/secd). Each example also
/// provides the source code for the equivalent Lisp program.

/// Test for simple list construction through CONS.
///
/// ```lisp
/// (cons 10 (cons 20 nil))
/// ```
#[test]
fn test_list_creation() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(NIL),
            InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
            InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS)
        )).peek(),
        Some(&ListCell( box list!(AtomCell(SInt(20)), AtomCell(SInt(10)))))
    );
}

/// Test for simple list construction and destructuring
///
/// ```lisp
/// (car (cons 10 (cons 20 nil)))
/// ```
#[test]
fn test_list_car() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(NIL),
            InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
            InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS),
            InstCell(CAR)
        )).peek(),
        Some(&AtomCell(SInt(20)))
    );
}
/// Test for simple list construction and destructuring
///
/// ```lisp
/// (cdr (cons 10 (cons 20 nil)))
/// ```
#[test]
fn test_list_cdr() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(NIL),
            InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
            InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS),
            InstCell(CDR)
        )).peek(),
        Some(&ListCell(box list!(AtomCell(SInt(10)))))
    );
}

/// Test for simple mathematics application
///
/// ```lisp
/// (+ 10 10)
/// ```
#[test]
fn test_simple_add() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(LDC), AtomCell(SInt(10)),
            InstCell(LDC), AtomCell(SInt(10)),
            InstCell(ADD)
        )).peek(),
        Some(&AtomCell(SInt(20)))
    );
}

/// Test for nested arithmetic
///
/// ```lisp
/// (- 20 (+ 5 5))
/// ```
#[test]
fn test_nested_arith() {
     assert_eq!(
        svm::eval_program(list!(
            InstCell(LDC), AtomCell(SInt(5)),
            InstCell(LDC), AtomCell(SInt(5)),
            InstCell(ADD),
            InstCell(LDC), AtomCell(SInt(20)),
            InstCell(SUB)
        )).peek(),
        Some(&AtomCell(SInt(10)))
    );
}

/// Tests for basic branching
///
/// ```lisp
/// ((if (= 0 (- 1 1)) true false)
/// ```
///
/// ```lisp
/// (+ 10 (if (nil? nil) 10 20))
/// ```
#[test]
fn test_basic_branching() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(LDC), AtomCell(SInt(1)), InstCell(LDC), AtomCell(SInt(1)),
            InstCell(SUB),
            InstCell(LDC), AtomCell(SInt(0)),
            InstCell(EQ),
            InstCell(SEL),
                ListCell(box list!(InstCell(LDC), AtomCell(SInt(1)), InstCell(JOIN))),
                ListCell(box list!(InstCell(NIL), InstCell(JOIN))
            )
        )).peek(),
        Some(&AtomCell(SInt(1)))
    );
    assert_eq!(
        svm::eval_program(list!(
            InstCell(NIL), InstCell(NULL),
            InstCell(SEL),
                ListCell(box list!(InstCell(LDC), AtomCell(SInt(10)), InstCell(JOIN))),
                ListCell(box list!(InstCell(LDC), AtomCell(SInt(20)), InstCell(JOIN))),
            InstCell(LDC), AtomCell(SInt(10)),
            InstCell(ADD)
        )).peek(),
        Some(&AtomCell(SInt(20)))
    );
}

<commit_msg>Remove unused import<commit_after>
#![feature(box_syntax,box_patterns)]
#[macro_use]
extern crate "seax_svm" as svm;

use svm::slist::Stack;
use svm::slist::List::{Cons,Nil};
use svm::cell::Atom::*;
use svm::cell::SVMCell::*;
use svm::Inst::*;

/// SVM integration tests.
///
/// These are based on the sample programs in Zach Allaun's Clojure SECD
/// [implementation](https://github.com/zachallaun/secd). Each example also
/// provides the source code for the equivalent Lisp program.

/// Test for simple list construction through CONS.
///
/// ```lisp
/// (cons 10 (cons 20 nil))
/// ```
#[test]
fn test_list_creation() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(NIL),
            InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
            InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS)
        )).peek(),
        Some(&ListCell( box list!(AtomCell(SInt(20)), AtomCell(SInt(10)))))
    );
}

/// Test for simple list construction and destructuring
///
/// ```lisp
/// (car (cons 10 (cons 20 nil)))
/// ```
#[test]
fn test_list_car() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(NIL),
            InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
            InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS),
            InstCell(CAR)
        )).peek(),
        Some(&AtomCell(SInt(20)))
    );
}
/// Test for simple list construction and destructuring
///
/// ```lisp
/// (cdr (cons 10 (cons 20 nil)))
/// ```
#[test]
fn test_list_cdr() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(NIL),
            InstCell(LDC), AtomCell(SInt(10)), InstCell(CONS),
            InstCell(LDC), AtomCell(SInt(20)), InstCell(CONS),
            InstCell(CDR)
        )).peek(),
        Some(&ListCell(box list!(AtomCell(SInt(10)))))
    );
}

/// Test for simple mathematics application
///
/// ```lisp
/// (+ 10 10)
/// ```
#[test]
fn test_simple_add() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(LDC), AtomCell(SInt(10)),
            InstCell(LDC), AtomCell(SInt(10)),
            InstCell(ADD)
        )).peek(),
        Some(&AtomCell(SInt(20)))
    );
}

/// Test for nested arithmetic
///
/// ```lisp
/// (- 20 (+ 5 5))
/// ```
#[test]
fn test_nested_arith() {
     assert_eq!(
        svm::eval_program(list!(
            InstCell(LDC), AtomCell(SInt(5)),
            InstCell(LDC), AtomCell(SInt(5)),
            InstCell(ADD),
            InstCell(LDC), AtomCell(SInt(20)),
            InstCell(SUB)
        )).peek(),
        Some(&AtomCell(SInt(10)))
    );
}

/// Tests for basic branching
///
/// ```lisp
/// ((if (= 0 (- 1 1)) true false)
/// ```
///
/// ```lisp
/// (+ 10 (if (nil? nil) 10 20))
/// ```
#[test]
fn test_basic_branching() {
    assert_eq!(
        svm::eval_program(list!(
            InstCell(LDC), AtomCell(SInt(1)), InstCell(LDC), AtomCell(SInt(1)),
            InstCell(SUB),
            InstCell(LDC), AtomCell(SInt(0)),
            InstCell(EQ),
            InstCell(SEL),
                ListCell(box list!(InstCell(LDC), AtomCell(SInt(1)), InstCell(JOIN))),
                ListCell(box list!(InstCell(NIL), InstCell(JOIN))
            )
        )).peek(),
        Some(&AtomCell(SInt(1)))
    );
    assert_eq!(
        svm::eval_program(list!(
            InstCell(NIL), InstCell(NULL),
            InstCell(SEL),
                ListCell(box list!(InstCell(LDC), AtomCell(SInt(10)), InstCell(JOIN))),
                ListCell(box list!(InstCell(LDC), AtomCell(SInt(20)), InstCell(JOIN))),
            InstCell(LDC), AtomCell(SInt(10)),
            InstCell(ADD)
        )).peek(),
        Some(&AtomCell(SInt(20)))
    );
}

<|endoftext|>