<commit_before>use gc::Gc;
use std::fmt::{Show,Formatter};
use std::fmt;

/// A generic value within our virtual machine. A value
/// can be anything defined within this enum.
pub enum Value {
  Int(u32),
  Str(~str),
  Pair(~Value, ~Value)
}

impl Eq for Value {
  fn eq(&self, other: &Value) -> bool {
    true
  }
}

impl Show for Value {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    match *self {
      Int(i) => write!(f.buf, "({})", i),
      Str(ref s) => write!(f.buf, "({})", s),
      _ => write!(f.buf, "({})", *self )
    }
  }
}

/// A virtual machine that holds needed objects (gc, stack, etc...) and
/// the current state.
pub struct Vm {
  /// A global garbage collector.
  gc: Gc,

  /// Our small stack. For simplicity, we'll limit this to
  /// a static value.
  stack: ~[Value],

  /// Stack Size
  stack_size: u64
}

impl Vm {
  pub fn new() -> Vm {
    Vm {
      gc: Gc::new(),
      stack: ~[],
      stack_size: 0
    }
  }

  pub fn push(&mut self, val: Value) {
    self.stack.push(val);
    self.stack_size += 1;
  }

  pub fn pop(&mut self) -> Option<Value> {
    self.stack_size -= 1;
    self.stack.pop()
  }
}

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

  #[test]
  fn empty_stack_default() {
    let vm = Vm::new();
    assert_eq!(vm.stack_size, 0);
  }

  #[test]
  fn should_push_item() {
    let mut vm = Vm::new();
    let val = Str(~"Hello World");
    vm.push(val);
    assert_eq!(vm.stack_size, 1);
    //assert_eq!(vm.stack[0], val);
  }

}<commit_msg>implemented Eq<commit_after>use gc::Gc;
use std::fmt::{Show,Formatter};
use std::fmt;

/// A generic value within our virtual machine. A value
/// can be anything defined within this enum.
pub enum Value {
  Int(u32),
  Str(~str),
  Pair(~Value, ~Value)
}

impl Eq for Value {
  fn eq(&self, other: &Value) -> bool {
    match *self {
      Int(i) => {
        match *other {
          Int(ii) => i == i,
          _ => fail!("Invalid comparison.")
        }
      },
      Str(ref r) => {
        match *other {
          Str(ref s) => r == s,
          _ => fail!("Invalid comparison.")
        }
      },
      _ => fail!("Missing further `Eq` implementations.")
    }
  }
}

impl Show for Value {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    match *self {
      Int(i) => write!(f.buf, "({})", i),
      Str(ref s) => write!(f.buf, "({})", s),
      _ => write!(f.buf, "({})", *self )
    }
  }
}

/// A virtual machine that holds needed objects (gc, stack, etc...) and
/// the current state.
pub struct Vm {
  /// A global garbage collector.
  gc: Gc,

  /// Our small stack. For simplicity, we'll limit this to
  /// a static value.
  stack: ~[Value],

  /// Stack Size
  stack_size: u64
}

impl Vm {
  pub fn new() -> Vm {
    Vm {
      gc: Gc::new(),
      stack: ~[],
      stack_size: 0
    }
  }

  pub fn push(&mut self, val: Value) {
    self.stack.push(val);
    self.stack_size += 1;
  }

  pub fn pop(&mut self) -> Option<Value> {
    self.stack_size -= 1;
    self.stack.pop()
  }
}

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

  #[test]
  fn empty_stack_default() {
    let vm = Vm::new();
    assert_eq!(vm.stack_size, 0);
  }

  #[test]
  fn should_push_item() {
    let mut vm = Vm::new();
    let val = Str(~"Hello World");
    vm.push(val);
    assert_eq!(vm.stack_size, 1);
    assert_eq!(vm.stack[0], Str(~"Hello World"));
  }

}<|endoftext|>


<commit_before>// This code is heavily inspired by hoedown.

//
// Performance observations:
//
// Note that buf.head() == Some(&ch) is much faster than buf[0] == ch.
//

extern crate extra;
use extra::test::BenchHarness;

static SP: u8 = ' ' as u8;
static NL: u8 = '\n' as u8;
static STAR: u8 = '*' as u8;
static DASH: u8 = '-' as u8;
static UNDERSCORE: u8 = '_' as u8;

/// Return Some(`rem`) if the line is a horizontal rule, with `rem` being the
/// buf after the hrule. Otherwise return None.
fn is_hrule<'a>(buf: &'a[u8]) -> Option<&'a[u8]> {
    let mut buf = buf;

    // Skip up to three leading spaces.
    //
    // We don't need to care about tabs here as in this position they are
    // equivalent to 4 spaces, which means we would not parse this as a
    // hrule.
    if buf.head() == Some(&SP) { buf = buf.tail(); }
    if buf.head() == Some(&SP) { buf = buf.tail(); }
    if buf.head() == Some(&SP) { buf = buf.tail(); }

    let item = match buf.head() {
        Some(&c) if c == STAR ||
                    c == DASH ||
                    c == UNDERSCORE => c,
        _                           => return None
    };

    // The count of '*', '-' or '_'
    let mut cnt: uint = 0;

    // Counts the consumed spaces (and the final NL)
    let mut spc: uint = 0;

    for &ch in buf.iter() {
        if      ch == item { cnt += 1; }
        else if ch == NL   { spc += 1; break; }
        else if ch == SP   { spc += 1; }
        else               { return None; }
    }

    if cnt >= 3 {
        Some(buf.slice_from(cnt + spc))
    } else {
        None
    }
}

#[test]
fn test_is_hrule() {
    // examples as given on the markdown homepage
    assert!(is_hrule(bytes!("* * *\n")).is_some());
    assert!(is_hrule(bytes!("***\n")).is_some());
    assert!(is_hrule(bytes!("*****\n")).is_some());
    assert!(is_hrule(bytes!("- - -\n")).is_some());
    assert!(is_hrule(bytes!("---------------------------------------\n")).is_some());

    // up to three spaces ignored
    assert!(is_hrule(bytes!(" ***\n")).is_some());
    assert!(is_hrule(bytes!("  ***\n")).is_some());
    assert!(is_hrule(bytes!("   ***\n")).is_some());

    // but not four, or a tab which is equivalent to four spaces

    assert!(is_hrule(bytes!("    ***\n")).is_none());
    assert!(is_hrule(bytes!("\t***\n")).is_none());

    // need at least three
    assert!(is_hrule(bytes!("*\n")).is_none());
    assert!(is_hrule(bytes!("**\n")).is_none());
    assert!(is_hrule(bytes!("* *\n")).is_none());
    assert!(is_hrule(bytes!("   * *\n")).is_none());

    // Also works without newline at the end
    assert!(is_hrule(bytes!("* * *")).is_some());

    // And underscores also supported
    assert!(is_hrule(bytes!("___")).is_some());
    assert!(is_hrule(bytes!("______________")).is_some());
    assert!(is_hrule(bytes!(" ______________")).is_some());

    // Test if the remaining buf actually works.
    let s = bytes!("   * * *\nremaining");
    let res = is_hrule(s);
    assert!(res.is_some());
    assert_eq!(res.unwrap(), bytes!("remaining"));
}

#[bench]
fn bench_is_hrule(b: &mut BenchHarness) {
    let s = bytes!("   * * * * * * * * * * * * * * * *\n");
    b.iter(|| is_hrule(s));
}
<commit_msg>Add is_empty<commit_after>// This code is heavily inspired by hoedown.

//
// Performance observations:
//
// Note that buf.head() == Some(&ch) is much faster than buf[0] == ch.
//

extern crate extra;
use extra::test::BenchHarness;

static SP: u8 = ' ' as u8;
static NL: u8 = '\n' as u8;
static CR: u8 = '\r' as u8;
static TAB: u8 = '\t' as u8;
static STAR: u8 = '*' as u8;
static DASH: u8 = '-' as u8;
static UNDERSCORE: u8 = '_' as u8;

/// Return Some(`rem`) if the line is a horizontal rule, with `rem` being the
/// buf after the hrule. Otherwise return None.
fn is_hrule<'a>(buf: &'a[u8]) -> Option<&'a[u8]> {
    let mut buf = buf;

    // Skip up to three leading spaces.
    //
    // We don't need to care about tabs here as in this position they are
    // equivalent to 4 spaces, which means we would not parse this as a
    // hrule.
    if buf.head() == Some(&SP) { buf = buf.tail(); }
    if buf.head() == Some(&SP) { buf = buf.tail(); }
    if buf.head() == Some(&SP) { buf = buf.tail(); }

    let item = match buf.head() {
        Some(&c) if c == STAR ||
                    c == DASH ||
                    c == UNDERSCORE => c,
        _                           => return None
    };

    // The count of '*', '-' or '_'
    let mut cnt: uint = 0;

    // Counts the consumed spaces (and the final NL)
    let mut spc: uint = 0;

    for &ch in buf.iter() {
        if      ch == item { cnt += 1; }
        else if ch == NL   { spc += 1; break; }
        else if ch == SP   { spc += 1; }
        else               { return None; }
    }

    if cnt >= 3 {
        Some(buf.slice_from(cnt + spc))
    } else {
        None
    }
}

#[test]
fn test_is_hrule() {
    // examples as given on the markdown homepage
    assert!(is_hrule(bytes!("* * *\n")).is_some());
    assert!(is_hrule(bytes!("***\n")).is_some());
    assert!(is_hrule(bytes!("*****\n")).is_some());
    assert!(is_hrule(bytes!("- - -\n")).is_some());
    assert!(is_hrule(bytes!("---------------------------------------\n")).is_some());

    // up to three spaces ignored
    assert!(is_hrule(bytes!(" ***\n")).is_some());
    assert!(is_hrule(bytes!("  ***\n")).is_some());
    assert!(is_hrule(bytes!("   ***\n")).is_some());

    // but not four, or a tab which is equivalent to four spaces

    assert!(is_hrule(bytes!("    ***\n")).is_none());
    assert!(is_hrule(bytes!("\t***\n")).is_none());

    // need at least three
    assert!(is_hrule(bytes!("*\n")).is_none());
    assert!(is_hrule(bytes!("**\n")).is_none());
    assert!(is_hrule(bytes!("* *\n")).is_none());
    assert!(is_hrule(bytes!("   * *\n")).is_none());

    // Also works without newline at the end
    assert!(is_hrule(bytes!("* * *")).is_some());

    // And underscores also supported
    assert!(is_hrule(bytes!("___")).is_some());
    assert!(is_hrule(bytes!("______________")).is_some());
    assert!(is_hrule(bytes!(" ______________")).is_some());

    // Test if the remaining buf actually works.
    let s = bytes!("   * * *\nremaining");
    let res = is_hrule(s);
    assert!(res.is_some());
    assert_eq!(res.unwrap(), bytes!("remaining"));
}

#[bench]
fn bench_is_hrule(b: &mut BenchHarness) {
    let s = bytes!("   * * * * * * * * * * * * * * * *\n");
    b.iter(|| is_hrule(s));
}

/// Return Some(`rem`) if the line is an empty line, with `rem` being the buf
/// after the empty line. Otherwise return None.
fn is_empty<'a>(buf: &'a[u8]) -> Option<&'a[u8]> {
    let mut cnt: uint = 0;

    for &ch in buf.iter() {
        if      ch == NL  { cnt += 1; break; }
        else if ch == CR  { cnt += 1; }
        else if ch == SP  { cnt += 1; }
        else if ch == TAB { cnt += 1; }
        else              { return None; }
    }

    if cnt > 0 {
        Some(buf.slice_from(cnt))
    } else {
        None
    }
}

#[test]
fn test_is_empty() {
    assert!(is_empty(bytes!("\n")).is_some());
    assert!(is_empty(bytes!("    \n")).is_some());
    assert!(is_empty(bytes!("  \t  \n")).is_some());
    assert!(is_empty(bytes!("  \t  \r\n")).is_some());
    assert!(is_empty(bytes!("  \t  \nabc")).is_some());
    assert!(is_empty(bytes!("  \t  ")).is_some());

    assert!(is_empty(bytes!("a")).is_none());
    assert!(is_empty(bytes!(" a")).is_none());
    assert!(is_empty(bytes!(" a\n")).is_none());
    assert!(is_empty(bytes!(" \ta\n")).is_none());

    // Test if the remaining buf actually works.
    let s = bytes!("   \t\r\nremaining");
    let res = is_empty(s);
    assert!(res.is_some());
    assert_eq!(res.unwrap(), bytes!("remaining"));
}
<|endoftext|>


<commit_before><commit_msg>adds function to open device by VID/PID<commit_after><|endoftext|>


<commit_before>/// This is a doubly-linked list implementation with forward pointers being owners and backward
/// pointers being unsafe pointers. The goal is to write the unsafe code involving the backward
/// links as similarly as the safe code for the forward links to avoid rampant stupidity.

use std::borrow::Borrow;
use std::borrow::BorrowMut;
use std::iter::IntoIterator;
use std::ptr;

////////////////////////////////////////////////////////////////////////////////
// List implementation

pub struct List<T> {
    head: Link<T>,
    tail: LinkPtr<T>,
}

type Link<T> = Option<Box<Node<T>>>;
type LinkPtr<T> = *const Node<T>;

struct Node<T> {
    elem: T,
    next: Link<T>,
    prev: LinkPtr<T>,
}

////////////////////////////////////////////////////////////
// Referential equality helpers
//
// While Option<&T> is Copy, Option<&mut T> is not, so taking Options by reference for consistency.

fn eq_ref_opt<T>(ref1: &T, opt_ref2: &Option<&T>) -> bool {
    match opt_ref2 {
        // Need to convert to *const for referential equality.
        &Some(ref ref2) => ref1 as *const T == *ref2 as *const T,
        &None => false
    }
}

fn eq_mut_ref_opt<T>(ref1: &mut T, opt_ref2: &Option<&mut T>) -> bool {
    match opt_ref2 {
        // Need to convert to *const for referential equality.
        &Some(ref ref2) => ref1 as *const T == *ref2 as *const T,
        &None => false
    }
}

////////////////////////////////////////////////////////////
// Box to ptr conversion

trait BoxHelpers<T> {
    fn to_ptr(&self) -> *const T;
}

impl<T> BoxHelpers<T> for Box<T> {
    fn to_ptr(&self) -> *const T {
        Borrow::<T>::borrow(self) as *const T
    }
}

////////////////////////////////////////////////////////////
/// Doubly-linked list

impl<T> List<T> {
    pub fn new() -> Self {
        List { head: None, tail: ptr::null() }
    }

    // PUSH
    pub fn push_front(&mut self, elem: T) {
        let mut node_box = Box::new(Node {
            elem: elem,
            next: self.head.take(),
            prev: ptr::null()
        });
        let node_ptr = node_box.to_ptr();
        match node_box.next.as_mut() { // What self.head used to be before it was take()n above.
            None => self.tail = node_ptr,
            Some(old_head_ref) => old_head_ref.prev = node_ptr
        }
        self.head = Some(node_box);
    }

    pub fn push_back(&mut self, elem: T) {
        let node_box = Box::new(Node {
            elem: elem,
            next: None,
            prev: self.tail
        });
        let node_ptr = node_box.to_ptr();
        if self.tail == ptr::null() {
            self.head = Some(node_box);
        } else {
            unsafe { (*(self.tail as *mut Node<T>)).next = Some(node_box) }
        }
        self.tail = node_ptr;
    }

    // POP
    pub fn pop_front(&mut self) -> Option<T> {
        self.head.take().map(|node_box| {
            let node = *node_box;
            self.head = node.next;
            // INCOMPLETE handling of pointer part, causing test_push_pop_crash() to panic
            //if self.head.is_none() {
            //    self.tail = ptr::null()
            //}
            // CORRECT handling of pointer part!
            match self.head.as_mut() {
                None => self.tail = ptr::null(),
                Some(node_box) => node_box.prev = ptr::null()
            }
            node.elem
        })
    }

    pub fn pop_back(&mut self) -> Option<T> {
        if self.tail == ptr::null() {
            return None;
        }
        self.tail = unsafe { (*self.tail).prev };
        let node_opt = if self.tail == ptr::null() {
                self.head.take()
            } else {
                unsafe { (*(self.tail as *mut Node<T>)).next.take() }
            };
        Some(node_opt.unwrap().elem) // Ideally, should use unwrap_unchecked().
    }

    // PEEK
    pub fn peek_front(&self) -> Option<&T> {
        self.head.as_ref().map(|node| { &node.elem })
    }

    pub fn peek_back(&self) -> Option<&T> {
        if self.tail == ptr::null() {
            None
        } else {
            Some(unsafe { &(*self.tail).elem })
        }
    }

    // PEEK MUT
    pub fn peek_front_mut(&mut self) -> Option<&mut T> {
        self.head.as_mut().map(|node| { &mut node.elem })
    }

    pub fn peek_back_mut(&mut self) -> Option<&mut T> {
        if self.tail == ptr::null() {
            None
        } else {
            Some(unsafe { &mut (*(self.tail as *mut Node<T>)).elem })
        }
    }

    // ITER
    pub fn iter(&self) -> Iter<T> {
        Iter {
            front_link: self.head.as_ref().map(|node_box| node_box.borrow()),
            back_link: if self.tail == ptr::null() { None } else {
                Some(unsafe { &*self.tail })
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// By-reference Iter

pub struct Iter<'a, T: 'a> {
    front_link: Option<&'a Node<T>>,
    back_link: Option<&'a Node<T>>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        self.front_link.take().map(|node_ref| {
            if eq_ref_opt(node_ref, &self.back_link) { // If both ends collide, be DONE!
                self.front_link = None;
                self.back_link = None;
            } else {
                self.front_link = node_ref.next.as_ref().map(|node_box| node_box.borrow())
            }
            &node_ref.elem
        })
    }
}

impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.back_link.take().map(|node_ref| {
            if eq_ref_opt(node_ref, &self.front_link) { // If both ends collide, be DONE!
                self.front_link = None;
                self.back_link = None;
            } else {
                self.back_link = Some(unsafe { &*node_ref.prev })
            }
            &node_ref.elem
        })
    }
}

////////////////////////////////////////////////////////////////////////////////
// IntoIterator

pub struct ListIntoIterator<T> {
    list: List<T>,
}

impl<T> Iterator for ListIntoIterator<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.list.pop_front()
    }
}

impl<T> DoubleEndedIterator for ListIntoIterator<T> {
    fn next_back(&mut self) -> Option<T> {
        self.list.pop_back()
    }
}

impl<T> IntoIterator for List<T> {
    type Item = T;
    type IntoIter = ListIntoIterator<T>;

    fn into_iter(self) -> ListIntoIterator<T> {
        ListIntoIterator { list: self }
    }
}

impl<'a, T> IntoIterator for &'a List<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

////////////////////////////////////////////////////////////////////////////////

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

    #[test]
    fn test_push_pop_front() {
        let mut list = List::new();
        list.push_front(1);
        assert_eq!(Some(&1), list.peek_front());
        list.push_front(2);
        assert_eq!(Some(&2), list.peek_front());
        list.push_front(3);
        assert_eq!(Some(&3), list.peek_front());
        assert_eq!(Some(3), list.pop_front());
        assert_eq!(Some(2), list.pop_front());
        assert_eq!(Some(1), list.pop_front());
        assert_eq!(None, list.pop_front());
    }

    #[test]
    fn test_push_pop_back() {
        let mut list = List::new();
        list.push_back(1);
        assert_eq!(Some(&1), list.peek_back());
        list.push_back(2);
        assert_eq!(Some(&2), list.peek_back());
        list.push_back(3);
        assert_eq!(Some(&3), list.peek_back());
        assert_eq!(Some(3), list.pop_back());
        assert_eq!(Some(2), list.pop_back());
        assert_eq!(Some(1), list.pop_back());
        assert_eq!(None, list.pop_back());
    }

    #[test]
    fn test_push_pop_both() {
        let mut list = List::new();
        list.push_back(2);
        assert_eq!(Some(&2), list.peek_back());
        list.push_front(1);
        assert_eq!(Some(&1), list.peek_front());
        assert_eq!(Some(&2), list.peek_back());
        list.push_back(3);
        assert_eq!(Some(&1), list.peek_front());
        assert_eq!(Some(&3), list.peek_back());
        assert_eq!(Some(3), list.pop_back());
        assert_eq!(Some(1), list.pop_front());
        assert_eq!(Some(2), list.pop_front());
        assert_eq!(None, list.pop_front());
        assert_eq!(None, list.pop_back());
    }

    #[test]
    fn test_push_pop_crash() {
        let mut list = List::new();
        list.push_front(1);
        list.push_front(2);
        list.push_front(3);
        let mut i = 3;
        for val in list {
            assert_eq!(i, val);
            i -= 1;
        }

        let mut list = List::new();
        list.push_back(1);
        list.push_back(2);
        list.push_back(3);
        assert_eq!(Some(1), list.pop_front());
        assert_eq!(Some(3), list.pop_back());
        assert_eq!(Some(2), list.pop_back());
        assert_eq!(None, list.pop_front());
        assert_eq!(None, list.pop_back());
    }

    #[test]
    fn test_into_iter() {
        let mut list = List::new();
        list.push_front(1);
        list.push_front(2);
        list.push_front(3);
        let mut i = 3;
        for val in list {
            assert_eq!(i, val);
            i -= 1;
        }

        let mut list = List::new();
        list.push_back(1);
        list.push_back(2);
        list.push_back(3);
        let mut iter = list.into_iter();
        assert_eq!(Some(1), iter.next());
        assert_eq!(Some(3), iter.next_back());
        assert_eq!(Some(2), iter.next_back());
        assert_eq!(None, iter.next());
        assert_eq!(None, iter.next_back());
    }

    #[test]
    fn test_iter() {
        let mut list = List::new();
        list.push_back(1);
        list.push_back(2);
        list.push_back(3);
        let mut iter = list.iter();
        assert_eq!(Some(&1), iter.next());
        assert_eq!(Some(&3), iter.next_back());
        assert_eq!(Some(&2), iter.next_back());
        assert_eq!(None, iter.next());
        assert_eq!(None, iter.next_back());

        let mut iter = list.iter();
        assert_eq!(Some(&3), iter.next_back());
        assert_eq!(Some(&1), iter.next());
        assert_eq!(Some(&2), iter.next());
        assert_eq!(None, iter.next());
        assert_eq!(None, iter.next_back());

        let mut i = 1;
        for val in &list {
            assert_eq!(i, *val);
            i += 1;
        }
    }
}

<commit_msg>Doubly-linked list: Made front and back code congruous.<commit_after>/// This is a doubly-linked list implementation with forward pointers being owners and backward
/// pointers being unsafe pointers. The goal is to write the unsafe code involving the backward
/// links as similarly as the safe code for the forward links to avoid rampant stupidity.

use std::borrow::Borrow;
use std::borrow::BorrowMut;
use std::iter::IntoIterator;
use std::ptr;

////////////////////////////////////////////////////////////////////////////////
// List implementation

pub struct List<T> {
    head: Link<T>,
    tail: LinkPtr<T>,
}

type Link<T> = Option<Box<Node<T>>>;
type LinkPtr<T> = *const Node<T>;

struct Node<T> {
    elem: T,
    next: Link<T>,
    prev: LinkPtr<T>,
}

////////////////////////////////////////////////////////////
// Referential equality helpers
//
// While Option<&T> is Copy, Option<&mut T> is not, so taking Options by reference for consistency.

fn eq_ref_opt<T>(ref1: &T, opt_ref2: &Option<&T>) -> bool {
    match opt_ref2 {
        // Need to convert to *const for referential equality.
        &Some(ref ref2) => ref1 as *const T == *ref2 as *const T,
        &None => false
    }
}

fn eq_mut_ref_opt<T>(ref1: &mut T, opt_ref2: &Option<&mut T>) -> bool {
    match opt_ref2 {
        // Need to convert to *const for referential equality.
        &Some(ref ref2) => ref1 as *const T == *ref2 as *const T,
        &None => false
    }
}

////////////////////////////////////////////////////////////
// Box to ptr conversion

trait BoxHelpers<T> {
    fn to_ptr(&self) -> *const T;
}

impl<T> BoxHelpers<T> for Box<T> {
    fn to_ptr(&self) -> *const T {
        Borrow::<T>::borrow(self) as *const T
    }
}

////////////////////////////////////////////////////////////
// Conversions to Option<&>

trait OptionRef<T> {
    fn to_ref(&self) -> Option<&T>;
    fn to_mut(&mut self) -> Option<&mut T>;
}

// Option<Box> -> Option<&>. In fact, can be used instead of as_ref() and as_mut() in most places.
impl<T, B: Borrow<T> + BorrowMut<T>> OptionRef<T> for Option<B> {
    fn to_ref(&self) -> Option<&T> {
        self.as_ref().take().map(|borrowable| {borrowable.borrow()})
    }
    fn to_mut(&mut self) -> Option<&mut T> {
        self.as_mut().take().map(|borrowable| {borrowable.borrow_mut()})
    }
}

// Make unsafe pointers behave similar to Option<Box> above. This is unsafe because the output
// reference isn't unbounded and the caller is responsible for bounding it appropriately.
trait UnsafeOptionRef<T> {
    unsafe fn to_ref<'b>(self) -> Option<&'b T>;
    unsafe fn to_mut<'b>(self) -> Option<&'b mut T>;
}

impl<T> UnsafeOptionRef<T> for *const T {
    unsafe fn to_ref<'b>(self) -> Option<&'b T> {
        match self as usize {
            0 => None,
            _ => Some(&*self)
        }
    }
    unsafe fn to_mut<'b>(self) -> Option<&'b mut T> {
        match self as usize {
            0 => None,
            _ => Some(&mut *(self as *mut _))
        }
    }
}

////////////////////////////////////////////////////////////
/// Doubly-linked list

impl<T> List<T> {
    pub fn new() -> Self {
        List { head: None, tail: ptr::null() }
    }

    // PUSH
    pub fn push_front(&mut self, elem: T) {
        let mut node_box = Box::new(Node {
            elem: elem,
            next: self.head.take(),
            prev: ptr::null()
        });
        let node_ptr = node_box.to_ptr();
        match node_box.next.as_mut() { // What self.head used to be before it was take()n above.
            None => self.tail = node_ptr,
            Some(old_head_ref) => old_head_ref.prev = node_ptr
        }
        self.head = Some(node_box);
    }

    pub fn push_back(&mut self, elem: T) {
        let node_box = Box::new(Node {
            elem: elem,
            next: None,
            prev: self.tail
        });
        let node_ptr = node_box.to_ptr();
        match unsafe { self.tail.to_mut() } {
            None => self.head = Some(node_box),
            Some(old_tail_ref) => old_tail_ref.next = Some(node_box)
        }
        self.tail = node_ptr;
    }

    // POP
    pub fn pop_front(&mut self) -> Option<T> {
        self.head.take().map(|node_box| {
            let node = *node_box;
            self.head = node.next;
            match self.head.as_mut() {
                None => self.tail = ptr::null(),
                Some(node_box) => node_box.prev = ptr::null()
            }
            node.elem
        })
    }

    pub fn pop_back(&mut self) -> Option<T> {
        // Subtle differences with pop_front() are primarily because the disconnection from the
        // owner via take() happens later.
        unsafe { self.tail.to_ref() }.map(|node_ref| {
            self.tail = node_ref.prev;
            let node_opt = match unsafe { self.tail.to_mut() } {
                None => self.head.take(),
                Some(node_ref) => node_ref.next.take()
            };
            node_opt.unwrap().elem // Ideally, should use unwrap_unchecked().
        })
    }

    // PEEK
    pub fn peek_front(&self) -> Option<&T> {
        self.head.as_ref().map(|node| { &node.elem })
    }

    pub fn peek_back(&self) -> Option<&T> {
        unsafe { self.tail.to_ref() }.map(|node| { &node.elem })
    }

    // PEEK MUT
    pub fn peek_front_mut(&mut self) -> Option<&mut T> {
        self.head.as_mut().map(|node| { &mut node.elem })
    }

    pub fn peek_back_mut(&mut self) -> Option<&mut T> {
        unsafe { self.tail.to_mut() }.map(|node| { &mut node.elem })
    }

    // ITER
    pub fn iter(&self) -> Iter<T> {
        Iter {
            front_link: self.head.to_ref(),
            back_link: unsafe { self.tail.to_ref() }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// By-reference Iter

pub struct Iter<'a, T: 'a> {
    front_link: Option<&'a Node<T>>,
    back_link: Option<&'a Node<T>>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        self.front_link.take().map(|node_ref| {
            if eq_ref_opt(node_ref, &self.back_link) { // If both ends collide, be DONE!
                self.front_link = None;
                self.back_link = None;
            } else {
                self.front_link = node_ref.next.to_ref()
            }
            &node_ref.elem
        })
    }
}

impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.back_link.take().map(|node_ref| {
            if eq_ref_opt(node_ref, &self.front_link) { // If both ends collide, be DONE!
                self.front_link = None;
                self.back_link = None;
            } else {
                self.back_link = unsafe { node_ref.prev.to_ref() }
            }
            &node_ref.elem
        })
    }
}

////////////////////////////////////////////////////////////////////////////////
// IntoIterator

pub struct ListIntoIterator<T> {
    list: List<T>,
}

impl<T> Iterator for ListIntoIterator<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.list.pop_front()
    }
}

impl<T> DoubleEndedIterator for ListIntoIterator<T> {
    fn next_back(&mut self) -> Option<T> {
        self.list.pop_back()
    }
}

impl<T> IntoIterator for List<T> {
    type Item = T;
    type IntoIter = ListIntoIterator<T>;

    fn into_iter(self) -> ListIntoIterator<T> {
        ListIntoIterator { list: self }
    }
}

impl<'a, T> IntoIterator for &'a List<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

////////////////////////////////////////////////////////////////////////////////

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

    #[test]
    fn test_push_pop_front() {
        let mut list = List::new();
        list.push_front(1);
        assert_eq!(Some(&1), list.peek_front());
        list.push_front(2);
        assert_eq!(Some(&2), list.peek_front());
        list.push_front(3);
        assert_eq!(Some(&3), list.peek_front());
        assert_eq!(Some(3), list.pop_front());
        assert_eq!(Some(2), list.pop_front());
        assert_eq!(Some(1), list.pop_front());
        assert_eq!(None, list.pop_front());
    }

    #[test]
    fn test_push_pop_back() {
        let mut list = List::new();
        list.push_back(1);
        assert_eq!(Some(&1), list.peek_back());
        list.push_back(2);
        assert_eq!(Some(&2), list.peek_back());
        list.push_back(3);
        assert_eq!(Some(&3), list.peek_back());
        assert_eq!(Some(3), list.pop_back());
        assert_eq!(Some(2), list.pop_back());
        assert_eq!(Some(1), list.pop_back());
        assert_eq!(None, list.pop_back());
    }

    #[test]
    fn test_push_pop_both() {
        let mut list = List::new();
        list.push_back(2);
        assert_eq!(Some(&2), list.peek_back());
        list.push_front(1);
        assert_eq!(Some(&1), list.peek_front());
        assert_eq!(Some(&2), list.peek_back());
        list.push_back(3);
        assert_eq!(Some(&1), list.peek_front());
        assert_eq!(Some(&3), list.peek_back());
        assert_eq!(Some(3), list.pop_back());
        assert_eq!(Some(1), list.pop_front());
        assert_eq!(Some(2), list.pop_front());
        assert_eq!(None, list.pop_front());
        assert_eq!(None, list.pop_back());
    }

    #[test]
    fn test_push_pop_crash() {
        let mut list = List::new();
        list.push_front(1);
        list.push_front(2);
        list.push_front(3);
        let mut i = 3;
        for val in list {
            assert_eq!(i, val);
            i -= 1;
        }

        let mut list = List::new();
        list.push_back(1);
        list.push_back(2);
        list.push_back(3);
        assert_eq!(Some(1), list.pop_front());
        assert_eq!(Some(3), list.pop_back());
        assert_eq!(Some(2), list.pop_back());
        assert_eq!(None, list.pop_front());
        assert_eq!(None, list.pop_back());
    }

    #[test]
    fn test_into_iter() {
        let mut list = List::new();
        list.push_front(1);
        list.push_front(2);
        list.push_front(3);
        let mut i = 3;
        for val in list {
            assert_eq!(i, val);
            i -= 1;
        }

        let mut list = List::new();
        list.push_back(1);
        list.push_back(2);
        list.push_back(3);
        let mut iter = list.into_iter();
        assert_eq!(Some(1), iter.next());
        assert_eq!(Some(3), iter.next_back());
        assert_eq!(Some(2), iter.next_back());
        assert_eq!(None, iter.next());
        assert_eq!(None, iter.next_back());
    }

    #[test]
    fn test_iter() {
        let mut list = List::new();
        list.push_back(1);
        list.push_back(2);
        list.push_back(3);
        let mut iter = list.iter();
        assert_eq!(Some(&1), iter.next());
        assert_eq!(Some(&3), iter.next_back());
        assert_eq!(Some(&2), iter.next_back());
        assert_eq!(None, iter.next());
        assert_eq!(None, iter.next_back());

        let mut iter = list.iter();
        assert_eq!(Some(&3), iter.next_back());
        assert_eq!(Some(&1), iter.next());
        assert_eq!(Some(&2), iter.next());
        assert_eq!(None, iter.next());
        assert_eq!(None, iter.next_back());

        let mut i = 1;
        for val in &list {
            assert_eq!(i, *val);
            i += 1;
        }
    }
}

<|endoftext|>


<commit_before>use std::path::PathBuf;

use anyhow::{bail, Context, Result};
use async_std::io::{Read, Write};
use async_std::net::{TcpListener, TcpStream};
use async_std::os::unix::net::{UnixListener, UnixStream};
use async_tls::TlsAcceptor;
use async_trait::async_trait;

use crate::settings::Settings;
use crate::state::SharedState;
use crate::tls::{get_tls_connector, get_tls_listener};

/// A new trait, which can be used to represent Unix- and TcpListeners.
/// This is necessary to easily write generic functions where both types can be used.
#[async_trait]
pub trait GenericListener: Sync + Send {
    async fn accept<'a>(&'a self) -> Result<GenericStream>;
}

/// This is a helper struct for TCP connections.
/// TCP should always be used in conjunction with TLS.
/// That's why we create a intermediate struct, which will encapsulate the logic of accepting a new
/// connection and initializing the TLS layer on top of it.
/// To the outside, it will just look like another GenericListener
pub struct TlsTcpListener {
    tcp_listener: TcpListener,
    tls_acceptor: TlsAcceptor,
}

#[async_trait]
impl GenericListener for TlsTcpListener {
    async fn accept<'a>(&'a self) -> Result<GenericStream> {
        let (stream, _) = self.tcp_listener.accept().await?;
        Ok(Box::new(self.tls_acceptor.accept(stream).await?))
    }
}

#[async_trait]
impl GenericListener for UnixListener {
    async fn accept<'a>(&'a self) -> Result<GenericStream> {
        let (stream, _) = self.accept().await?;
        Ok(Box::new(stream))
    }
}

/// A new trait, which can be used to represent Unix- and Tls encrypted TcpStreams.
/// This is necessary to write generic functions where both types can be used.
pub trait Stream: Read + Write + Unpin + Send {}
impl Stream for UnixStream {}
impl Stream for async_tls::server::TlsStream<TcpStream> {}
impl Stream for async_tls::client::TlsStream<TcpStream> {}

/// Two convenient types, so we don't have type write Box<dyn ...> all the time.
pub type Listener = Box<dyn GenericListener>;
pub type GenericStream = Box<dyn Stream>;

/// Get a new stream for the client.
/// This can either be a UnixStream or a Tls encrypted TCPStream, depending on the parameters.
pub async fn get_client_stream(settings: &Settings) -> Result<GenericStream> {
    let unix_socket_path = &settings.shared.unix_socket_path;
    // Don't allow anything else than loopback until we have proper crypto
    let host = "127.0.0.1";
    let port = &settings.shared.port;

    // Create a unix socket, if the config says so.
    if settings.shared.use_unix_socket {
        if !PathBuf::from(unix_socket_path).exists() {
            bail!(
                "Couldn't find unix socket at path {:?}. Is the daemon running yet?",
                unix_socket_path
            );
        }
        let stream = UnixStream::connect(unix_socket_path).await?;
        return Ok(Box::new(stream));
    }

    // Connect to the daemon via TCP
    let address = format!("{}:{}", host, port);
    let tcp_stream = TcpStream::connect(&address).await.context(format!(
        "Failed to connect to the daemon on {}. Did you start it?",
        &address
    ))?;

    // Initialize the TLS layer
    let tls_connector = get_tls_connector(&settings)
        .await
        .context("Failed to initialize TLS Connector")?;

    let stream = tls_connector
        .connect("pueue.local", tcp_stream)
        .await
        .context("Failed to initialize TLS stream")?;

    Ok(Box::new(stream))
}

/// Get a new listener for the daemon.
/// This can either be a UnixListener or a TCPlistener,
/// which depends on the parameters.
pub async fn get_listener(state: &SharedState) -> Result<Listener> {
    let state = state.lock().unwrap();

    let unix_socket_path = &state.settings.shared.unix_socket_path;
    // Don't allow anything else than loopback until we have proper crypto
    let host = "127.0.0.1";
    let port = &state.settings.shared.port;

    if state.settings.shared.use_unix_socket {
        // Check, if the socket already exists
        // In case it does, we have to check, if it's an active socket.
        // If it is, we have to throw an error, because another daemon is already running.
        // Otherwise, we can simply remove it.
        if PathBuf::from(unix_socket_path).exists() {
            if get_client_stream(&state.settings).await.is_ok() {
                bail!(
                    "There seems to be an active pueue daemon.\n\
                      If you're sure there isn't, please remove the socket by hand \
                      inside the pueue_directory."
                );
            }

            std::fs::remove_file(unix_socket_path)?;
        }

        return Ok(Box::new(UnixListener::bind(unix_socket_path).await?));
    }

    let tls_acceptor = get_tls_listener(&state.settings)?;
    let address = format!("{}:{}", host, port);
    let tcp_listener = TcpListener::bind(address).await?;

    // Create a list, which accepts connections and initializes a TLS layer.
    let tls_listener = TlsTcpListener {
        tcp_listener,
        tls_acceptor,
    };

    Ok(Box::new(tls_listener))
}
<commit_msg>Comments and minor code restructurings<commit_after>use std::path::PathBuf;

use anyhow::{bail, Context, Result};
use async_std::io::{Read, Write};
use async_std::net::{TcpListener, TcpStream};
use async_std::os::unix::net::{UnixListener, UnixStream};
use async_tls::TlsAcceptor;
use async_trait::async_trait;

use crate::settings::Settings;
use crate::state::SharedState;
use crate::tls::{get_tls_connector, get_tls_listener};

/// A new trait, which can be used to represent Unix- and TcpListeners.
/// This is necessary to easily write generic functions where both types can be used.
#[async_trait]
pub trait GenericListener: Sync + Send {
    async fn accept<'a>(&'a self) -> Result<GenericStream>;
}

/// This is a helper struct for TCP connections.
/// TCP should always be used in conjunction with TLS.
/// That's why this helper exists, which encapsulates the logic of accepting a new
/// connection and initializing the TLS layer on top of it.
/// This way we can expose an `accept` function and implement the GenericListener trait.
pub struct TlsTcpListener {
    tcp_listener: TcpListener,
    tls_acceptor: TlsAcceptor,
}

#[async_trait]
impl GenericListener for TlsTcpListener {
    async fn accept<'a>(&'a self) -> Result<GenericStream> {
        let (stream, _) = self.tcp_listener.accept().await?;
        Ok(Box::new(self.tls_acceptor.accept(stream).await?))
    }
}

#[async_trait]
impl GenericListener for UnixListener {
    async fn accept<'a>(&'a self) -> Result<GenericStream> {
        let (stream, _) = self.accept().await?;
        Ok(Box::new(stream))
    }
}

/// A new trait, which can be used to represent Unix- and Tls encrypted TcpStreams.
/// This is necessary to write generic functions where both types can be used.
pub trait Stream: Read + Write + Unpin + Send {}
impl Stream for UnixStream {}
impl Stream for async_tls::server::TlsStream<TcpStream> {}
impl Stream for async_tls::client::TlsStream<TcpStream> {}

/// Two convenient types, so we don't have type write Box<dyn ...> all the time.
pub type Listener = Box<dyn GenericListener>;
pub type GenericStream = Box<dyn Stream>;

/// Get a new stream for the client.
/// This can either be a UnixStream or a Tls encrypted TCPStream, depending on the parameters.
pub async fn get_client_stream(settings: &Settings) -> Result<GenericStream> {
    let unix_socket_path = &settings.shared.unix_socket_path;

    // Create a unix socket, if the config says so.
    if settings.shared.use_unix_socket {
        if !PathBuf::from(unix_socket_path).exists() {
            bail!(
                "Couldn't find unix socket at path {:?}. Is the daemon running yet?",
                unix_socket_path
            );
        }
        let stream = UnixStream::connect(unix_socket_path).await?;
        return Ok(Box::new(stream));
    }

    // Don't allow anything else than loopback until we have proper crypto
    let host = "127.0.0.1";
    let port = &settings.shared.port;
    let address = format!("{}:{}", host, port);

    // Connect to the daemon via TCP
    let tcp_stream = TcpStream::connect(&address).await.context(format!(
        "Failed to connect to the daemon on {}. Did you start it?",
        &address
    ))?;

    // Get the configured rustls TlsConnector
    let tls_connector = get_tls_connector(&settings)
        .await
        .context("Failed to initialize TLS Connector")?;

    // Initialize the TLS layer
    let stream = tls_connector
        .connect("pueue.local", tcp_stream)
        .await
        .context("Failed to initialize TLS stream")?;

    Ok(Box::new(stream))
}

/// Get a new listener for the daemon.
/// This can either be a UnixListener or a TCPlistener,
/// which depends on the parameters.
pub async fn get_listener(state: &SharedState) -> Result<Listener> {
    let state = state.lock().unwrap();

    let unix_socket_path = &state.settings.shared.unix_socket_path;
    if state.settings.shared.use_unix_socket {
        // Check, if the socket already exists
        // In case it does, we have to check, if it's an active socket.
        // If it is, we have to throw an error, because another daemon is already running.
        // Otherwise, we can simply remove it.
        if PathBuf::from(unix_socket_path).exists() {
            if get_client_stream(&state.settings).await.is_ok() {
                bail!(
                    "There seems to be an active pueue daemon.\n\
                      If you're sure there isn't, please remove the socket by hand \
                      inside the pueue_directory."
                );
            }

            std::fs::remove_file(unix_socket_path)?;
        }

        return Ok(Box::new(UnixListener::bind(unix_socket_path).await?));
    }

    // Don't allow anything else than loopback until we have proper crypto
    let host = "127.0.0.1";
    let port = &state.settings.shared.port;

    let tls_acceptor = get_tls_listener(&state.settings)?;
    let address = format!("{}:{}", host, port);
    let tcp_listener = TcpListener::bind(address).await?;

    // Create a struct, which accepts connections and initializes a TLS layer in one go.
    let tls_listener = TlsTcpListener {
        tcp_listener,
        tls_acceptor,
    };

    Ok(Box::new(tls_listener))
}
<|endoftext|>


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

use super::XConnection;

#[derive(Clone)]
pub struct MonitorId {
    /// The actual id
    id: u32,
    /// The name of the monitor
    name: String,
    /// The size of the monitor
    dimensions: (u32, u32),
    /// The position of the monitor in the X screen
    position: (i32, i32),
    /// If the monitor is the primary one
    primary: bool,
}

pub fn get_available_monitors(x: &Arc<XConnection>) -> Vec<MonitorId> {
    let mut available = Vec::new();
    unsafe {
        let root = (x.xlib.XDefaultRootWindow)(x.display);
        let resources = (x.xrandr.XRRGetScreenResources)(x.display, root);

        let mut major = 0;
        let mut minor = 0;
        (x.xrandr.XRRQueryVersion)(x.display, &mut major, &mut minor);
        if ((major as u64)<<32)+(minor as u64) >= (1<<32)+5 {
            // We're in XRandR >= 1.5, enumerate Monitors to handle things like MST and videowalls
            let mut nmonitors = 0;
            let monitors = (x.xrandr.XRRGetMonitors)(x.display, root, 1, &mut nmonitors);
            for i in 0..nmonitors {
                let monitor = *(monitors.offset(i as isize));
                let output = (x.xrandr.XRRGetOutputInfo)(x.display, resources, *(monitor.outputs.offset(0)));
                let nameslice = slice::from_raw_parts((*output).name as *mut u8, (*output).nameLen as usize);
                let name = String::from_utf8_lossy(nameslice).into_owned();
                (x.xrandr.XRRFreeOutputInfo)(output);
                available.push(MonitorId{
                    id: i as u32,
                    name,
                    dimensions: (monitor.width as u32, monitor.height as u32),
                    position: (monitor.x as i32, monitor.y as i32),
                    primary: (monitor.primary != 0),
                });
            }
            (x.xrandr.XRRFreeMonitors)(monitors);
        } else {
            // We're in XRandR < 1.5, enumerate CRTCs. Everything will work but MST and
            // videowall setups will show more monitors than the logical groups the user
            // cares about
            for i in 0..(*resources).ncrtc {
                let crtcid = *((*resources).crtcs.offset(i as isize));
                let crtc = (x.xrandr.XRRGetCrtcInfo)(x.display, resources, crtcid);
                if (*crtc).width > 0 && (*crtc).height > 0 && (*crtc).noutput > 0 {
                    let output = (x.xrandr.XRRGetOutputInfo)(x.display, resources, *((*crtc).outputs.offset(0)));
                    let nameslice = slice::from_raw_parts((*output).name as *mut u8, (*output).nameLen as usize);
                    let name = String::from_utf8_lossy(nameslice).into_owned();
                    (x.xrandr.XRRFreeOutputInfo)(output);
                    available.push(MonitorId{
                        id: crtcid as u32,
                        name,
                        dimensions: ((*crtc).width as u32, (*crtc).height as u32),
                        position: ((*crtc).x as i32, (*crtc).y as i32),
                        primary: true,
                    });
                }
                (x.xrandr.XRRFreeCrtcInfo)(crtc);
            }
        }
        (x.xrandr.XRRFreeScreenResources)(resources);
    }
    available
}

#[inline]
pub fn get_primary_monitor(x: &Arc<XConnection>) -> MonitorId {
    get_available_monitors(x).into_iter().find(|m| m.primary)
        // 'no primary' case is better handled picking some existing monitor
        .or_else(|| get_available_monitors(x).into_iter().next())
        .expect("[winit] Failed to find any x11 monitor")
}

impl MonitorId {
    pub fn get_name(&self) -> Option<String> {
        Some(self.name.clone())
    }

    #[inline]
    pub fn get_native_identifier(&self) -> u32 {
        self.id as u32
    }

    pub fn get_dimensions(&self) -> (u32, u32) {
        self.dimensions
    }

    pub fn get_position(&self) -> (i32, i32) {
        self.position
    }

    #[inline]
    pub fn get_hidpi_factor(&self) -> f32 {
        1.0
    }
}
<commit_msg>Implement hidpi factor for x11 MonitorId (#387)<commit_after>use std::sync::Arc;
use std::slice;

use super::XConnection;

#[derive(Clone)]
pub struct MonitorId {
    /// The actual id
    id: u32,
    /// The name of the monitor
    name: String,
    /// The size of the monitor
    dimensions: (u32, u32),
    /// The position of the monitor in the X screen
    position: (i32, i32),
    /// If the monitor is the primary one
    primary: bool,
    /// The DPI scaling factor
    hidpi_factor: f32,
}

pub fn get_available_monitors(x: &Arc<XConnection>) -> Vec<MonitorId> {
    let mut available = Vec::new();
    unsafe {
        let root = (x.xlib.XDefaultRootWindow)(x.display);
        let resources = (x.xrandr.XRRGetScreenResources)(x.display, root);

        let mut major = 0;
        let mut minor = 0;
        (x.xrandr.XRRQueryVersion)(x.display, &mut major, &mut minor);
        if ((major as u64)<<32)+(minor as u64) >= (1<<32)+5 {
            // We're in XRandR >= 1.5, enumerate Monitors to handle things like MST and videowalls
            let mut nmonitors = 0;
            let monitors = (x.xrandr.XRRGetMonitors)(x.display, root, 1, &mut nmonitors);
            for i in 0..nmonitors {
                let monitor = *(monitors.offset(i as isize));
                let output = (x.xrandr.XRRGetOutputInfo)(x.display, resources, *(monitor.outputs.offset(0)));
                let nameslice = slice::from_raw_parts((*output).name as *mut u8, (*output).nameLen as usize);
                let name = String::from_utf8_lossy(nameslice).into_owned();
                let hidpi_factor = {
                    let x_mm = (*output).mm_width as f32;
                    let y_mm = (*output).mm_height as f32;
                    let x_px = monitor.width as f32;
                    let y_px = monitor.height as f32;
                    let ppmm = ((x_px * y_px) / (x_mm * y_mm)).sqrt();

                    // Quantize 1/12 step size
                    ((ppmm * (12.0 * 25.4 / 96.0)).round() / 12.0).max(1.0)
                };
                (x.xrandr.XRRFreeOutputInfo)(output);
                available.push(MonitorId{
                    id: i as u32,
                    name,
                    hidpi_factor,
                    dimensions: (monitor.width as u32, monitor.height as u32),
                    position: (monitor.x as i32, monitor.y as i32),
                    primary: (monitor.primary != 0),
                });
            }
            (x.xrandr.XRRFreeMonitors)(monitors);
        } else {
            // We're in XRandR < 1.5, enumerate CRTCs. Everything will work but MST and
            // videowall setups will show more monitors than the logical groups the user
            // cares about
            for i in 0..(*resources).ncrtc {
                let crtcid = *((*resources).crtcs.offset(i as isize));
                let crtc = (x.xrandr.XRRGetCrtcInfo)(x.display, resources, crtcid);
                if (*crtc).width > 0 && (*crtc).height > 0 && (*crtc).noutput > 0 {
                    let output = (x.xrandr.XRRGetOutputInfo)(x.display, resources, *((*crtc).outputs.offset(0)));
                    let nameslice = slice::from_raw_parts((*output).name as *mut u8, (*output).nameLen as usize);
                    let name = String::from_utf8_lossy(nameslice).into_owned();

                    let hidpi_factor = {
                        let x_mm = (*output).mm_width as f32;
                        let y_mm = (*output).mm_height as f32;
                        let x_px = (*crtc).width as f32;
                        let y_px = (*crtc).height as f32;
                        let ppmm = ((x_px * y_px) / (x_mm * y_mm)).sqrt();

                        // Quantize 1/12 step size
                        ((ppmm * (12.0 * 25.4 / 96.0)).round() / 12.0).max(1.0)
                    };

                    (x.xrandr.XRRFreeOutputInfo)(output);
                    available.push(MonitorId{
                        id: crtcid as u32,
                        name,
                        hidpi_factor,
                        dimensions: ((*crtc).width as u32, (*crtc).height as u32),
                        position: ((*crtc).x as i32, (*crtc).y as i32),
                        primary: true,
                    });
                }
                (x.xrandr.XRRFreeCrtcInfo)(crtc);
            }
        }
        (x.xrandr.XRRFreeScreenResources)(resources);
    }
    available
}

#[inline]
pub fn get_primary_monitor(x: &Arc<XConnection>) -> MonitorId {
    get_available_monitors(x).into_iter().find(|m| m.primary)
        // 'no primary' case is better handled picking some existing monitor
        .or_else(|| get_available_monitors(x).into_iter().next())
        .expect("[winit] Failed to find any x11 monitor")
}

impl MonitorId {
    pub fn get_name(&self) -> Option<String> {
        Some(self.name.clone())
    }

    #[inline]
    pub fn get_native_identifier(&self) -> u32 {
        self.id as u32
    }

    pub fn get_dimensions(&self) -> (u32, u32) {
        self.dimensions
    }

    pub fn get_position(&self) -> (i32, i32) {
        self.position
    }

    #[inline]
    pub fn get_hidpi_factor(&self) -> f32 {
        self.hidpi_factor
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust Linkage Model and Symbol Names
//! =======================================
//!
//! The semantic model of Rust linkage is, broadly, that "there's no global
//! namespace" between crates. Our aim is to preserve the illusion of this
//! model despite the fact that it's not *quite* possible to implement on
//! modern linkers. We initially didn't use system linkers at all, but have
//! been convinced of their utility.
//!
//! There are a few issues to handle:
//!
//!  - Linkers operate on a flat namespace, so we have to flatten names.
//!    We do this using the C++ namespace-mangling technique. Foo::bar
//!    symbols and such.
//!
//!  - Symbols for distinct items with the same *name* need to get different
//!    linkage-names. Examples of this are monomorphizations of functions or
//!    items within anonymous scopes that end up having the same path.
//!
//!  - Symbols in different crates but with same names "within" the crate need
//!    to get different linkage-names.
//!
//!  - Symbol names should be deterministic: Two consecutive runs of the
//!    compiler over the same code base should produce the same symbol names for
//!    the same items.
//!
//!  - Symbol names should not depend on any global properties of the code base,
//!    so that small modifications to the code base do not result in all symbols
//!    changing. In previous versions of the compiler, symbol names incorporated
//!    the SVH (Stable Version Hash) of the crate. This scheme turned out to be
//!    infeasible when used in conjunction with incremental compilation because
//!    small code changes would invalidate all symbols generated previously.
//!
//!  - Even symbols from different versions of the same crate should be able to
//!    live next to each other without conflict.
//!
//! In order to fulfill the above requirements the following scheme is used by
//! the compiler:
//!
//! The main tool for avoiding naming conflicts is the incorporation of a 64-bit
//! hash value into every exported symbol name. Anything that makes a difference
//! to the symbol being named, but does not show up in the regular path needs to
//! be fed into this hash:
//!
//! - Different monomorphizations of the same item have the same path but differ
//!   in their concrete type parameters, so these parameters are part of the
//!   data being digested for the symbol hash.
//!
//! - Rust allows items to be defined in anonymous scopes, such as in
//!   `fn foo() { { fn bar() {} } { fn bar() {} } }`. Both `bar` functions have
//!   the path `foo::bar`, since the anonymous scopes do not contribute to the
//!   path of an item. The compiler already handles this case via so-called
//!   disambiguating `DefPaths` which use indices to distinguish items with the
//!   same name. The DefPaths of the functions above are thus `foo[0]::bar[0]`
//!   and `foo[0]::bar[1]`. In order to incorporate this disambiguation
//!   information into the symbol name too, these indices are fed into the
//!   symbol hash, so that the above two symbols would end up with different
//!   hash values.
//!
//! The two measures described above suffice to avoid intra-crate conflicts. In
//! order to also avoid inter-crate conflicts two more measures are taken:
//!
//! - The name of the crate containing the symbol is prepended to the symbol
//!   name, i.e. symbols are "crate qualified". For example, a function `foo` in
//!   module `bar` in crate `baz` would get a symbol name like
//!   `baz::bar::foo::{hash}` instead of just `bar::foo::{hash}`. This avoids
//!   simple conflicts between functions from different crates.
//!
//! - In order to be able to also use symbols from two versions of the same
//!   crate (which naturally also have the same name), a stronger measure is
//!   required: The compiler accepts an arbitrary "disambiguator" value via the
//!   `-C metadata` commandline argument. This disambiguator is then fed into
//!   the symbol hash of every exported item. Consequently, the symbols in two
//!   identical crates but with different disambiguators are not in conflict
//!   with each other. This facility is mainly intended to be used by build
//!   tools like Cargo.
//!
//! A note on symbol name stability
//! -------------------------------
//! Previous versions of the compiler resorted to feeding NodeIds into the
//! symbol hash in order to disambiguate between items with the same path. The
//! current version of the name generation algorithm takes great care not to do
//! that, since NodeIds are notoriously unstable: A small change to the
//! code base will offset all NodeIds after the change and thus, much as using
//! the SVH in the hash, invalidate an unbounded number of symbol names. This
//! makes re-using previously compiled code for incremental compilation
//! virtually impossible. Thus, symbol hash generation exclusively relies on
//! DefPaths which are much more robust in the face of changes to the code base.

use trans::{CrateContext, Instance, gensym_name};
use util::sha2::{Digest, Sha256};

use rustc::middle::cstore;
use rustc::middle::def_id::DefId;
use rustc::middle::ty::{self, TypeFoldable};
use rustc::middle::ty::item_path::{ItemPathBuffer, RootMode};
use rustc::front::map::definitions::DefPath;

use std::fmt::Write;
use syntax::parse::token::{self, InternedString};
use serialize::hex::ToHex;

pub fn def_id_to_string<'tcx>(tcx: &ty::TyCtxt<'tcx>, def_id: DefId) -> String {
    let def_path = tcx.def_path(def_id);
    def_path_to_string(tcx, &def_path)
}

pub fn def_path_to_string<'tcx>(tcx: &ty::TyCtxt<'tcx>, def_path: &DefPath) -> String {
    let mut s = String::with_capacity(def_path.data.len() * 16);

    s.push_str(&tcx.crate_name(def_path.krate));
    s.push_str("/");
    s.push_str(&tcx.crate_disambiguator(def_path.krate));

    for component in &def_path.data {
        write!(s,
               "::{}[{}]",
               component.data.as_interned_str(),
               component.disambiguator)
            .unwrap();
    }

    s
}

fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                             def_path: &DefPath,
                             parameters: &[ty::Ty<'tcx>])
                             -> String {
    debug!("get_symbol_hash(def_path={:?}, parameters={:?})",
           def_path, parameters);

    let tcx = ccx.tcx();

    let mut hash_state = ccx.symbol_hasher().borrow_mut();

    hash_state.reset();

    // the main symbol name is not necessarily unique; hash in the
    // compiler's internal def-path, guaranteeing each symbol has a
    // truly unique path
    hash_state.input_str(&def_path_to_string(tcx, def_path));

    // also include any type parameters (for generic items)
    for t in parameters {
       assert!(!t.has_erasable_regions());
       assert!(!t.needs_subst());
       let encoded_type = tcx.sess.cstore.encode_type(tcx, t, def_id_to_string);
       hash_state.input(&encoded_type[..]);
    }

    return format!("h{}", truncated_hash_result(&mut *hash_state));

    fn truncated_hash_result(symbol_hasher: &mut Sha256) -> String {
        let output = symbol_hasher.result_bytes();
        // 64 bits should be enough to avoid collisions.
        output[.. 8].to_hex()
    }
}

fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           instance: &Instance<'tcx>,
                                           suffix: Option<&str>)
                                           -> String {
    let &Instance { def: mut def_id, params: parameters } = instance;

    debug!("exported_name_with_opt_suffix(def_id={:?}, parameters={:?}, suffix={:?})",
           def_id, parameters, suffix);

    if let Some(node_id) = ccx.tcx().map.as_local_node_id(def_id) {
        if let Some(&src_def_id) = ccx.external_srcs().borrow().get(&node_id) {
            def_id = src_def_id;
        }
    }

    let def_path = ccx.tcx().def_path(def_id);
    assert_eq!(def_path.krate, def_id.krate);
    let hash = get_symbol_hash(ccx, &def_path, parameters.as_slice());

    let mut buffer = SymbolPathBuffer {
        names: Vec::with_capacity(def_path.data.len())
    };
    ccx.tcx().push_item_path(&mut buffer, def_id);

    if let Some(suffix) = suffix {
        buffer.push(suffix);
    }

    mangle(buffer.names.into_iter(), Some(&hash[..]))
}

struct SymbolPathBuffer {
    names: Vec<InternedString>,
}

impl ItemPathBuffer for SymbolPathBuffer {
    fn root_mode(&self) -> &RootMode {
        const ABSOLUTE: &'static RootMode = &RootMode::Absolute;
        ABSOLUTE
    }

    fn push(&mut self, text: &str) {
        self.names.push(token::intern(text).as_str());
    }
}

pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                               instance: &Instance<'tcx>)
                               -> String {
    exported_name_with_opt_suffix(ccx, instance, None)
}

pub fn exported_name_with_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           instance: &Instance<'tcx>,
                                           suffix: &str)
                                           -> String {
   exported_name_with_opt_suffix(ccx, instance, Some(suffix))
}

/// Only symbols that are invisible outside their compilation unit should use a
/// name generated by this function.
pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                                    t: ty::Ty<'tcx>,
                                                    suffix: &str)
                                                    -> String {
    let path = [token::intern(&t.to_string()).as_str(),
                gensym_name(suffix).as_str()];
    let def_path = DefPath {
        data: vec![],
        krate: cstore::LOCAL_CRATE,
    };
    let hash = get_symbol_hash(ccx, &def_path, &[t]);
    mangle(path.iter().cloned(), Some(&hash[..]))
}

// Name sanitation. LLVM will happily accept identifiers with weird names, but
// gas doesn't!
// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
pub fn sanitize(s: &str) -> String {
    let mut result = String::new();
    for c in s.chars() {
        match c {
            // Escape these with $ sequences
            '@' => result.push_str("$SP$"),
            '*' => result.push_str("$BP$"),
            '&' => result.push_str("$RF$"),
            '<' => result.push_str("$LT$"),
            '>' => result.push_str("$GT$"),
            '(' => result.push_str("$LP$"),
            ')' => result.push_str("$RP$"),
            ',' => result.push_str("$C$"),

            // '.' doesn't occur in types and functions, so reuse it
            // for ':' and '-'
            '-' | ':' => result.push('.'),

            // These are legal symbols
            'a' ... 'z'
            | 'A' ... 'Z'
            | '0' ... '9'
            | '_' | '.' | '$' => result.push(c),

            _ => {
                result.push('$');
                for c in c.escape_unicode().skip(1) {
                    match c {
                        '{' => {},
                        '}' => result.push('$'),
                        c => result.push(c),
                    }
                }
            }
        }
    }

    // Underscore-qualify anything that didn't start as an ident.
    if !result.is_empty() &&
        result.as_bytes()[0] != '_' as u8 &&
        ! (result.as_bytes()[0] as char).is_xid_start() {
        return format!("_{}", &result[..]);
    }

    return result;
}

pub fn mangle<PI: Iterator<Item=InternedString>>(path: PI, hash: Option<&str>) -> String {
    // Follow C++ namespace-mangling style, see
    // http://en.wikipedia.org/wiki/Name_mangling for more info.
    //
    // It turns out that on OSX you can actually have arbitrary symbols in
    // function names (at least when given to LLVM), but this is not possible
    // when using unix's linker. Perhaps one day when we just use a linker from LLVM
    // we won't need to do this name mangling. The problem with name mangling is
    // that it seriously limits the available characters. For example we can't
    // have things like &T in symbol names when one would theoretically
    // want them for things like impls of traits on that type.
    //
    // To be able to work on all platforms and get *some* reasonable output, we
    // use C++ name-mangling.

    let mut n = String::from("_ZN"); // _Z == Begin name-sequence, N == nested

    fn push(n: &mut String, s: &str) {
        let sani = sanitize(s);
        n.push_str(&format!("{}{}", sani.len(), sani));
    }

    // First, connect each component with <len, name> pairs.
    for data in path {
        push(&mut n, &data);
    }

    if let Some(s) = hash {
        push(&mut n, s)
    }

    n.push('E'); // End name-sequence.
    n
}
<commit_msg>include the immediate type in the symbol name hash<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The Rust Linkage Model and Symbol Names
//! =======================================
//!
//! The semantic model of Rust linkage is, broadly, that "there's no global
//! namespace" between crates. Our aim is to preserve the illusion of this
//! model despite the fact that it's not *quite* possible to implement on
//! modern linkers. We initially didn't use system linkers at all, but have
//! been convinced of their utility.
//!
//! There are a few issues to handle:
//!
//!  - Linkers operate on a flat namespace, so we have to flatten names.
//!    We do this using the C++ namespace-mangling technique. Foo::bar
//!    symbols and such.
//!
//!  - Symbols for distinct items with the same *name* need to get different
//!    linkage-names. Examples of this are monomorphizations of functions or
//!    items within anonymous scopes that end up having the same path.
//!
//!  - Symbols in different crates but with same names "within" the crate need
//!    to get different linkage-names.
//!
//!  - Symbol names should be deterministic: Two consecutive runs of the
//!    compiler over the same code base should produce the same symbol names for
//!    the same items.
//!
//!  - Symbol names should not depend on any global properties of the code base,
//!    so that small modifications to the code base do not result in all symbols
//!    changing. In previous versions of the compiler, symbol names incorporated
//!    the SVH (Stable Version Hash) of the crate. This scheme turned out to be
//!    infeasible when used in conjunction with incremental compilation because
//!    small code changes would invalidate all symbols generated previously.
//!
//!  - Even symbols from different versions of the same crate should be able to
//!    live next to each other without conflict.
//!
//! In order to fulfill the above requirements the following scheme is used by
//! the compiler:
//!
//! The main tool for avoiding naming conflicts is the incorporation of a 64-bit
//! hash value into every exported symbol name. Anything that makes a difference
//! to the symbol being named, but does not show up in the regular path needs to
//! be fed into this hash:
//!
//! - Different monomorphizations of the same item have the same path but differ
//!   in their concrete type parameters, so these parameters are part of the
//!   data being digested for the symbol hash.
//!
//! - Rust allows items to be defined in anonymous scopes, such as in
//!   `fn foo() { { fn bar() {} } { fn bar() {} } }`. Both `bar` functions have
//!   the path `foo::bar`, since the anonymous scopes do not contribute to the
//!   path of an item. The compiler already handles this case via so-called
//!   disambiguating `DefPaths` which use indices to distinguish items with the
//!   same name. The DefPaths of the functions above are thus `foo[0]::bar[0]`
//!   and `foo[0]::bar[1]`. In order to incorporate this disambiguation
//!   information into the symbol name too, these indices are fed into the
//!   symbol hash, so that the above two symbols would end up with different
//!   hash values.
//!
//! The two measures described above suffice to avoid intra-crate conflicts. In
//! order to also avoid inter-crate conflicts two more measures are taken:
//!
//! - The name of the crate containing the symbol is prepended to the symbol
//!   name, i.e. symbols are "crate qualified". For example, a function `foo` in
//!   module `bar` in crate `baz` would get a symbol name like
//!   `baz::bar::foo::{hash}` instead of just `bar::foo::{hash}`. This avoids
//!   simple conflicts between functions from different crates.
//!
//! - In order to be able to also use symbols from two versions of the same
//!   crate (which naturally also have the same name), a stronger measure is
//!   required: The compiler accepts an arbitrary "disambiguator" value via the
//!   `-C metadata` commandline argument. This disambiguator is then fed into
//!   the symbol hash of every exported item. Consequently, the symbols in two
//!   identical crates but with different disambiguators are not in conflict
//!   with each other. This facility is mainly intended to be used by build
//!   tools like Cargo.
//!
//! A note on symbol name stability
//! -------------------------------
//! Previous versions of the compiler resorted to feeding NodeIds into the
//! symbol hash in order to disambiguate between items with the same path. The
//! current version of the name generation algorithm takes great care not to do
//! that, since NodeIds are notoriously unstable: A small change to the
//! code base will offset all NodeIds after the change and thus, much as using
//! the SVH in the hash, invalidate an unbounded number of symbol names. This
//! makes re-using previously compiled code for incremental compilation
//! virtually impossible. Thus, symbol hash generation exclusively relies on
//! DefPaths which are much more robust in the face of changes to the code base.

use trans::{CrateContext, Instance, gensym_name};
use util::sha2::{Digest, Sha256};

use rustc::middle::cstore;
use rustc::middle::def_id::DefId;
use rustc::middle::ty::{self, TypeFoldable};
use rustc::middle::ty::item_path::{ItemPathBuffer, RootMode};
use rustc::front::map::definitions::{DefPath, DefPathData};

use std::fmt::Write;
use syntax::parse::token::{self, InternedString};
use serialize::hex::ToHex;

pub fn def_id_to_string<'tcx>(tcx: &ty::TyCtxt<'tcx>, def_id: DefId) -> String {
    let def_path = tcx.def_path(def_id);
    def_path_to_string(tcx, &def_path)
}

pub fn def_path_to_string<'tcx>(tcx: &ty::TyCtxt<'tcx>, def_path: &DefPath) -> String {
    let mut s = String::with_capacity(def_path.data.len() * 16);

    s.push_str(&tcx.crate_name(def_path.krate));
    s.push_str("/");
    s.push_str(&tcx.crate_disambiguator(def_path.krate));

    for component in &def_path.data {
        write!(s,
               "::{}[{}]",
               component.data.as_interned_str(),
               component.disambiguator)
            .unwrap();
    }

    s
}

fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,

                             // path to the item this name is for
                             def_path: &DefPath,

                             // type of the item, without any generic
                             // parameters substituted; this is
                             // included in the hash as a kind of
                             // safeguard.
                             item_type: ty::Ty<'tcx>,

                             // values for generic type parameters,
                             // if any.
                             parameters: &[ty::Ty<'tcx>])
                             -> String {
    debug!("get_symbol_hash(def_path={:?}, parameters={:?})",
           def_path, parameters);

    let tcx = ccx.tcx();

    let mut hash_state = ccx.symbol_hasher().borrow_mut();

    hash_state.reset();

    // the main symbol name is not necessarily unique; hash in the
    // compiler's internal def-path, guaranteeing each symbol has a
    // truly unique path
    hash_state.input_str(&def_path_to_string(tcx, def_path));

    // Include the main item-type. Note that, in this case, the
    // assertions about `needs_subst` may not hold, but this item-type
    // ought to be the same for every reference anyway.
    assert!(!item_type.has_erasable_regions());
    let encoded_item_type = tcx.sess.cstore.encode_type(tcx, item_type, def_id_to_string);
    hash_state.input(&encoded_item_type[..]);

    // also include any type parameters (for generic items)
    for t in parameters {
       assert!(!t.has_erasable_regions());
       assert!(!t.needs_subst());
       let encoded_type = tcx.sess.cstore.encode_type(tcx, t, def_id_to_string);
       hash_state.input(&encoded_type[..]);
    }

    return format!("h{}", truncated_hash_result(&mut *hash_state));

    fn truncated_hash_result(symbol_hasher: &mut Sha256) -> String {
        let output = symbol_hasher.result_bytes();
        // 64 bits should be enough to avoid collisions.
        output[.. 8].to_hex()
    }
}

fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           instance: &Instance<'tcx>,
                                           suffix: Option<&str>)
                                           -> String {
    let &Instance { def: mut def_id, params: parameters } = instance;

    debug!("exported_name_with_opt_suffix(def_id={:?}, parameters={:?}, suffix={:?})",
           def_id, parameters, suffix);

    if let Some(node_id) = ccx.tcx().map.as_local_node_id(def_id) {
        if let Some(&src_def_id) = ccx.external_srcs().borrow().get(&node_id) {
            def_id = src_def_id;
        }
    }

    let def_path = ccx.tcx().def_path(def_id);
    assert_eq!(def_path.krate, def_id.krate);

    // We want to compute the "type" of this item. Unfortunately, some
    // kinds of items (e.g., closures) don't have an entry in the
    // item-type array. So walk back up the find the closest parent
    // that DOES have an entry.
    let mut ty_def_id = def_id;
    let instance_ty;
    loop {
        let key = ccx.tcx().def_key(ty_def_id);
        match key.disambiguated_data.data {
            DefPathData::TypeNs(_) |
            DefPathData::ValueNs(_) => {
                instance_ty = ccx.tcx().lookup_item_type(ty_def_id);
                break;
            }
            _ => {
                // if we're making a symbol for something, there ought
                // to be a value or type-def or something in there
                // *somewhere*
                ty_def_id.index = key.parent.unwrap_or_else(|| {
                    panic!("finding type for {:?}, encountered def-id {:?} with no \
                            parent", def_id, ty_def_id);
                });
            }
        }
    }

    // Erase regions because they may not be deterministic when hashed
    // and should not matter anyhow.
    let instance_ty = ccx.tcx().erase_regions(&instance_ty.ty);

    let hash = get_symbol_hash(ccx, &def_path, instance_ty, parameters.as_slice());

    let mut buffer = SymbolPathBuffer {
        names: Vec::with_capacity(def_path.data.len())
    };
    ccx.tcx().push_item_path(&mut buffer, def_id);

    if let Some(suffix) = suffix {
        buffer.push(suffix);
    }

    mangle(buffer.names.into_iter(), Some(&hash[..]))
}

struct SymbolPathBuffer {
    names: Vec<InternedString>,
}

impl ItemPathBuffer for SymbolPathBuffer {
    fn root_mode(&self) -> &RootMode {
        const ABSOLUTE: &'static RootMode = &RootMode::Absolute;
        ABSOLUTE
    }

    fn push(&mut self, text: &str) {
        self.names.push(token::intern(text).as_str());
    }
}

pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                               instance: &Instance<'tcx>)
                               -> String {
    exported_name_with_opt_suffix(ccx, instance, None)
}

pub fn exported_name_with_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           instance: &Instance<'tcx>,
                                           suffix: &str)
                                           -> String {
   exported_name_with_opt_suffix(ccx, instance, Some(suffix))
}

/// Only symbols that are invisible outside their compilation unit should use a
/// name generated by this function.
pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                                    t: ty::Ty<'tcx>,
                                                    suffix: &str)
                                                    -> String {
    let path = [token::intern(&t.to_string()).as_str(),
                gensym_name(suffix).as_str()];
    let def_path = DefPath {
        data: vec![],
        krate: cstore::LOCAL_CRATE,
    };
    let hash = get_symbol_hash(ccx, &def_path, t, &[]);
    mangle(path.iter().cloned(), Some(&hash[..]))
}

// Name sanitation. LLVM will happily accept identifiers with weird names, but
// gas doesn't!
// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
pub fn sanitize(s: &str) -> String {
    let mut result = String::new();
    for c in s.chars() {
        match c {
            // Escape these with $ sequences
            '@' => result.push_str("$SP$"),
            '*' => result.push_str("$BP$"),
            '&' => result.push_str("$RF$"),
            '<' => result.push_str("$LT$"),
            '>' => result.push_str("$GT$"),
            '(' => result.push_str("$LP$"),
            ')' => result.push_str("$RP$"),
            ',' => result.push_str("$C$"),

            // '.' doesn't occur in types and functions, so reuse it
            // for ':' and '-'
            '-' | ':' => result.push('.'),

            // These are legal symbols
            'a' ... 'z'
            | 'A' ... 'Z'
            | '0' ... '9'
            | '_' | '.' | '$' => result.push(c),

            _ => {
                result.push('$');
                for c in c.escape_unicode().skip(1) {
                    match c {
                        '{' => {},
                        '}' => result.push('$'),
                        c => result.push(c),
                    }
                }
            }
        }
    }

    // Underscore-qualify anything that didn't start as an ident.
    if !result.is_empty() &&
        result.as_bytes()[0] != '_' as u8 &&
        ! (result.as_bytes()[0] as char).is_xid_start() {
        return format!("_{}", &result[..]);
    }

    return result;
}

pub fn mangle<PI: Iterator<Item=InternedString>>(path: PI, hash: Option<&str>) -> String {
    // Follow C++ namespace-mangling style, see
    // http://en.wikipedia.org/wiki/Name_mangling for more info.
    //
    // It turns out that on OSX you can actually have arbitrary symbols in
    // function names (at least when given to LLVM), but this is not possible
    // when using unix's linker. Perhaps one day when we just use a linker from LLVM
    // we won't need to do this name mangling. The problem with name mangling is
    // that it seriously limits the available characters. For example we can't
    // have things like &T in symbol names when one would theoretically
    // want them for things like impls of traits on that type.
    //
    // To be able to work on all platforms and get *some* reasonable output, we
    // use C++ name-mangling.

    let mut n = String::from("_ZN"); // _Z == Begin name-sequence, N == nested

    fn push(n: &mut String, s: &str) {
        let sani = sanitize(s);
        n.push_str(&format!("{}{}", sani.len(), sani));
    }

    // First, connect each component with <len, name> pairs.
    for data in path {
        push(&mut n, &data);
    }

    if let Some(s) = hash {
        push(&mut n, s)
    }

    n.push('E'); // End name-sequence.
    n
}
<|endoftext|>


<commit_before>/* Copyright (C) 2015 Yutaka Kamei */

use std::string::FromUtf8Error;

const OFFSET : usize = 6;
const DIGIT : &'static [u8] = b"0123456789ABCDEFabcdef";

/// Replaces %xx escapes by their single-character equivalent.
///
/// # Examples
///
/// ```
/// use urlparse::unquote;
///
/// let s = unquote("ABC%3D123%21%20DEF%3D%23%23");
/// assert_eq!(s.ok().unwrap(), "ABC=123! DEF=##");
/// ```
///
pub fn unquote(s: &str) -> Result<String, FromUtf8Error> {
    let mut result : Vec<u8> = Vec::new();
    let mut items = s.as_bytes().split(|&b| b == b'%');
    match items.next() {
        Some(item) => result.append(&mut item.to_vec()),
        None       => return String::from_utf8(result),
    }
    for item in items {
        match item.len() {
            0 => result.push(b'%'),
            1 => {
                    result.push(b'%');
                    result.append(&mut item.to_vec());
            },
            _ => {
                let fs = &item[..2];
                let ls = &item[2..];
                if let Some(digit) = to_digit(*fs.get(0).unwrap(), *fs.get(1).unwrap()) {
                    result.push(digit);
                    result.append(&mut ls.to_vec());
                } else {
                    result.push(b'%');
                    result.append(&mut item.to_vec());
                }
            },
        }
    }
    return String::from_utf8(result);
}

/// Like unquote(), but also replaces plus signs by spaces, as required for
/// unquoting HTML form values.
///
/// # Examples
///
/// ```
/// use urlparse::unquote_plus;
///
/// let s = unquote_plus("ABC%3D123%21+DEF%3D%23%23");
/// assert_eq!(s.ok().unwrap(), "ABC=123! DEF=##");
/// ```
///
pub fn unquote_plus(s: &str) -> Result<String, FromUtf8Error> {
    let _s = s.replace("+", " ");
    return unquote(&_s);
}

fn to_digit(n1: u8, n2: u8) -> Option<u8> {
    let mut byte : u8 = 0;
    match DIGIT.binary_search(&n1) {
        Ok(_n1) => byte += if _n1 < 16 {_n1 as u8 * 16} else {(_n1 - OFFSET) as u8 * 16},
        Err(_)  => return None,
    }
    match DIGIT.binary_search(&n2) {
        Ok(_n2) => byte += if _n2 < 16 {_n2 as u8} else {(_n2 - OFFSET) as u8},
        Err(_)  => return None,
    }
    return Some(byte);
}
<commit_msg>Add test function for to_digit()<commit_after>/* Copyright (C) 2015 Yutaka Kamei */

use std::string::FromUtf8Error;

const OFFSET : usize = 6;
const DIGIT : &'static [u8] = b"0123456789ABCDEFabcdef";

/// Replaces %xx escapes by their single-character equivalent.
///
/// # Examples
///
/// ```
/// use urlparse::unquote;
///
/// let s = unquote("ABC%3D123%21%20DEF%3D%23%23");
/// assert_eq!(s.ok().unwrap(), "ABC=123! DEF=##");
/// ```
///
pub fn unquote(s: &str) -> Result<String, FromUtf8Error> {
    let mut result : Vec<u8> = Vec::new();
    let mut items = s.as_bytes().split(|&b| b == b'%');
    match items.next() {
        Some(item) => result.append(&mut item.to_vec()),
        None       => return String::from_utf8(result),
    }
    for item in items {
        match item.len() {
            0 => result.push(b'%'),
            1 => {
                    result.push(b'%');
                    result.append(&mut item.to_vec());
            },
            _ => {
                let fs = &item[..2];
                let ls = &item[2..];
                if let Some(digit) = to_digit(*fs.get(0).unwrap(), *fs.get(1).unwrap()) {
                    result.push(digit);
                    result.append(&mut ls.to_vec());
                } else {
                    result.push(b'%');
                    result.append(&mut item.to_vec());
                }
            },
        }
    }
    return String::from_utf8(result);
}

/// Like unquote(), but also replaces plus signs by spaces, as required for
/// unquoting HTML form values.
///
/// # Examples
///
/// ```
/// use urlparse::unquote_plus;
///
/// let s = unquote_plus("ABC%3D123%21+DEF%3D%23%23");
/// assert_eq!(s.ok().unwrap(), "ABC=123! DEF=##");
/// ```
///
pub fn unquote_plus(s: &str) -> Result<String, FromUtf8Error> {
    let _s = s.replace("+", " ");
    return unquote(&_s);
}

fn to_digit(n1: u8, n2: u8) -> Option<u8> {
    let mut byte : u8 = 0;
    match DIGIT.binary_search(&n1) {
        Ok(_n1) => byte += if _n1 < 16 {_n1 as u8 * 16} else {(_n1 - OFFSET) as u8 * 16},
        Err(_)  => return None,
    }
    match DIGIT.binary_search(&n2) {
        Ok(_n2) => byte += if _n2 < 16 {_n2 as u8} else {(_n2 - OFFSET) as u8},
        Err(_)  => return None,
    }
    return Some(byte);
}

#[test]
fn test_to_digit() {
    assert_eq!(to_digit(b'1', b'2'), Some(0x12));
    assert_eq!(to_digit(b'e', b'a'), Some(0xEA));
    assert_eq!(to_digit(b'E', b'A'), Some(0xEA));
    assert_eq!(to_digit(b'F', b'F'), Some(0xFF));
    assert_eq!(to_digit(b'X', b'1'), None);
    assert_eq!(to_digit(b'A', b'x'), None);
}
<|endoftext|>


<commit_before>extern crate widestring;
extern crate winapi;

use crate::{Browser, Error, ErrorKind, ExitStatus, Result};
use std::os::windows::process::ExitStatusExt;
use std::ptr;
use widestring::U16CString;

/// Deal with opening of browsers on Windows, using [`ShellExecuteW`](
/// https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutew)
/// fucntion.
#[inline]
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<ExitStatus> {
    use winapi::shared::winerror::SUCCEEDED;
    use winapi::um::combaseapi::{CoInitializeEx, CoUninitialize};
    use winapi::um::objbase::{COINIT_APARTMENTTHREADED, COINIT_DISABLE_OLE1DDE};
    use winapi::um::shellapi::ShellExecuteW;
    use winapi::um::winuser::SW_SHOWNORMAL;
    match browser {
        Browser::Default => {
            static OPEN: &[u16] = &['o' as u16, 'p' as u16, 'e' as u16, 'n' as u16, 0x0000];
            let url =
                U16CString::from_str(url).map_err(|e| Error::new(ErrorKind::InvalidInput, e))?;
            let code = unsafe {
                let coinitializeex_result = CoInitializeEx(
                    ptr::null_mut(),
                    COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE,
                );
                let code = ShellExecuteW(
                    ptr::null_mut(),
                    OPEN.as_ptr(),
                    url.as_ptr(),
                    ptr::null(),
                    ptr::null(),
                    SW_SHOWNORMAL,
                ) as usize as i32;
                if SUCCEEDED(coinitializeex_result) {
                    CoUninitialize();
                }
                code
            };
            if code > 32 {
                Ok(ExitStatus::from_raw(0))
            } else {
                Err(Error::last_os_error())
            }
        }
        _ => Err(Error::new(
            ErrorKind::NotFound,
            "Only the default browser is supported on this platform right now",
        )),
    }
}<commit_msg>Fix fmt error<commit_after>extern crate widestring;
extern crate winapi;

use crate::{Browser, Error, ErrorKind, ExitStatus, Result};
use std::os::windows::process::ExitStatusExt;
use std::ptr;
use widestring::U16CString;

/// Deal with opening of browsers on Windows, using [`ShellExecuteW`](
/// https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutew)
/// fucntion.
#[inline]
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<ExitStatus> {
    use winapi::shared::winerror::SUCCEEDED;
    use winapi::um::combaseapi::{CoInitializeEx, CoUninitialize};
    use winapi::um::objbase::{COINIT_APARTMENTTHREADED, COINIT_DISABLE_OLE1DDE};
    use winapi::um::shellapi::ShellExecuteW;
    use winapi::um::winuser::SW_SHOWNORMAL;
    match browser {
        Browser::Default => {
            static OPEN: &[u16] = &['o' as u16, 'p' as u16, 'e' as u16, 'n' as u16, 0x0000];
            let url =
                U16CString::from_str(url).map_err(|e| Error::new(ErrorKind::InvalidInput, e))?;
            let code = unsafe {
                let coinitializeex_result = CoInitializeEx(
                    ptr::null_mut(),
                    COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE,
                );
                let code = ShellExecuteW(
                    ptr::null_mut(),
                    OPEN.as_ptr(),
                    url.as_ptr(),
                    ptr::null(),
                    ptr::null(),
                    SW_SHOWNORMAL,
                ) as usize as i32;
                if SUCCEEDED(coinitializeex_result) {
                    CoUninitialize();
                }
                code
            };
            if code > 32 {
                Ok(ExitStatus::from_raw(0))
            } else {
                Err(Error::last_os_error())
            }
        }
        _ => Err(Error::new(
            ErrorKind::NotFound,
            "Only the default browser is supported on this platform right now",
        )),
    }
}
<|endoftext|>


<commit_before><commit_msg>fix: module scoping on windows builds for a few types<commit_after><|endoftext|>


<commit_before><commit_msg>avx: add _mm256_div_pd, _mm256_div_ps<commit_after><|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2014 Kashyap
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use super::x86asm::outb;
use super::x86asm::inb;

use core::str::StrPrelude;

const COM1 : u16 = 0x3f8;
static mut uartInitialized : bool = false;

pub fn early_init () {
	outb(COM1+2 , 0);
	outb(COM1+3, 0x80);    // Unlock divisor
	outb(COM1+0, 12);
	outb(COM1+1, 0);
	outb(COM1+3, 0x03);    // Lock divisor, 8 data bits.
	outb(COM1+4, 0);
	outb(COM1+1, 0x01);    // Enable receive interrupts.

	if inb(COM1+5) == 0xff {
		return;
	}

	unsafe {
		uartInitialized = true;
	}

	outb(COM1, 65);
	uart_putc("123456");
}

fn uart_putc(text: &str) {
	for b in text.bytes() {
		outb(COM1, b);
	}
}
<commit_msg>Since StrPrelude has been renamed to StrExt<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2014 Kashyap
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use super::x86asm::outb;
use super::x86asm::inb;

use core::str::StrExt;

const COM1 : u16 = 0x3f8;
static mut uartInitialized : bool = false;

pub fn early_init () {
	outb(COM1+2 , 0);
	outb(COM1+3, 0x80);    // Unlock divisor
	outb(COM1+0, 12);
	outb(COM1+1, 0);
	outb(COM1+3, 0x03);    // Lock divisor, 8 data bits.
	outb(COM1+4, 0);
	outb(COM1+1, 0x01);    // Enable receive interrupts.

	if inb(COM1+5) == 0xff {
		return;
	}

	unsafe {
		uartInitialized = true;
	}

	outb(COM1, 65);
	uart_putc("123456");
}

fn uart_putc(text: &str) {
	for b in text.bytes() {
		outb(COM1, b);
	}
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::env;
use std::process;

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 2 {
        println!("No file was passed in to be parsed");
        process::exit(1);
    }

    let mut f = File::open(&args[1]).unwrap();
    let mut instructions = String::new();
    f.read_to_string(&mut instructions).unwrap();
    let final_floor = process_instructions(instructions);

    println!("Santa ends up on floor {}", final_floor);
}

fn process_instructions(ins: String) -> i32{
    let mut floor = 0;

    for c in ins.chars() {
        match c {
            '(' => { floor += 1; },
            ')' => { floor -= 1; },
            _ => {}
        }
    }
    floor
}
<commit_msg>Added tests to day 1<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::env;
use std::process;

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 2 {
        println!("No file was passed in to be parsed");
        process::exit(1);
    }

    let mut f = File::open(&args[1]).unwrap();
    let mut instructions = String::new();
    f.read_to_string(&mut instructions).unwrap();
    let final_floor = process_instructions(instructions);

    println!("Santa ends up on floor {}", final_floor);
}

fn process_instructions(ins: String) -> i32{
    let mut floor = 0;

    for c in ins.chars() {
        match c {
            '(' => { floor += 1; },
            ')' => { floor -= 1; },
            _ => {}
        }
    }
    floor
}

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

    #[test]
    fn test_process() {
        assert_eq!(process_instructions(String::from("((()))")), 0);
        assert_eq!(process_instructions(String::from(")))(((")), 0);
        assert_eq!(process_instructions(String::from("()()()")), 0);
        assert_eq!(process_instructions(String::from("((())")), 1);
        assert_eq!(process_instructions(String::from("(()))")), -1);
        assert_eq!(process_instructions(String::from("(((((")), 5);
        assert_eq!(process_instructions(String::from(")))))")), -5);
    }
}
<|endoftext|>