<commit_before>extern crate libc;

use std;
use std::mem;
use libc::c_char;
use std::ffi::CStr;

use std::io::Write;
use std::io::stdout;

use nom::*;

use rparser::*;

use tls_parser::tls::{TlsMessage,TlsMessageHandshake,tls_parser_many};
use tls_parser::tls_ciphers::TlsCipherSuite;
use tls_parser::tls_extensions::parse_tls_extensions;

// --------------------------------------------
// example implementation: TLS parser

#[repr(u32)]
pub enum TlsParserEvents {
    HeartbeatOverflow = 1,
}

pub struct TlsParserState<'a> {
    pub o: Option<&'a[u8]>,

    events: Vec<u32>,

    cipher: u16,
}

impl<'a> TlsParserState<'a> {
    pub fn new(i: &'a[u8]) -> TlsParserState<'a> {
        TlsParserState{o:Some(i),events:Vec::new(),cipher:0}
    }

    fn send(&self, value: i32) -> bool {
        debug!("=============================================================");
        debug!("inner send: {}", value);
        debug!("o: {:?}", self.o);
        debug!("cipher: {:?}", self.cipher);
        debug!("=============================================================");
        let _ = stdout().flush();
        true
    }
}

r_declare_state_new!(r_tls_state_new,TlsParserState,b"blah");
r_declare_state_free!(r_tls_state_free,TlsParserState,{ debug!("Drop TlsParserState"); });

struct TlsParser;

impl<'a> RParser<TlsParserState<'a>> for TlsParser {
    fn new_state() -> TlsParserState<'a> {
        TlsParserState::new(b"blah")
    }

    fn probe(i: &[u8]) -> bool {
        if i.len() <= 2 { return false; }
        // first byte is record type (between 0x14 and 0x17, 0x16 is handhake)
        // second is TLS version major (0x3)
        // third is TLS version minor (0x0 for SSLv3, 0x1 for TLSv1.0, etc.)
        match (i[0],i[1],i[2]) {
            (0x14...0x17,0x03,0...3) => true,
            _ => false,
        }
    }

    fn parse(this: &mut TlsParserState, i: &[u8], direction: u8) -> u32 {
        debug!("[TLS->parse]");
        debug!("  direction: {}", direction);
        debug!("  len: {}", i.len());
        debug!("  data: {:?}", i);

        let d = tls_parser_many(i);
        debug!("d: {:?}", d);

        let mut status = R_STATUS_OK;

        match d {
            IResult::Done(rem,p) => {
                debug!("TLS parser successful {} element(s)", p.len());
                for ref record in &p {
                    debug!("{:?}", record);
                    for msg in &record.msg {
                        match *msg {
                            TlsMessage::Handshake(ref m) => {
                                match *m {
                                    TlsMessageHandshake::ClientHello(ref content) => {
                                        let blah = parse_tls_extensions(content.ext.unwrap_or(b""));
                                        debug!("ext {:?}", blah);
                                    },
                                    TlsMessageHandshake::ServerHello(ref content) => {
                                        this.cipher = content.cipher;
                                        match TlsCipherSuite::from_id(content.cipher) {
                                            Some(c) => debug!("Selected cipher: {:?}", c),
                                            _ => warn!("Unknown cipher 0x{:x}", content.cipher),
                                        };
                                        let blah = parse_tls_extensions(content.ext.unwrap_or(b""));
                                        debug!("extensions: {:?}", blah);
                                    },
                                    _ => (),
                                }
                            },
                            TlsMessage::Heartbeat(ref d) => {
                                if d.payload_len as usize > d.payload.len() {
                                    warn!("Heartbeat message with incorrect length {}. Heartbleed attempt ?",d.payload.len());
                                    this.events.push(TlsParserEvents::HeartbeatOverflow as u32);
                                    println!("{:?}", this.events);
                                    status |= R_STATUS_EVENTS;
                                }
                            },
                            _ => (),
                        }
                    }
                }
                if rem.len() > 0 { warn!("** unparsed ** {:?}",rem); };
            },
            IResult::Error(e) => error!("TLS parser reported an error: {:?}", e),
            IResult::Incomplete(e) => error!("TLS parser reported incomplete input: {:?}", e),
        };

        println!("status: {:x}",status);
        status
    }
}

r_implement_probe!(r_tls_probe,TlsParser);
r_implement_parse!(r_tls_parse,TlsParser);

// --------------------------------------------

#[no_mangle]
pub extern fn r_tls_get_next_event(ptr: *mut libc::c_char) -> u32
// pub extern fn r_tls_get_next_event<'a>(this: &mut TlsParserState<'a>) -> u32
{
    assert!(!ptr.is_null());
    let this: &mut TlsParserState = unsafe { mem::transmute(ptr) };
    debug!("r_tls_get_next_event");
    println!("{:?}", this.events);
    match this.events.pop() {
        None     => 0xffffffff,
        Some(ev) => ev,
    }
}

#[no_mangle]
pub extern fn rusticata_use_tls_parser_state(ptr: *mut libc::c_char, value: i32) -> bool
{
    let this: &Box<TlsParserState> = unsafe { mem::transmute(ptr) };
    debug!("rusticata_use_tls_parser_state({:?})", value);
    this.send(value)
}

#[no_mangle]
pub extern fn rusticata_tls_get_cipher(ptr: *mut libc::c_char) -> u32
// or
// pub extern fn rusticata_tls_get_cipher<'a>(this: &TlsParserState<'a>) -> u32
// but this gives a warning:
// warning: generic functions must be mangled, #[warn(no_mangle_generic_items)] on by default
{
    let this: &Box<TlsParserState> = unsafe { mem::transmute(ptr) };
    this.cipher as u32
}

#[no_mangle]
pub extern fn rusticata_tls_cipher_of_string(value: *const c_char) -> u32
{
    let c_str = unsafe { CStr::from_ptr(value) };
    let s = c_str.to_str().unwrap();
    match TlsCipherSuite::from_name(s) {
        Some(c) => c.id as u32,
        None    => 0,
    }
}

<commit_msg>Very TLS state transitions when parsing<commit_after>extern crate libc;

use std;
use std::mem;
use libc::c_char;
use std::ffi::CStr;

use nom::*;

use rparser::*;

use tls_parser::tls::{TlsMessage,TlsMessageHandshake,tls_parser_many};
use tls_parser::tls_ciphers::TlsCipherSuite;
use tls_parser::tls_extensions::parse_tls_extensions;
use tls_parser::tls_states::{TlsState,tls_state_transition};

// --------------------------------------------
// example implementation: TLS parser

#[repr(u32)]
pub enum TlsParserEvents {
    HeartbeatOverflow = 1,
    InvalidState = 2,
}

pub struct TlsParserState<'a> {
    pub o: Option<&'a[u8]>,

    events: Vec<u32>,

    cipher: u16,
    state: TlsState,
}

impl<'a> TlsParserState<'a> {
    pub fn new(i: &'a[u8]) -> TlsParserState<'a> {
        TlsParserState{
            o:Some(i),
            events:Vec::new(),
            cipher:0,
            state:TlsState::None
        }
    }

}

r_declare_state_new!(r_tls_state_new,TlsParserState,b"blah");
r_declare_state_free!(r_tls_state_free,TlsParserState,{ debug!("Drop TlsParserState"); });

struct TlsParser;

impl<'a> RParser<TlsParserState<'a>> for TlsParser {
    fn new_state() -> TlsParserState<'a> {
        TlsParserState::new(b"blah")
    }

    fn probe(i: &[u8]) -> bool {
        if i.len() <= 2 { return false; }
        // first byte is record type (between 0x14 and 0x17, 0x16 is handhake)
        // second is TLS version major (0x3)
        // third is TLS version minor (0x0 for SSLv3, 0x1 for TLSv1.0, etc.)
        match (i[0],i[1],i[2]) {
            (0x14...0x17,0x03,0...3) => true,
            _ => false,
        }
    }

    fn parse(this: &mut TlsParserState, i: &[u8], direction: u8) -> u32 {
        debug!("[TLS->parse]");
        debug!("  direction: {}", direction);
        debug!("  len: {}", i.len());
        debug!("  data: {:?}", i);

        let d = tls_parser_many(i);
        debug!("d: {:?}", d);

        let mut status = R_STATUS_OK;

        match d {
            IResult::Done(rem,p) => {
                debug!("TLS parser successful {} element(s)", p.len());
                for ref record in &p {
                    debug!("{:?}", record);
                    for msg in &record.msg {
                        if this.state == TlsState::ClientChangeCipherSpec {
                            // Ignore records from now on, they are encrypted
                            break
                        };
                        // update state machine
                        debug!("Old state: {:?}",this.state);
                        match tls_state_transition(this.state, msg) {
                            Ok(s)  => this.state = s,
                            Err(_) => {
                                this.state = TlsState::Invalid;
                                this.events.push(TlsParserEvents::InvalidState as u32);
                                status |= R_STATUS_EVENTS;
                            },
                        };
                        debug!("New state: {:?}",this.state);

                        // extract variables
                        match *msg {
                            TlsMessage::Handshake(ref m) => {
                                match *m {
                                    TlsMessageHandshake::ClientHello(ref content) => {
                                        let blah = parse_tls_extensions(content.ext.unwrap_or(b""));
                                        debug!("ext {:?}", blah);
                                    },
                                    TlsMessageHandshake::ServerHello(ref content) => {
                                        this.cipher = content.cipher;
                                        match TlsCipherSuite::from_id(content.cipher) {
                                            Some(c) => debug!("Selected cipher: {:?}", c),
                                            _ => warn!("Unknown cipher 0x{:x}", content.cipher),
                                        };
                                        let blah = parse_tls_extensions(content.ext.unwrap_or(b""));
                                        debug!("extensions: {:?}", blah);
                                    },
                                    _ => (),
                                }
                            },
                            TlsMessage::Heartbeat(ref d) => {
                                if d.payload_len as usize > d.payload.len() {
                                    warn!("Heartbeat message with incorrect length {}. Heartbleed attempt ?",d.payload.len());
                                    this.events.push(TlsParserEvents::HeartbeatOverflow as u32);
                                    println!("{:?}", this.events);
                                    status |= R_STATUS_EVENTS;
                                }
                            },
                            _ => (),
                        }
                    }
                }
                if rem.len() > 0 { warn!("** unparsed ** {:?}",rem); };
            },
            IResult::Error(e) => error!("TLS parser reported an error: {:?}", e),
            IResult::Incomplete(e) => error!("TLS parser reported incomplete input: {:?}", e),
        };

        println!("status: {:x}",status);
        status
    }
}

r_implement_probe!(r_tls_probe,TlsParser);
r_implement_parse!(r_tls_parse,TlsParser);

// --------------------------------------------

#[no_mangle]
pub extern fn r_tls_get_next_event(ptr: *mut libc::c_char) -> u32
// pub extern fn r_tls_get_next_event<'a>(this: &mut TlsParserState<'a>) -> u32
{
    assert!(!ptr.is_null());
    let this: &mut TlsParserState = unsafe { mem::transmute(ptr) };
    debug!("r_tls_get_next_event");
    println!("{:?}", this.events);
    match this.events.pop() {
        None     => 0xffffffff,
        Some(ev) => ev,
    }
}

#[no_mangle]
pub extern fn rusticata_tls_get_cipher(ptr: *mut libc::c_char) -> u32
// or
// pub extern fn rusticata_tls_get_cipher<'a>(this: &TlsParserState<'a>) -> u32
// but this gives a warning:
// warning: generic functions must be mangled, #[warn(no_mangle_generic_items)] on by default
{
    let this: &Box<TlsParserState> = unsafe { mem::transmute(ptr) };
    this.cipher as u32
}

#[no_mangle]
pub extern fn rusticata_tls_cipher_of_string(value: *const c_char) -> u32
{
    let c_str = unsafe { CStr::from_ptr(value) };
    let s = c_str.to_str().unwrap();
    match TlsCipherSuite::from_name(s) {
        Some(c) => c.id as u32,
        None    => 0,
    }
}

<|endoftext|>


<commit_before>use std::iter::*;
use std::sync::atomic::*;
use atomic_option::*;
use types::*;
use config::*;
use player::*;
use field::*;

struct UctNode {
  wins: AtomicUsize,
  draws: AtomicUsize,
  visits: AtomicUsize,
  pos: Pos,
  child: AtomicOption<UctNode>,
  sibling: Option<Box<UctNode>>
}

unsafe impl Send for UctNode { }

impl UctNode {
  pub fn new() -> UctNode {
    UctNode {
      wins: AtomicUsize::new(0),
      draws: AtomicUsize::new(0),
      visits: AtomicUsize::new(0),
      pos: 0,
      child: AtomicOption::empty(),
      sibling: None
    }
  }
}

pub struct UctRoot {
  node: Option<Box<UctNode>>,
  moves: Vec<Pos>,
  moves_field: Vec<Pos>,
  player: Player,
  moves_count: usize,
  hash: u64
}

impl UctRoot {
  fn clear(&mut self) {
    self.node = None;
    self.moves.clear();
    for i in self.moves_field.iter_mut() {
      *i = 0;
    }
    self.player = Player::Red;
    self.moves_count = 0;
    self.hash = 0;
  }

  fn init(&mut self, field: &Field, player: Player) {
    self.node = Some(Box::new(UctNode::new()));
    self.player = Player::Red;
    let width = field.width();
    for &start_pos in field.points_seq() {
      wave(width, start_pos, |pos| {
        if self.moves_field[pos] != start_pos && field.is_putting_allowed(pos) && manhattan(width, start_pos, pos) <= UCT_RADIUS {
          if self.moves_field[pos] == 0 {
            self.moves.push(pos);
          }
          self.moves_field[pos] = start_pos;
          true
        } else {
          false
        }
      });
    }
    self.player = player;
  }

  fn update(&mut self, field: &Field, player: Player) {
    if !self.node.is_none() && field.hash_at(self.moves_count) != Some(self.hash) {
      self.clear();
    }
    if self.node.is_none() {
      self.init(field, player);
    } else {
      let points_seq = field.points_seq();
      let moves_count = field.moves_count();
      loop {
        if self.moves_count == moves_count {
          break;
        }
        let next_pos = points_seq[self.moves_count];
        if !field.is_players_point(next_pos, self.player) {
          self.clear();
          self.init(field, player);
          break;
        }
        let mut next = self.node.as_ref().unwrap().child.take(Ordering::Relaxed);
        while next.is_some() && next.as_ref().unwrap().pos != next_pos {
          next = next.unwrap().sibling;
        }
        match next.as_mut() {
          Some(node) => {
            node.sibling = None;
          },
          None => { }
        }
        self.node = next;
        let moves_field = &mut self.moves_field;
        self.moves.retain(|&pos| {
          if field.is_putting_allowed(pos) {
            true
          } else {
            moves_field[pos] = 0;
            false
          }
        });

      }
    }
  }

  pub fn new(length: Pos) -> UctRoot {
    UctRoot {
      node: None,
      moves: Vec::new(),
      moves_field: repeat(0).take(length).collect(),
      player: Player::Red,
      moves_count: 0,
      hash: 0
    }
  }

  pub fn best_move(&mut self, field: &Field, player: Player) -> Pos {
    self.update(field, player);
    0
  }

  //pub fn estimates
}
<commit_msg>Updation of uct implemented (without expanding).<commit_after>use std::iter::*;
use std::sync::atomic::*;
use atomic_option::*;
use types::*;
use config::*;
use player::*;
use field::*;

struct UctNode {
  wins: AtomicUsize,
  draws: AtomicUsize,
  visits: AtomicUsize,
  pos: Pos,
  child: AtomicOption<UctNode>,
  sibling: Option<Box<UctNode>>
}

unsafe impl Send for UctNode { }

impl UctNode {
  pub fn new() -> UctNode {
    UctNode {
      wins: AtomicUsize::new(0),
      draws: AtomicUsize::new(0),
      visits: AtomicUsize::new(0),
      pos: 0,
      child: AtomicOption::empty(),
      sibling: None
    }
  }
}

pub struct UctRoot {
  node: Option<Box<UctNode>>,
  moves: Vec<Pos>,
  moves_field: Vec<Pos>,
  player: Player,
  moves_count: usize,
  hash: u64
}

impl UctRoot {
  fn clear(&mut self) {
    self.node = None;
    self.moves.clear();
    for i in self.moves_field.iter_mut() {
      *i = 0;
    }
    self.player = Player::Red;
    self.moves_count = 0;
    self.hash = 0;
  }

  fn init(&mut self, field: &Field, player: Player) {
    self.node = Some(Box::new(UctNode::new()));
    self.player = Player::Red;
    let width = field.width();
    for &start_pos in field.points_seq() {
      wave(width, start_pos, |pos| {
        if self.moves_field[pos] != start_pos && field.is_putting_allowed(pos) && manhattan(width, start_pos, pos) <= UCT_RADIUS {
          if self.moves_field[pos] == 0 {
            self.moves.push(pos);
          }
          self.moves_field[pos] = start_pos;
          true
        } else {
          false
        }
      });
    }
    self.player = player;
  }

  fn expand_node(node: &UctNode, moves: &Vec<Pos>) {
  }

  fn update(&mut self, field: &Field, player: Player) {
    if !self.node.is_none() && field.hash_at(self.moves_count) != Some(self.hash) {
      self.clear();
    }
    if self.node.is_none() {
      self.init(field, player);
    } else {
      let points_seq = field.points_seq();
      let moves_count = field.moves_count();
      loop {
        if self.moves_count == moves_count {
          break;
        }
        let next_pos = points_seq[self.moves_count];
        if !field.is_players_point(next_pos, self.player) {
          self.clear();
          self.init(field, player);
          break;
        }
        let mut next = self.node.as_ref().unwrap().child.take(Ordering::Relaxed);
        while next.is_some() && next.as_ref().unwrap().pos != next_pos {
          next = next.unwrap().sibling;
        }
        match next.as_mut() {
          Some(node) => {
            node.sibling = None;
          },
          None => {
            self.clear();
            self.init(field, player);
            break;
          }
        }
        self.node = next;
        let moves_field = &mut self.moves_field;
        self.moves.retain(|&pos| {
          if field.is_putting_allowed(pos) {
            true
          } else {
            moves_field[pos] = 0;
            false
          }
        });
        let mut added_moves = Vec::new();
        let width = field.width();
        wave(width, next_pos, |pos| {
          if moves_field[pos] != next_pos && field.is_putting_allowed(pos) && manhattan(width, next_pos, pos) <= UCT_RADIUS {
            if moves_field[pos] == 0 {
              added_moves.push(pos);
            }
            moves_field[pos] = next_pos;
            true
          } else {
            false
          }
        });
        UctRoot::expand_node(self.node.as_ref().unwrap(), &added_moves);
        self.moves_count += 1;
        self.player = self.player.next();
      }
    }
  }

  pub fn new(length: Pos) -> UctRoot {
    UctRoot {
      node: None,
      moves: Vec::new(),
      moves_field: repeat(0).take(length).collect(),
      player: Player::Red,
      moves_count: 0,
      hash: 0
    }
  }

  pub fn best_move(&mut self, field: &Field, player: Player) -> Pos {
    self.update(field, player);
    0
  }

  //pub fn estimates
}
<|endoftext|>


<commit_before>use std::ops::Range;

use crate::scanner::Scanner;

/// Scan for URLs starting from the trigger character ":", requires "://".
///
/// Based on RFC 3986.
pub struct UrlScanner {}

impl Scanner for UrlScanner {
    fn scan(&self, s: &str, colon: usize) -> Option<Range<usize>> {
        let after_slash_slash = colon + 3;
        // Need at least one character for scheme, and one after '//'
        if colon > 0 && after_slash_slash < s.len() && s[colon..].starts_with("://") {
            if let Some(start) = self.find_start(&s[0..colon]) {
                if let Some(end) = self.find_end(&s[after_slash_slash..]) {
                    let range = Range {
                        start,
                        end: after_slash_slash + end,
                    };
                    return Some(range);
                }
            }
        }
        None
    }
}

impl UrlScanner {
    // See "scheme" in RFC 3986
    fn find_start(&self, s: &str) -> Option<usize> {
        let mut first = None;
        let mut digit = None;
        for (i, c) in s.char_indices().rev() {
            match c {
                'a'..='z' | 'A'..='Z' => first = Some(i),
                '0'..='9' => digit = Some(i),
                // scheme special
                '+' | '-' | '.' => {}
                _ => {
                    break;
                }
            }
        }

        // We don't want to extract "abc://foo" out of "1abc://foo".
        // ".abc://foo" and others are ok though, as they feel more like separators.
        if let Some(first) = first {
            if let Some(digit) = digit {
                // Comparing the byte indices with `- 1` is ok as scheme must be ASCII
                if first > 0 && first - 1 == digit {
                    return None;
                }
            }
        }
        first
    }

    fn find_end(&self, s: &str) -> Option<usize> {
        let mut round = 0;
        let mut square = 0;
        let mut curly = 0;
        let mut single_quote = false;

        let mut previous_can_be_last = true;
        let mut end = None;

        for (i, c) in s.char_indices() {
            let can_be_last = match c {
                '\u{00}'..='\u{1F}' | ' ' | '|' |  '\"' | '<' | '>' | '`' | '\u{7F}'..='\u{9F}' => {
                    // These can never be part of an URL, so stop now. See RFC 3986 and RFC 3987.
                    // Some characters are not in the above list, even they are not in "unreserved"
                    // or "reserved":
                    //   '\\', '^', '{', '}'
                    // The reason for this is that other link detectors also allow them. Also see
                    // below, we require the braces to be balanced.
                    break;
                }
                '?' | '!' | '.' | ',' | ':' | ';' | '*' => {
                    // These may be part of an URL but not at the end. It's not that the spec
                    // doesn't allow them, but they are frequently used in plain text as delimiters
                    // where they're not meant to be part of the URL.
                    false
                }
                '/' => {
                    // This may be part of an URL and at the end, but not if the previous character
                    // can't be the end of an URL
                    previous_can_be_last
                }
                '(' => {
                    round += 1;
                    false
                }
                ')' => {
                    round -= 1;
                    if round < 0 {
                        // More closing than opening brackets, stop now
                        break;
                    }
                    true
                }
                '[' => {
                    // Allowed in IPv6 address host
                    square += 1;
                    false
                }
                ']' => {
                    // Allowed in IPv6 address host
                    square -= 1;
                    if square < 0 {
                        // More closing than opening brackets, stop now
                        break;
                    }
                    true
                }
                '{' => {
                    curly += 1;
                    false
                }
                '}' => {
                    curly -= 1;
                    if curly < 0 {
                        // More closing than opening brackets, stop now
                        break;
                    }
                    true
                }
                '\'' => {
                    single_quote = !single_quote;
                    // A single quote can only be the end of an URL if there's an even number
                    !single_quote
                }
                _ => true,
            };
            if can_be_last {
                end = Some(i + c.len_utf8());
            }
            previous_can_be_last = can_be_last;
        }

        end
    }
}
<commit_msg>Formatting<commit_after>use std::ops::Range;

use crate::scanner::Scanner;

/// Scan for URLs starting from the trigger character ":", requires "://".
///
/// Based on RFC 3986.
pub struct UrlScanner {}

impl Scanner for UrlScanner {
    fn scan(&self, s: &str, colon: usize) -> Option<Range<usize>> {
        let after_slash_slash = colon + 3;
        // Need at least one character for scheme, and one after '//'
        if colon > 0 && after_slash_slash < s.len() && s[colon..].starts_with("://") {
            if let Some(start) = self.find_start(&s[0..colon]) {
                if let Some(end) = self.find_end(&s[after_slash_slash..]) {
                    let range = Range {
                        start,
                        end: after_slash_slash + end,
                    };
                    return Some(range);
                }
            }
        }
        None
    }
}

impl UrlScanner {
    // See "scheme" in RFC 3986
    fn find_start(&self, s: &str) -> Option<usize> {
        let mut first = None;
        let mut digit = None;
        for (i, c) in s.char_indices().rev() {
            match c {
                'a'..='z' | 'A'..='Z' => first = Some(i),
                '0'..='9' => digit = Some(i),
                // scheme special
                '+' | '-' | '.' => {}
                _ => {
                    break;
                }
            }
        }

        // We don't want to extract "abc://foo" out of "1abc://foo".
        // ".abc://foo" and others are ok though, as they feel more like separators.
        if let Some(first) = first {
            if let Some(digit) = digit {
                // Comparing the byte indices with `- 1` is ok as scheme must be ASCII
                if first > 0 && first - 1 == digit {
                    return None;
                }
            }
        }
        first
    }

    fn find_end(&self, s: &str) -> Option<usize> {
        let mut round = 0;
        let mut square = 0;
        let mut curly = 0;
        let mut single_quote = false;

        let mut previous_can_be_last = true;
        let mut end = None;

        for (i, c) in s.char_indices() {
            let can_be_last = match c {
                '\u{00}'..='\u{1F}' | ' ' | '|' | '\"' | '<' | '>' | '`' | '\u{7F}'..='\u{9F}' => {
                    // These can never be part of an URL, so stop now. See RFC 3986 and RFC 3987.
                    // Some characters are not in the above list, even they are not in "unreserved"
                    // or "reserved":
                    //   '\\', '^', '{', '}'
                    // The reason for this is that other link detectors also allow them. Also see
                    // below, we require the braces to be balanced.
                    break;
                }
                '?' | '!' | '.' | ',' | ':' | ';' | '*' => {
                    // These may be part of an URL but not at the end. It's not that the spec
                    // doesn't allow them, but they are frequently used in plain text as delimiters
                    // where they're not meant to be part of the URL.
                    false
                }
                '/' => {
                    // This may be part of an URL and at the end, but not if the previous character
                    // can't be the end of an URL
                    previous_can_be_last
                }
                '(' => {
                    round += 1;
                    false
                }
                ')' => {
                    round -= 1;
                    if round < 0 {
                        // More closing than opening brackets, stop now
                        break;
                    }
                    true
                }
                '[' => {
                    // Allowed in IPv6 address host
                    square += 1;
                    false
                }
                ']' => {
                    // Allowed in IPv6 address host
                    square -= 1;
                    if square < 0 {
                        // More closing than opening brackets, stop now
                        break;
                    }
                    true
                }
                '{' => {
                    curly += 1;
                    false
                }
                '}' => {
                    curly -= 1;
                    if curly < 0 {
                        // More closing than opening brackets, stop now
                        break;
                    }
                    true
                }
                '\'' => {
                    single_quote = !single_quote;
                    // A single quote can only be the end of an URL if there's an even number
                    !single_quote
                }
                _ => true,
            };
            if can_be_last {
                end = Some(i + c.len_utf8());
            }
            previous_can_be_last = can_be_last;
        }

        end
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
	        match *self {
				Error::InvalidValue => write!(f, "Invalid value."),
				Error::InvalidType => write!(f, "Invalid type."),
				Error::Io(ref err) => err.fmt(f),
			}
	}
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidValue => "Invalid value.",
            Error::InvalidType => "Invalid type.",
            Error::Io(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidValue => None,
            Error::InvalidType => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

pub struct XdrReader {
	reader : io::Cursor<Vec<u8>>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn get_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

}
pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i64::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u64::<BigEndian>(v).unwrap();
	}

}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f32::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f64::<BigEndian>(v).unwrap();
	}
}
<commit_msg>Add pack method to XdrWriter.<commit_after>use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
	        match *self {
				Error::InvalidValue => write!(f, "Invalid value."),
				Error::InvalidType => write!(f, "Invalid type."),
				Error::Io(ref err) => err.fmt(f),
			}
	}
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidValue => "Invalid value.",
            Error::InvalidType => "Invalid type.",
            Error::Io(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidValue => None,
            Error::InvalidType => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

pub struct XdrReader {
	reader : io::Cursor<Vec<u8>>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn get_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

	pub fn pack<T:XdrPrimitive>(&mut self, x:T) {
		XdrPrimitive::write_to_xdr(self, x)
	}

}
pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i64::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u64::<BigEndian>(v).unwrap();
	}

}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f32::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f64::<BigEndian>(v).unwrap();
	}
}
<|endoftext|>


<commit_before>use super::Graph;
use super::iterate::reverse_post_order;
use super::node_vec::NodeVec;

use std::fmt;

#[cfg(test)]
mod test;

pub fn dominators<G: Graph>(graph: &G)
                            -> Dominators<G>
{
    let start_node = graph.start_node();
    let rpo = reverse_post_order(graph, start_node);
    dominators_given_rpo(graph, &rpo)
}

pub fn dominators_given_rpo<G: Graph>(graph: &G,
                                      rpo: &[G::Node])
                                      -> Dominators<G>
{
    let start_node = graph.start_node();
    assert_eq!(rpo[0], start_node);

    // compute the post order index (rank) for each node
    let mut post_order_rank: NodeVec<G, usize> = NodeVec::from_default(graph);
    for (index, node) in rpo.iter().rev().cloned().enumerate() {
        post_order_rank[node] = index;
    }

    let mut immediate_dominators: NodeVec<G, Option<G::Node>> =
        NodeVec::from_default(graph);
    immediate_dominators[start_node] = Some(start_node);

    let mut changed = true;
    while changed {
        changed = false;

        for &node in &rpo[1..] {
            let mut new_idom = None;
            for pred in graph.predecessors(node) {
                if immediate_dominators[pred].is_some() { // (*)
                    // (*) dominators for `pred` have been calculated
                    new_idom = intersect_opt(&post_order_rank,
                                             &immediate_dominators,
                                             new_idom,
                                             Some(pred));
                }
            }

            if new_idom != immediate_dominators[node] {
                immediate_dominators[node] = new_idom;
                changed = true;
            }
        }
    }

    Dominators {
        post_order_rank: post_order_rank,
        immediate_dominators: immediate_dominators,
    }
}

fn intersect_opt<G: Graph>(post_order_rank: &NodeVec<G, usize>,
                           immediate_dominators: &NodeVec<G, Option<G::Node>>,
                           node1: Option<G::Node>,
                           node2: Option<G::Node>)
                           -> Option<G::Node>
{
    match (node1, node2) {
        (None, None) => None,
        (Some(n), None) | (None, Some(n)) => Some(n),
        (Some(n1), Some(n2)) => Some(intersect(post_order_rank,
                                               immediate_dominators,
                                               n1,
                                               n2)),
    }
}

fn intersect<G: Graph>(post_order_rank: &NodeVec<G, usize>,
                       immediate_dominators: &NodeVec<G, Option<G::Node>>,
                       mut node1: G::Node,
                       mut node2: G::Node)
                       -> G::Node
{
    while node1 != node2 {
        while post_order_rank[node1] < post_order_rank[node2] {
            node1 = immediate_dominators[node1].unwrap();
        }

        while post_order_rank[node2] < post_order_rank[node1] {
            node2 = immediate_dominators[node2].unwrap();
        }
    }
    return node1;
}

pub struct Dominators<G: Graph> {
    post_order_rank: NodeVec<G, usize>,
    immediate_dominators: NodeVec<G, Option<G::Node>>,
}

impl<G: Graph> Dominators<G> {
    pub fn is_reachable(&self, node: G::Node) -> bool {
        self.immediate_dominators[node].is_some()
    }

    pub fn immediate_dominator(&self, node: G::Node) -> G::Node {
        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
        self.immediate_dominators[node].unwrap()
    }

    pub fn dominators(&self, node: G::Node) -> Iter<G> {
        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
        Iter { dominators: self, node: Some(node) }
    }

    pub fn is_dominated_by(&self, node: G::Node, dom: G::Node) -> bool {
        // FIXME -- could be optimized by using post-order-rank
        self.dominators(node).any(|n| n == dom)
    }

    pub fn mutual_dominator(&self, node1: G::Node, node2: G::Node) -> G::Node {
        assert!(self.is_reachable(node1), "node {:?} is not reachable", node1);
        assert!(self.is_reachable(node2), "node {:?} is not reachable", node2);
        intersect(&self.post_order_rank, &self.immediate_dominators, node1, node2)
    }

    pub fn all_immediate_dominators(&self) -> &NodeVec<G, Option<G::Node>> {
        &self.immediate_dominators
    }

    pub fn dominator_tree(&self) -> DominatorTree<G> {
        let mut children: NodeVec<G, Vec<G::Node>> =
            NodeVec::from_default_with_len(self.immediate_dominators.len());
        let mut root = None;
        for (index, immed_dom) in self.immediate_dominators.iter().enumerate() {
            let node = G::Node::from(index);
            match *immed_dom {
                None => { /* node not reachable */ }
                Some(immed_dom) => {
                    if node == immed_dom {
                        root = Some(node);
                    } else {
                        children[immed_dom].push(node);
                    }
                }
            }
        }
        DominatorTree { root: root.unwrap(), children: children }
    }
}

pub struct Iter<'dom, G: Graph + 'dom> {
    dominators: &'dom Dominators<G>,
    node: Option<G::Node>
}

impl<'dom, G: Graph> Iterator for Iter<'dom, G> {
    type Item = G::Node;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(node) = self.node {
            let dom = self.dominators.immediate_dominator(node);
            if dom == node {
                self.node = None; // reached the root
            } else {
                self.node = Some(dom);
            }
            return Some(node);
        } else {
            return None;
        }
    }
}

pub struct DominatorTree<G: Graph> {
    root: G::Node,
    children: NodeVec<G, Vec<G::Node>>,
}

impl<G: Graph> DominatorTree<G> {
    pub fn root(&self) -> G::Node {
        self.root
    }

    pub fn children(&self, node: G::Node) -> &[G::Node] {
        &self.children[node]
    }
}

impl<G: Graph> fmt::Debug for DominatorTree<G> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Debug::fmt(&DominatorTreeNode { tree: self, node: self.root }, fmt)
    }
}

struct DominatorTreeNode<'tree, G: Graph + 'tree> {
    tree: &'tree DominatorTree<G>,
    node: G::Node,
}

impl<'tree, G: Graph> fmt::Debug for DominatorTreeNode<'tree, G> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let subtrees: Vec<_> =
            self.tree.children(self.node)
                     .iter()
                     .map(|&child| DominatorTreeNode { tree: self.tree, node: child })
                     .collect();
        fmt.debug_tuple("")
           .field(&self.node)
           .field(&subtrees)
           .finish()
    }
}

<commit_msg>dom tree and iterator (untested)<commit_after>use super::Graph;
use super::iterate::reverse_post_order;
use super::node_vec::NodeVec;

use std::fmt;

#[cfg(test)]
mod test;

pub fn dominators<G: Graph>(graph: &G)
                            -> Dominators<G>
{
    let start_node = graph.start_node();
    let rpo = reverse_post_order(graph, start_node);
    dominators_given_rpo(graph, &rpo)
}

pub fn dominators_given_rpo<G: Graph>(graph: &G,
                                      rpo: &[G::Node])
                                      -> Dominators<G>
{
    let start_node = graph.start_node();
    assert_eq!(rpo[0], start_node);

    // compute the post order index (rank) for each node
    let mut post_order_rank: NodeVec<G, usize> = NodeVec::from_default(graph);
    for (index, node) in rpo.iter().rev().cloned().enumerate() {
        post_order_rank[node] = index;
    }

    let mut immediate_dominators: NodeVec<G, Option<G::Node>> =
        NodeVec::from_default(graph);
    immediate_dominators[start_node] = Some(start_node);

    let mut changed = true;
    while changed {
        changed = false;

        for &node in &rpo[1..] {
            let mut new_idom = None;
            for pred in graph.predecessors(node) {
                if immediate_dominators[pred].is_some() { // (*)
                    // (*) dominators for `pred` have been calculated
                    new_idom = intersect_opt(&post_order_rank,
                                             &immediate_dominators,
                                             new_idom,
                                             Some(pred));
                }
            }

            if new_idom != immediate_dominators[node] {
                immediate_dominators[node] = new_idom;
                changed = true;
            }
        }
    }

    Dominators {
        post_order_rank: post_order_rank,
        immediate_dominators: immediate_dominators,
    }
}

fn intersect_opt<G: Graph>(post_order_rank: &NodeVec<G, usize>,
                           immediate_dominators: &NodeVec<G, Option<G::Node>>,
                           node1: Option<G::Node>,
                           node2: Option<G::Node>)
                           -> Option<G::Node>
{
    match (node1, node2) {
        (None, None) => None,
        (Some(n), None) | (None, Some(n)) => Some(n),
        (Some(n1), Some(n2)) => Some(intersect(post_order_rank,
                                               immediate_dominators,
                                               n1,
                                               n2)),
    }
}

fn intersect<G: Graph>(post_order_rank: &NodeVec<G, usize>,
                       immediate_dominators: &NodeVec<G, Option<G::Node>>,
                       mut node1: G::Node,
                       mut node2: G::Node)
                       -> G::Node
{
    while node1 != node2 {
        while post_order_rank[node1] < post_order_rank[node2] {
            node1 = immediate_dominators[node1].unwrap();
        }

        while post_order_rank[node2] < post_order_rank[node1] {
            node2 = immediate_dominators[node2].unwrap();
        }
    }
    return node1;
}

pub struct Dominators<G: Graph> {
    post_order_rank: NodeVec<G, usize>,
    immediate_dominators: NodeVec<G, Option<G::Node>>,
}

impl<G: Graph> Dominators<G> {
    pub fn is_reachable(&self, node: G::Node) -> bool {
        self.immediate_dominators[node].is_some()
    }

    pub fn immediate_dominator(&self, node: G::Node) -> G::Node {
        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
        self.immediate_dominators[node].unwrap()
    }

    pub fn dominators(&self, node: G::Node) -> Iter<G> {
        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
        Iter { dominators: self, node: Some(node) }
    }

    pub fn is_dominated_by(&self, node: G::Node, dom: G::Node) -> bool {
        // FIXME -- could be optimized by using post-order-rank
        self.dominators(node).any(|n| n == dom)
    }

    pub fn mutual_dominator_node(&self, node1: G::Node, node2: G::Node) -> G::Node {
        assert!(self.is_reachable(node1), "node {:?} is not reachable", node1);
        assert!(self.is_reachable(node2), "node {:?} is not reachable", node2);
        intersect(&self.post_order_rank, &self.immediate_dominators, node1, node2)
    }

    pub fn mutual_dominator<I>(&self, iter: I) -> Option<G::Node>
        where I: IntoIterator<Item=G::Node>
    {
        let mut iter = iter.into_iter();
        iter.next()
            .map(|dom| {
                iter.fold(dom, |dom, node| self.mutual_dominator_node(dom, node))
            })
    }

    pub fn all_immediate_dominators(&self) -> &NodeVec<G, Option<G::Node>> {
        &self.immediate_dominators
    }

    pub fn dominator_tree(&self) -> DominatorTree<G> {
        let mut children: NodeVec<G, Vec<G::Node>> =
            NodeVec::from_default_with_len(self.immediate_dominators.len());
        let mut root = None;
        for (index, immed_dom) in self.immediate_dominators.iter().enumerate() {
            let node = G::Node::from(index);
            match *immed_dom {
                None => { /* node not reachable */ }
                Some(immed_dom) => {
                    if node == immed_dom {
                        root = Some(node);
                    } else {
                        children[immed_dom].push(node);
                    }
                }
            }
        }
        DominatorTree { root: root.unwrap(), children: children }
    }
}

pub struct Iter<'dom, G: Graph + 'dom> {
    dominators: &'dom Dominators<G>,
    node: Option<G::Node>
}

impl<'dom, G: Graph> Iterator for Iter<'dom, G> {
    type Item = G::Node;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(node) = self.node {
            let dom = self.dominators.immediate_dominator(node);
            if dom == node {
                self.node = None; // reached the root
            } else {
                self.node = Some(dom);
            }
            return Some(node);
        } else {
            return None;
        }
    }
}

pub struct DominatorTree<G: Graph> {
    root: G::Node,
    children: NodeVec<G, Vec<G::Node>>,
}

impl<G: Graph> DominatorTree<G> {
    pub fn root(&self) -> G::Node {
        self.root
    }

    pub fn children(&self, node: G::Node) -> &[G::Node] {
        &self.children[node]
    }

    pub fn iter_children_of(&self, node: G::Node) -> IterChildrenOf<G> {
        IterChildrenOf { tree: self, stack: vec![node] }
    }
}

pub struct IterChildrenOf<'iter, G: Graph + 'iter> {
    tree: &'iter DominatorTree<G>,
    stack: Vec<G::Node>
}

impl<'iter, G: Graph> Iterator for IterChildrenOf<'iter, G> {
    type Item = G::Node;

    fn next(&mut self) -> Option<G::Node> {
        if let Some(node) = self.stack.pop() {
            self.stack.extend(self.tree.children(node));
            Some(node)
        } else {
            None
        }
    }
}

impl<G: Graph> fmt::Debug for DominatorTree<G> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Debug::fmt(&DominatorTreeNode { tree: self, node: self.root }, fmt)
    }
}

struct DominatorTreeNode<'tree, G: Graph + 'tree> {
    tree: &'tree DominatorTree<G>,
    node: G::Node,
}

impl<'tree, G: Graph> fmt::Debug for DominatorTreeNode<'tree, G> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let subtrees: Vec<_> =
            self.tree.children(self.node)
                     .iter()
                     .map(|&child| DominatorTreeNode { tree: self.tree, node: child })
                     .collect();
        fmt.debug_tuple("")
           .field(&self.node)
           .field(&subtrees)
           .finish()
    }
}

<|endoftext|>


<commit_before>use algo::{deserialize, secret_to_key, serialize};

use communication::Communicate;

use bignum::BigNumTrait;
use bignum::NumBigInt as BigNum;

use failure::{err_msg, Error};
use handshake::{ClientDeterminesParameters, ClientServerPair, ServerCanOverrideParameters};

pub trait MitmHandshake<T: Communicate> {
    fn handshake(client_stream: &mut T, server_stream: &mut T) -> Result<Vec<u8>, Error>;
}

pub trait MitmForClientServer<T: Communicate> {
    type Mitm: MitmHandshake<T>;
    type CS: ClientServerPair<T>;
}

// Mitm used for challenge 34

pub struct MitmHandshakeFakePublicKey;

impl<T: Communicate> MitmHandshake<T> for MitmHandshakeFakePublicKey {
    fn handshake(client_stream: &mut T, server_stream: &mut T) -> Result<Vec<u8>, Error> {
        let p = client_stream
            .receive()?
            .ok_or_else(|| err_msg("did not receive p"))?;
        let g = client_stream
            .receive()?
            .ok_or_else(|| err_msg("did not receive g"))?;
        server_stream.send(&p)?;
        server_stream.send(&g)?;
        //Discard actual public keys
        client_stream.receive()?;
        server_stream.receive()?;
        //Send fake public keys
        client_stream.send(&p)?;
        server_stream.send(&p)?;
        let key = secret_to_key(&[0]);
        Ok(key)
    }
}

pub struct MitmFakePublicKey;

impl<T: Communicate> MitmForClientServer<T> for MitmFakePublicKey {
    type Mitm = MitmHandshakeFakePublicKey;
    type CS = ClientDeterminesParameters;
}

// Mitm used for challenge 35

pub enum FakeGeneratorMode {
    One,
    P,
    PMinusOne,
}

#[allow(non_snake_case)]
fn handshake_with_fake_generator<T: Communicate>(
    client_stream: &mut T,
    server_stream: &mut T,
    mode: &FakeGeneratorMode,
) -> Result<Vec<u8>, Error> {
    let p = client_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive p"))?;
    // Discard g
    client_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive g"))?;

    server_stream.send(&p)?;

    let g_fake = compute_fake_generator(mode, &p);

    // Send fake g
    server_stream.send(&g_fake)?;

    server_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive p"))?;
    server_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive g"))?;

    client_stream.send(&p)?;

    // Send fake g
    client_stream.send(&g_fake)?;

    let A = client_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive A"))?;
    let B = server_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive B"))?;
    client_stream.send(&B)?;
    server_stream.send(&A)?;

    let secret = compute_secret(&mode, &A, &B);
    let key = secret_to_key(&secret);
    Ok(key)
}

fn compute_fake_generator(mode: &FakeGeneratorMode, p: &[u8]) -> Vec<u8> {
    let _1 = BigNum::from_u32(1);
    serialize(&match mode {
        FakeGeneratorMode::One => _1,
        FakeGeneratorMode::P => deserialize(&p),
        FakeGeneratorMode::PMinusOne => &deserialize(&p) - &_1,
    })
}

#[allow(non_snake_case)]
fn compute_secret(mode: &FakeGeneratorMode, A: &[u8], B: &[u8]) -> Vec<u8> {
    let _0 = serialize(&BigNum::from_u32(0));
    let _1 = serialize(&BigNum::from_u32(1));
    match mode {
        FakeGeneratorMode::One => _1,
        FakeGeneratorMode::P => _0,
        FakeGeneratorMode::PMinusOne => {
            /* In this case, both client and server use the generator p - 1.
             * But p - 1 is equal to -1 modulo p. Therefore A = (g ^ a) % p
             * is either equal to 1 or to -1, depending on whether a is even or odd,
             * and analogously for B and b. The shared secret is equal to g ^ (a * b) % p.
             * By noting that the product a * b is even iff at least one of a or b is even
             * we can compute the shared secret from the public keys as follows. */
            if A == &_1[..] || B == &_1[..] {
                _1
            } else {
                A.to_vec()
            }
        }
    }
}

// I could not get this to work in the type system
macro_rules! generator {
    ($handshake:ident, $mitm:ident, $mode:expr) => {
        pub struct $handshake;
        impl<T: Communicate> MitmHandshake<T> for $handshake {
            fn handshake(client_stream: &mut T, server_stream: &mut T) -> Result<Vec<u8>, Error> {
                handshake_with_fake_generator(client_stream, server_stream, &$mode)
            }
        }

        pub struct $mitm;
        impl<T: Communicate> MitmForClientServer<T> for $mitm {
            type Mitm = $handshake;
            type CS = ServerCanOverrideParameters;
        }
    };
}

generator!(
    MitmHandshakeFakeGeneratorOne,
    MitmFakeGeneratorOne,
    FakeGeneratorMode::One
);
generator!(
    MitmHandshakeFakeGeneratorP,
    MitmFakeGeneratorP,
    FakeGeneratorMode::P
);
generator!(
    MitmHandshakeFakeGeneratorPMinusOne,
    MitmFakeGeneratorPMinusOne,
    FakeGeneratorMode::PMinusOne
);
<commit_msg>Fix bug: zero might not be serialized to [0]<commit_after>use algo::{deserialize, secret_to_key, serialize};

use communication::Communicate;

use bignum::BigNumTrait;
use bignum::NumBigInt as BigNum;

use failure::{err_msg, Error};
use handshake::{ClientDeterminesParameters, ClientServerPair, ServerCanOverrideParameters};

pub trait MitmHandshake<T: Communicate> {
    fn handshake(client_stream: &mut T, server_stream: &mut T) -> Result<Vec<u8>, Error>;
}

pub trait MitmForClientServer<T: Communicate> {
    type Mitm: MitmHandshake<T>;
    type CS: ClientServerPair<T>;
}

// Mitm used for challenge 34

pub struct MitmHandshakeFakePublicKey;

impl<T: Communicate> MitmHandshake<T> for MitmHandshakeFakePublicKey {
    fn handshake(client_stream: &mut T, server_stream: &mut T) -> Result<Vec<u8>, Error> {
        let p = client_stream
            .receive()?
            .ok_or_else(|| err_msg("did not receive p"))?;
        let g = client_stream
            .receive()?
            .ok_or_else(|| err_msg("did not receive g"))?;
        server_stream.send(&p)?;
        server_stream.send(&g)?;
        //Discard actual public keys
        client_stream.receive()?;
        server_stream.receive()?;
        //Send fake public keys
        client_stream.send(&p)?;
        server_stream.send(&p)?;
        let key = secret_to_key(&serialize(&BigNum::zero()));
        Ok(key)
    }
}

pub struct MitmFakePublicKey;

impl<T: Communicate> MitmForClientServer<T> for MitmFakePublicKey {
    type Mitm = MitmHandshakeFakePublicKey;
    type CS = ClientDeterminesParameters;
}

// Mitm used for challenge 35

pub enum FakeGeneratorMode {
    One,
    P,
    PMinusOne,
}

#[allow(non_snake_case)]
fn handshake_with_fake_generator<T: Communicate>(
    client_stream: &mut T,
    server_stream: &mut T,
    mode: &FakeGeneratorMode,
) -> Result<Vec<u8>, Error> {
    let p = client_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive p"))?;
    // Discard g
    client_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive g"))?;

    server_stream.send(&p)?;

    let g_fake = compute_fake_generator(mode, &p);

    // Send fake g
    server_stream.send(&g_fake)?;

    server_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive p"))?;
    server_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive g"))?;

    client_stream.send(&p)?;

    // Send fake g
    client_stream.send(&g_fake)?;

    let A = client_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive A"))?;
    let B = server_stream
        .receive()?
        .ok_or_else(|| err_msg("did not receive B"))?;
    client_stream.send(&B)?;
    server_stream.send(&A)?;

    let secret = compute_secret(&mode, &A, &B);
    let key = secret_to_key(&secret);
    Ok(key)
}

fn compute_fake_generator(mode: &FakeGeneratorMode, p: &[u8]) -> Vec<u8> {
    let _1 = BigNum::from_u32(1);
    serialize(&match mode {
        FakeGeneratorMode::One => _1,
        FakeGeneratorMode::P => deserialize(&p),
        FakeGeneratorMode::PMinusOne => &deserialize(&p) - &_1,
    })
}

#[allow(non_snake_case)]
fn compute_secret(mode: &FakeGeneratorMode, A: &[u8], B: &[u8]) -> Vec<u8> {
    let _0 = serialize(&BigNum::from_u32(0));
    let _1 = serialize(&BigNum::from_u32(1));
    match mode {
        FakeGeneratorMode::One => _1,
        FakeGeneratorMode::P => _0,
        FakeGeneratorMode::PMinusOne => {
            /* In this case, both client and server use the generator p - 1.
             * But p - 1 is equal to -1 modulo p. Therefore A = (g ^ a) % p
             * is either equal to 1 or to -1, depending on whether a is even or odd,
             * and analogously for B and b. The shared secret is equal to g ^ (a * b) % p.
             * By noting that the product a * b is even iff at least one of a or b is even
             * we can compute the shared secret from the public keys as follows. */
            if A == &_1[..] || B == &_1[..] {
                _1
            } else {
                A.to_vec()
            }
        }
    }
}

// I could not get this to work in the type system
macro_rules! generator {
    ($handshake:ident, $mitm:ident, $mode:expr) => {
        pub struct $handshake;
        impl<T: Communicate> MitmHandshake<T> for $handshake {
            fn handshake(client_stream: &mut T, server_stream: &mut T) -> Result<Vec<u8>, Error> {
                handshake_with_fake_generator(client_stream, server_stream, &$mode)
            }
        }

        pub struct $mitm;
        impl<T: Communicate> MitmForClientServer<T> for $mitm {
            type Mitm = $handshake;
            type CS = ServerCanOverrideParameters;
        }
    };
}

generator!(
    MitmHandshakeFakeGeneratorOne,
    MitmFakeGeneratorOne,
    FakeGeneratorMode::One
);
generator!(
    MitmHandshakeFakeGeneratorP,
    MitmFakeGeneratorP,
    FakeGeneratorMode::P
);
generator!(
    MitmHandshakeFakeGeneratorPMinusOne,
    MitmFakeGeneratorPMinusOne,
    FakeGeneratorMode::PMinusOne
);
<|endoftext|>


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

use backend::{Backend, SupportsDefaultKeyword};
use expression::Expression;
use result::QueryResult;
use query_builder::{QueryBuilder, BuildQueryResult};
use query_source::{Table, Column};

/// Represents that a structure can be used to to insert a new row into the
/// database. This is automatically implemented for `&[T]` and `&Vec<T>` for
/// inserting more than one record.
///
/// ### Deriving
///
/// This trait can be automatically derived using `diesel_codegen` by adding
/// `#[derive(Insertable)]` to your struct. Structs which derive this trait must
/// also be annotated with `#[table_name = "some_table_name"]`. If the field
/// name of your struct differs from the name of the column, you can annotate
/// the field with `#[column_name = "some_column_name"]`.
pub trait Insertable<T: Table, DB: Backend> {
    type Values: InsertValues<DB>;

    fn values(self) -> Self::Values;
}

pub trait InsertValues<DB: Backend> {
    fn column_names(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult;
    fn values_clause(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult;
    fn values_bind_params(&self, out: &mut DB::BindCollector) -> QueryResult<()>;
}

#[derive(Debug, Copy, Clone)]
pub enum ColumnInsertValue<Col, Expr> where
    Col: Column,
    Expr: Expression<SqlType=Col::SqlType>,
{
    Expression(Col, Expr),
    Default(Col),
}

impl<'a, T, U: 'a, DB> Insertable<T, DB> for &'a [U] where
    T: Table,
    DB: Backend,
    &'a U: Insertable<T, DB>,
    DB: SupportsDefaultKeyword,
{
    type Values = BatchInsertValues<'a, T, U, DB>;

    fn values(self) -> Self::Values {
        BatchInsertValues {
            values: self,
            _marker: PhantomData,
        }
    }
}

impl<'a, T, U, DB> Insertable<T, DB> for &'a Vec<U> where
    T: Table,
    DB: Backend,
    &'a [U]: Insertable<T, DB>,
{
    type Values = <&'a [U] as Insertable<T, DB>>::Values;

    fn values(self) -> Self::Values {
        (self as &'a [U]).values()
    }
}

#[derive(Debug, Copy, Clone)]
pub struct BatchInsertValues<'a, T, U: 'a, DB> {
    values: &'a [U],
    _marker: PhantomData<(T, DB)>,
}

impl<'a, T, U: 'a, DB> InsertValues<DB> for BatchInsertValues<'a, T, U, DB> where
    T: Table,
    DB: Backend,
    &'a U: Insertable<T, DB>,
{
    fn column_names(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        self.values[0].values().column_names(out)
    }

    fn values_clause(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        for (i, record) in self.values.into_iter().enumerate() {
            if i != 0 {
                out.push_sql(", ");
            }
            try!(record.values().values_clause(out));
        }
        Ok(())
    }

    fn values_bind_params(&self, out: &mut DB::BindCollector) -> QueryResult<()> {
        for record in self.values.into_iter() {
            try!(record.values().values_bind_params(out));
        }
        Ok(())
    }
}
<commit_msg>Simplify the implementation of `BatchInsertValues` a bit<commit_after>use backend::{Backend, SupportsDefaultKeyword};
use expression::Expression;
use result::QueryResult;
use query_builder::{QueryBuilder, BuildQueryResult};
use query_source::{Table, Column};

/// Represents that a structure can be used to to insert a new row into the
/// database. This is automatically implemented for `&[T]` and `&Vec<T>` for
/// inserting more than one record.
///
/// ### Deriving
///
/// This trait can be automatically derived using `diesel_codegen` by adding
/// `#[derive(Insertable)]` to your struct. Structs which derive this trait must
/// also be annotated with `#[table_name = "some_table_name"]`. If the field
/// name of your struct differs from the name of the column, you can annotate
/// the field with `#[column_name = "some_column_name"]`.
pub trait Insertable<T: Table, DB: Backend> {
    type Values: InsertValues<DB>;

    fn values(self) -> Self::Values;
}

pub trait InsertValues<DB: Backend> {
    fn column_names(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult;
    fn values_clause(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult;
    fn values_bind_params(&self, out: &mut DB::BindCollector) -> QueryResult<()>;
}

#[derive(Debug, Copy, Clone)]
pub enum ColumnInsertValue<Col, Expr> where
    Col: Column,
    Expr: Expression<SqlType=Col::SqlType>,
{
    Expression(Col, Expr),
    Default(Col),
}

impl<Iter, T, DB> Insertable<T, DB> for Iter where
    T: Table,
    DB: Backend + SupportsDefaultKeyword,
    Iter: IntoIterator,
    Iter::Item: Insertable<T, DB>,
{
    type Values = BatchInsertValues<<Iter::Item as Insertable<T, DB>>::Values>;

    fn values(self) -> Self::Values {
        let values = self.into_iter().map(Insertable::values).collect();
        BatchInsertValues(values)
    }
}

#[derive(Debug, Clone)]
pub struct BatchInsertValues<T>(Vec<T>);

impl<T, DB> InsertValues<DB> for BatchInsertValues<T> where
    T: InsertValues<DB>,
    DB: Backend,
{
    fn column_names(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        self.0[0].column_names(out)
    }

    fn values_clause(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        for (i, values) in self.0.iter().enumerate() {
            if i != 0 {
                out.push_sql(", ");
            }
            try!(values.values_clause(out));
        }
        Ok(())
    }

    fn values_bind_params(&self, out: &mut DB::BindCollector) -> QueryResult<()> {
        for values in self.0.iter() {
            try!(values.values_bind_params(out));
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>#[doc = "Rust wrappers around the raw JS apis"];

import bg = jsapi::bindgen;
import libc::types::os::arch::c95::size_t;

export rt;
export cx;
export jsobj;
export methods;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

type rt = @rt_rsrc;

resource rt_rsrc(self: {ptr: *JSRuntime}) {
    JS_Finish(self.ptr)
}

fn rt() -> rt {
    @rt_rsrc({ptr: JS_Init(default_heapsize)})
}

impl methods for rt {
    fn cx() -> cx {
        @cx_rsrc({ptr: JS_NewContext(self.ptr, default_stacksize as size_t),
                  rt: self})
    }
}

// ___________________________________________________________________________
// contexts

type cx = @cx_rsrc;
resource cx_rsrc(self: {ptr: *JSContext, rt: rt}) {
    JS_DestroyContext(self.ptr);
}

impl methods for cx {
    fn rooted_obj(obj: *JSObject) -> jsobj {
        let jsobj = @jsobj_rsrc({cx: self, cxptr: self.ptr, ptr: obj});
        JS_AddObjectRoot(self.ptr, ptr::addr_of(jsobj.ptr));
        jsobj
    }

    fn set_default_options_and_version() {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT);
        self.set_version(JSVERSION_LATEST);
    }

    fn set_options(v: jsuint) {
        JS_SetOptions(self.ptr, v);
    }

    fn set_version(v: i32) {
        JS_SetVersion(self.ptr, v);
    }

    fn set_logging_error_reporter() {
        JS_SetErrorReporter(self.ptr, reportError);
    }

    fn set_error_reporter(reportfn: *u8) {
        JS_SetErrorReporter(self.ptr, reportfn);
    }

    fn new_compartment(globclsfn: fn(name_pool) -> JSClass) -> result<compartment,()> {
        let np = name_pool();
        let globcls = @globclsfn(np);
        let globobj =
            JS_NewCompartmentAndGlobalObject(
                self.ptr,
                &*globcls as *JSClass,
                null());
        result(JS_InitStandardClasses(self.ptr, globobj)).chain { |_ok|
            ok(@{cx: self,
                 name_pool: np,
                 global_class: globcls,
                 mut global_funcs: [],
                 global_obj: self.rooted_obj(globobj)})
        }
    }

    fn evaluate_script(glob: jsobj, bytes: [u8], filename: str,
                       line_num: uint) -> result<(),()> {
        vec::as_buf(bytes) { |bytes_ptr|
            str::as_c_str(filename) { |filename_cstr|
                let bytes_ptr = bytes_ptr as *c_char;
                let v: jsval = 0_u64;
                #debug["Evaluating script from %s with bytes %?", filename, bytes];
                if JS_EvaluateScript(self.ptr, glob.ptr,
                                     bytes_ptr, bytes.len() as uintN,
                                     filename_cstr, line_num as uintN,
                                     ptr::addr_of(v)) == ERR {
                    #debug["...err!"];
                    err(())
                } else {
                    // we could return the script result but then we'd have
                    // to root it and so forth and, really, who cares?
                    #debug["...ok!"];
                    ok(())
                }
            }
        }
    }

    unsafe fn get_cx_private() -> *() {
        unsafe::reinterpret_cast(JS_GetContextPrivate(self.ptr))
    }

    unsafe fn set_cx_private(data: *()) {
        JS_SetContextPrivate(self.ptr, unsafe::reinterpret_cast(data));
    }

    unsafe fn get_obj_private(obj: *JSObject) -> *() {
        unsafe::reinterpret_cast(JS_GetPrivate(self.ptr, obj))
    }

    unsafe fn set_obj_private(obj: *JSObject, data: *()) {
        JS_SetPrivate(self.ptr, obj, unsafe::reinterpret_cast(data));
    }
}

crust fn reportError(_cx: *JSContext,
                     msg: *c_char,
                     report: *JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {"none"};
        let lineno = (*report).lineno;
        let msg = from_c_str(msg);
        #error["Error at %s:%?: %s\n", fname, lineno, msg];
    }
}

// ___________________________________________________________________________
// compartment

type compartment = @{
    cx: cx,
    name_pool: name_pool,
    global_class: @JSClass,
    mut global_funcs: [@[JSFunctionSpec]],
    global_obj: jsobj
};

impl methods for compartment {
    fn define_functions(specfn: fn(name_pool) -> [JSFunctionSpec]) -> result<(),()> {
        let specvec = @specfn(self.name_pool);
        self.global_funcs += [specvec];
        vec::as_buf(*specvec) { |specs|
            result(JS_DefineFunctions(self.cx.ptr, self.global_obj.ptr, specs))
        }
    }
}

// ___________________________________________________________________________
// objects

type jsobj = @jsobj_rsrc;

resource jsobj_rsrc(self: {cx: cx, cxptr: *JSContext, ptr: *JSObject}) {
    JS_RemoveObjectRoot(self.cxptr, ptr::addr_of(self.ptr));
}

// ___________________________________________________________________________
// random utilities

impl methods for str {
    fn to_jsstr(cx: cx) -> *JSString {
        str::as_buf(self) { |buf|
            let cbuf = unsafe { unsafe::reinterpret_cast(buf) };
            bg::JS_NewStringCopyN(cx.ptr, cbuf, self.len())
        }
    }
}

#[cfg(test)]
mod test {

    #[test]
    fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.set_default_options_and_version();
        cx.set_logging_error_reporter();
        cx.new_compartment(global::global_class).chain { |comp|
            comp.define_functions(global::debug_fns);

            let bytes = str::bytes("debug(22);");
            cx.evaluate_script(comp.global_obj, bytes, "test", 1u)
        };
    }

}
<commit_msg>Add a cast to fix build<commit_after>#[doc = "Rust wrappers around the raw JS apis"];

import bg = jsapi::bindgen;
import libc::types::os::arch::c95::size_t;

export rt;
export cx;
export jsobj;
export methods;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

type rt = @rt_rsrc;

resource rt_rsrc(self: {ptr: *JSRuntime}) {
    JS_Finish(self.ptr)
}

fn rt() -> rt {
    @rt_rsrc({ptr: JS_Init(default_heapsize)})
}

impl methods for rt {
    fn cx() -> cx {
        @cx_rsrc({ptr: JS_NewContext(self.ptr, default_stacksize as size_t),
                  rt: self})
    }
}

// ___________________________________________________________________________
// contexts

type cx = @cx_rsrc;
resource cx_rsrc(self: {ptr: *JSContext, rt: rt}) {
    JS_DestroyContext(self.ptr);
}

impl methods for cx {
    fn rooted_obj(obj: *JSObject) -> jsobj {
        let jsobj = @jsobj_rsrc({cx: self, cxptr: self.ptr, ptr: obj});
        JS_AddObjectRoot(self.ptr, ptr::addr_of(jsobj.ptr));
        jsobj
    }

    fn set_default_options_and_version() {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT);
        self.set_version(JSVERSION_LATEST);
    }

    fn set_options(v: jsuint) {
        JS_SetOptions(self.ptr, v);
    }

    fn set_version(v: i32) {
        JS_SetVersion(self.ptr, v);
    }

    fn set_logging_error_reporter() {
        JS_SetErrorReporter(self.ptr, reportError);
    }

    fn set_error_reporter(reportfn: *u8) {
        JS_SetErrorReporter(self.ptr, reportfn);
    }

    fn new_compartment(globclsfn: fn(name_pool) -> JSClass) -> result<compartment,()> {
        let np = name_pool();
        let globcls = @globclsfn(np);
        let globobj =
            JS_NewCompartmentAndGlobalObject(
                self.ptr,
                &*globcls as *JSClass,
                null());
        result(JS_InitStandardClasses(self.ptr, globobj)).chain { |_ok|
            ok(@{cx: self,
                 name_pool: np,
                 global_class: globcls,
                 mut global_funcs: [],
                 global_obj: self.rooted_obj(globobj)})
        }
    }

    fn evaluate_script(glob: jsobj, bytes: [u8], filename: str,
                       line_num: uint) -> result<(),()> {
        vec::as_buf(bytes) { |bytes_ptr|
            str::as_c_str(filename) { |filename_cstr|
                let bytes_ptr = bytes_ptr as *c_char;
                let v: jsval = 0_u64;
                #debug["Evaluating script from %s with bytes %?", filename, bytes];
                if JS_EvaluateScript(self.ptr, glob.ptr,
                                     bytes_ptr, bytes.len() as uintN,
                                     filename_cstr, line_num as uintN,
                                     ptr::addr_of(v)) == ERR {
                    #debug["...err!"];
                    err(())
                } else {
                    // we could return the script result but then we'd have
                    // to root it and so forth and, really, who cares?
                    #debug["...ok!"];
                    ok(())
                }
            }
        }
    }

    unsafe fn get_cx_private() -> *() {
        unsafe::reinterpret_cast(JS_GetContextPrivate(self.ptr))
    }

    unsafe fn set_cx_private(data: *()) {
        JS_SetContextPrivate(self.ptr, unsafe::reinterpret_cast(data));
    }

    unsafe fn get_obj_private(obj: *JSObject) -> *() {
        unsafe::reinterpret_cast(JS_GetPrivate(self.ptr, obj))
    }

    unsafe fn set_obj_private(obj: *JSObject, data: *()) {
        JS_SetPrivate(self.ptr, obj, unsafe::reinterpret_cast(data));
    }
}

crust fn reportError(_cx: *JSContext,
                     msg: *c_char,
                     report: *JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {"none"};
        let lineno = (*report).lineno;
        let msg = from_c_str(msg);
        #error["Error at %s:%?: %s\n", fname, lineno, msg];
    }
}

// ___________________________________________________________________________
// compartment

type compartment = @{
    cx: cx,
    name_pool: name_pool,
    global_class: @JSClass,
    mut global_funcs: [@[JSFunctionSpec]],
    global_obj: jsobj
};

impl methods for compartment {
    fn define_functions(specfn: fn(name_pool) -> [JSFunctionSpec]) -> result<(),()> {
        let specvec = @specfn(self.name_pool);
        self.global_funcs += [specvec];
        vec::as_buf(*specvec) { |specs|
            result(JS_DefineFunctions(self.cx.ptr, self.global_obj.ptr, specs))
        }
    }
}

// ___________________________________________________________________________
// objects

type jsobj = @jsobj_rsrc;

resource jsobj_rsrc(self: {cx: cx, cxptr: *JSContext, ptr: *JSObject}) {
    JS_RemoveObjectRoot(self.cxptr, ptr::addr_of(self.ptr));
}

// ___________________________________________________________________________
// random utilities

impl methods for str {
    fn to_jsstr(cx: cx) -> *JSString {
        str::as_buf(self) { |buf|
            let cbuf = unsafe { unsafe::reinterpret_cast(buf) };
            bg::JS_NewStringCopyN(cx.ptr, cbuf, self.len() as size_t)
        }
    }
}

#[cfg(test)]
mod test {

    #[test]
    fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.set_default_options_and_version();
        cx.set_logging_error_reporter();
        cx.new_compartment(global::global_class).chain { |comp|
            comp.define_functions(global::debug_fns);

            let bytes = str::bytes("debug(22);");
            cx.evaluate_script(comp.global_obj, bytes, "test", 1u)
        };
    }

}
<|endoftext|>


<commit_before>extern crate clap;
extern crate regex;

#[cfg(test)]
mod tests {
    include!("../clap-test.rs");
    use clap::{App, Arg, SubCommand, ArgMatches};

    fn get_app() -> App<'static, 'static> {
        App::new("myprog")
            .arg(Arg::with_name("GLOBAL_ARG")
                .long("global-arg")
                .help(
                    "Specifies something needed by the subcommands",
                )
                .global(true)
                .takes_value(true)
                .default_value("default_value"))
            .arg(Arg::with_name("GLOBAL_FLAG")
                .long("global-flag")
                .help(
                    "Specifies something needed by the subcommands",
                )
                .multiple(true)
                .global(true))
            .subcommand(SubCommand::with_name("outer")
                .subcommand(SubCommand::with_name("inner")))
    }

    fn get_matches(app: App<'static, 'static>, argv: &'static str) -> ArgMatches<'static> {
        app.get_matches_from(argv.split(" ").collect::<Vec<_>>())
    }

    fn get_outer_matches<'a>(m: &'a ArgMatches<'static>) -> &'a ArgMatches<'static> {
        m.subcommand_matches("outer").expect("could not access outer subcommand")
    }

    fn get_inner_matches<'a>(m: &'a ArgMatches<'static>) -> &'a ArgMatches<'static> {
        get_outer_matches(m).subcommand_matches("inner").expect("could not access inner subcommand")
    }

    fn top_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
        m.value_of("GLOBAL_ARG") == val.into()
    }

    fn inner_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
        get_inner_matches(m).value_of("GLOBAL_ARG") == val.into()
    }

    fn outer_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
        get_outer_matches(m).value_of("GLOBAL_ARG") == val.into()
    }

    fn top_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
        (m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
    }

    fn inner_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
        let m = get_inner_matches(m);
        (m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
    }

    fn outer_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
        let m = get_outer_matches(m);
        (m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
    }

    #[test]
    fn global_arg_used_top_level() {
        let m = get_matches(get_app(), "myprog --global-arg=some_value outer inner");

        assert!(top_can_access_arg(&m, "some_value"));
        assert!(inner_can_access_arg(&m, "some_value"));
        assert!(outer_can_access_arg(&m, "some_value"));
    }

    #[test]
    fn global_arg_used_outer() {
        let m = get_matches(get_app(), "myprog outer --global-arg=some_value inner");

        assert!(top_can_access_arg(&m, "some_value"));
        assert!(inner_can_access_arg(&m, "some_value"));
        assert!(outer_can_access_arg(&m, "some_value"));
    }

    #[test]
    fn global_arg_used_inner() {
        let m = get_matches(get_app(), "myprog outer inner --global-arg=some_value");

        assert!(top_can_access_arg(&m, "some_value"));
        assert!(inner_can_access_arg(&m, "some_value"));
        assert!(outer_can_access_arg(&m, "some_value"));
    }

    #[test]
    fn global_arg_default_value() {
        let m = get_matches(get_app(), "myprog outer inner");

        assert!(top_can_access_arg(&m, "default_value"));
        assert!(inner_can_access_arg(&m, "default_value"));
        assert!(outer_can_access_arg(&m, "default_value"));
    }

    #[test]
    fn global_flag_used_top_level() {
        let m = get_matches(get_app(), "myprog --global-flag outer inner");

        assert!(top_can_access_flag(&m, true, 1));
        assert!(inner_can_access_flag(&m, true, 1));
        assert!(outer_can_access_flag(&m, true, 1));
    }

    #[test]
    fn global_flag_used_outer() {
        let m = get_matches(get_app(), "myprog outer --global-flag inner");

        assert!(top_can_access_flag(&m, true, 1));
        assert!(inner_can_access_flag(&m, true, 1));
        assert!(outer_can_access_flag(&m, true, 1));
    }

    #[test]
    fn global_flag_used_inner() {
        let m = get_matches(get_app(), "myprog outer inner --global-flag");

        assert!(top_can_access_flag(&m, true, 1));
        assert!(inner_can_access_flag(&m, true, 1));
        assert!(outer_can_access_flag(&m, true, 1));
    }

    #[test]
    fn global_flag_2x_used_top_level() {
        let m = get_matches(get_app(), "myprog --global-flag --global-flag outer inner");

        assert!(top_can_access_flag(&m, true, 2));
        assert!(inner_can_access_flag(&m, true, 2));
        assert!(outer_can_access_flag(&m, true, 2));
    }

    #[test]
    fn global_flag_2x_used_inner() {
        let m = get_matches(get_app(), "myprog outer inner --global-flag --global-flag");

        assert!(top_can_access_flag(&m, true, 2));
        assert!(inner_can_access_flag(&m, true, 2));
        assert!(outer_can_access_flag(&m, true, 2));
    }
}
<commit_msg>chore(clippy): Use single character pattern in test.<commit_after>extern crate clap;
extern crate regex;

#[cfg(test)]
mod tests {
    include!("../clap-test.rs");
    use clap::{App, Arg, SubCommand, ArgMatches};

    fn get_app() -> App<'static, 'static> {
        App::new("myprog")
            .arg(Arg::with_name("GLOBAL_ARG")
                .long("global-arg")
                .help(
                    "Specifies something needed by the subcommands",
                )
                .global(true)
                .takes_value(true)
                .default_value("default_value"))
            .arg(Arg::with_name("GLOBAL_FLAG")
                .long("global-flag")
                .help(
                    "Specifies something needed by the subcommands",
                )
                .multiple(true)
                .global(true))
            .subcommand(SubCommand::with_name("outer")
                .subcommand(SubCommand::with_name("inner")))
    }

    fn get_matches(app: App<'static, 'static>, argv: &'static str) -> ArgMatches<'static> {
        app.get_matches_from(argv.split(' ').collect::<Vec<_>>())
    }

    fn get_outer_matches<'a>(m: &'a ArgMatches<'static>) -> &'a ArgMatches<'static> {
        m.subcommand_matches("outer").expect("could not access outer subcommand")
    }

    fn get_inner_matches<'a>(m: &'a ArgMatches<'static>) -> &'a ArgMatches<'static> {
        get_outer_matches(m).subcommand_matches("inner").expect("could not access inner subcommand")
    }

    fn top_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
        m.value_of("GLOBAL_ARG") == val.into()
    }

    fn inner_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
        get_inner_matches(m).value_of("GLOBAL_ARG") == val.into()
    }

    fn outer_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
        get_outer_matches(m).value_of("GLOBAL_ARG") == val.into()
    }

    fn top_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
        (m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
    }

    fn inner_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
        let m = get_inner_matches(m);
        (m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
    }

    fn outer_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
        let m = get_outer_matches(m);
        (m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
    }

    #[test]
    fn global_arg_used_top_level() {
        let m = get_matches(get_app(), "myprog --global-arg=some_value outer inner");

        assert!(top_can_access_arg(&m, "some_value"));
        assert!(inner_can_access_arg(&m, "some_value"));
        assert!(outer_can_access_arg(&m, "some_value"));
    }

    #[test]
    fn global_arg_used_outer() {
        let m = get_matches(get_app(), "myprog outer --global-arg=some_value inner");

        assert!(top_can_access_arg(&m, "some_value"));
        assert!(inner_can_access_arg(&m, "some_value"));
        assert!(outer_can_access_arg(&m, "some_value"));
    }

    #[test]
    fn global_arg_used_inner() {
        let m = get_matches(get_app(), "myprog outer inner --global-arg=some_value");

        assert!(top_can_access_arg(&m, "some_value"));
        assert!(inner_can_access_arg(&m, "some_value"));
        assert!(outer_can_access_arg(&m, "some_value"));
    }

    #[test]
    fn global_arg_default_value() {
        let m = get_matches(get_app(), "myprog outer inner");

        assert!(top_can_access_arg(&m, "default_value"));
        assert!(inner_can_access_arg(&m, "default_value"));
        assert!(outer_can_access_arg(&m, "default_value"));
    }

    #[test]
    fn global_flag_used_top_level() {
        let m = get_matches(get_app(), "myprog --global-flag outer inner");

        assert!(top_can_access_flag(&m, true, 1));
        assert!(inner_can_access_flag(&m, true, 1));
        assert!(outer_can_access_flag(&m, true, 1));
    }

    #[test]
    fn global_flag_used_outer() {
        let m = get_matches(get_app(), "myprog outer --global-flag inner");

        assert!(top_can_access_flag(&m, true, 1));
        assert!(inner_can_access_flag(&m, true, 1));
        assert!(outer_can_access_flag(&m, true, 1));
    }

    #[test]
    fn global_flag_used_inner() {
        let m = get_matches(get_app(), "myprog outer inner --global-flag");

        assert!(top_can_access_flag(&m, true, 1));
        assert!(inner_can_access_flag(&m, true, 1));
        assert!(outer_can_access_flag(&m, true, 1));
    }

    #[test]
    fn global_flag_2x_used_top_level() {
        let m = get_matches(get_app(), "myprog --global-flag --global-flag outer inner");

        assert!(top_can_access_flag(&m, true, 2));
        assert!(inner_can_access_flag(&m, true, 2));
        assert!(outer_can_access_flag(&m, true, 2));
    }

    #[test]
    fn global_flag_2x_used_inner() {
        let m = get_matches(get_app(), "myprog outer inner --global-flag --global-flag");

        assert!(top_can_access_flag(&m, true, 2));
        assert!(inner_can_access_flag(&m, true, 2));
        assert!(outer_can_access_flag(&m, true, 2));
    }
}
<|endoftext|>