<commit_before>use crate::boxed::Box;

#[rustc_specialization_trait]
pub(super) unsafe trait IsZero {
    /// Whether this value is zero
    fn is_zero(&self) -> bool;
}

macro_rules! impl_is_zero {
    ($t:ty, $is_zero:expr) => {
        unsafe impl IsZero for $t {
            #[inline]
            fn is_zero(&self) -> bool {
                $is_zero(*self)
            }
        }
    };
}

impl_is_zero!(i16, |x| x == 0);
impl_is_zero!(i32, |x| x == 0);
impl_is_zero!(i64, |x| x == 0);
impl_is_zero!(i128, |x| x == 0);
impl_is_zero!(isize, |x| x == 0);

impl_is_zero!(u16, |x| x == 0);
impl_is_zero!(u32, |x| x == 0);
impl_is_zero!(u64, |x| x == 0);
impl_is_zero!(u128, |x| x == 0);
impl_is_zero!(usize, |x| x == 0);

impl_is_zero!(bool, |x| x == false);
impl_is_zero!(char, |x| x == '\0');

impl_is_zero!(f32, |x: f32| x.to_bits() == 0);
impl_is_zero!(f64, |x: f64| x.to_bits() == 0);

unsafe impl<T> IsZero for *const T {
    #[inline]
    fn is_zero(&self) -> bool {
        (*self).is_null()
    }
}

unsafe impl<T> IsZero for *mut T {
    #[inline]
    fn is_zero(&self) -> bool {
        (*self).is_null()
    }
}

// `Option<&T>` and `Option<Box<T>>` are guaranteed to represent `None` as null.
// For fat pointers, the bytes that would be the pointer metadata in the `Some`
// variant are padding in the `None` variant, so ignoring them and
// zero-initializing instead is ok.
// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of
// `SpecFromElem`.

unsafe impl<T: ?Sized> IsZero for Option<&T> {
    #[inline]
    fn is_zero(&self) -> bool {
        self.is_none()
    }
}

unsafe impl<T: ?Sized> IsZero for Option<Box<T>> {
    #[inline]
    fn is_zero(&self) -> bool {
        self.is_none()
    }
}
<commit_msg>Enable Vec's calloc optimization for Option<NonZero><commit_after>use crate::boxed::Box;

#[rustc_specialization_trait]
pub(super) unsafe trait IsZero {
    /// Whether this value is zero
    fn is_zero(&self) -> bool;
}

macro_rules! impl_is_zero {
    ($t:ty, $is_zero:expr) => {
        unsafe impl IsZero for $t {
            #[inline]
            fn is_zero(&self) -> bool {
                $is_zero(*self)
            }
        }
    };
}

impl_is_zero!(i16, |x| x == 0);
impl_is_zero!(i32, |x| x == 0);
impl_is_zero!(i64, |x| x == 0);
impl_is_zero!(i128, |x| x == 0);
impl_is_zero!(isize, |x| x == 0);

impl_is_zero!(u16, |x| x == 0);
impl_is_zero!(u32, |x| x == 0);
impl_is_zero!(u64, |x| x == 0);
impl_is_zero!(u128, |x| x == 0);
impl_is_zero!(usize, |x| x == 0);

impl_is_zero!(bool, |x| x == false);
impl_is_zero!(char, |x| x == '\0');

impl_is_zero!(f32, |x: f32| x.to_bits() == 0);
impl_is_zero!(f64, |x: f64| x.to_bits() == 0);

unsafe impl<T> IsZero for *const T {
    #[inline]
    fn is_zero(&self) -> bool {
        (*self).is_null()
    }
}

unsafe impl<T> IsZero for *mut T {
    #[inline]
    fn is_zero(&self) -> bool {
        (*self).is_null()
    }
}

// `Option<&T>` and `Option<Box<T>>` are guaranteed to represent `None` as null.
// For fat pointers, the bytes that would be the pointer metadata in the `Some`
// variant are padding in the `None` variant, so ignoring them and
// zero-initializing instead is ok.
// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of
// `SpecFromElem`.

unsafe impl<T: ?Sized> IsZero for Option<&T> {
    #[inline]
    fn is_zero(&self) -> bool {
        self.is_none()
    }
}

unsafe impl<T: ?Sized> IsZero for Option<Box<T>> {
    #[inline]
    fn is_zero(&self) -> bool {
        self.is_none()
    }
}

// `Option<num::NonZeroU32>` and similar have a representation guarantee that
// they're the same size as the corresponding `u32` type, as well as a guarantee
// that transmuting between `NonZeroU32` and `Option<num::NonZeroU32>` works.
// While the documentation officially makes in UB to transmute from `None`,
// we're the standard library so we can make extra inferences, and we know that
// the only niche available to represent `None` is the one that's all zeros.

macro_rules! impl_is_zero_option_of_nonzero {
    ($($t:ident,)+) => {$(
        unsafe impl IsZero for Option<core::num::$t> {
            #[inline]
            fn is_zero(&self) -> bool {
                self.is_none()
            }
        }
    )+};
}

impl_is_zero_option_of_nonzero!(
    NonZeroU8,
    NonZeroU16,
    NonZeroU32,
    NonZeroU64,
    NonZeroU128,
    NonZeroI8,
    NonZeroI16,
    NonZeroI32,
    NonZeroI64,
    NonZeroI128,
    NonZeroUsize,
    NonZeroIsize,
);
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}

// the function ez_vec takes a static string and a terminating byte and returns an owned Vec<u8> for convenience
// Without it, character-based tests are a pain

#[test]
fn example_tests() {
  // Echo until byte 255 encountered
//   assert_eq!(String::from_utf8(brain_luck(",+[-.,+]", ez_vec("Codewars", 255))).unwrap(), "Codewars");
//   // Echo until byte 0 encountered
//   assert_eq!(String::from_utf8(brain_luck(",[.[-],]", ez_vec("Codewars", 0))).unwrap(), "Codewars");
  // Multiply two numbers
  assert_eq!(brain_luck(",>,<[>[->+>+<<]>>[-<<+>>]<<<-]>>.", vec![8, 9]), vec![72]);
}

// '>' increment the data pointer (to point to the next cell to the right).
//
// '<' decrement the data pointer (to point to the next cell to the left).
//
// '+' increment (increase by one, truncate overflow: 255 + 1 = 0) the byte at the data pointer.
//
// '-' decrement (decrease by one, treat as unsigned byte: 0 - 1 = 255 ) the byte at the data pointer.
//
// '.' output the byte at the data pointer.
//
// ',' accept one byte of input, storing its value in the byte at the data pointer.
//
// '[' if the byte at the data pointer is zero, then instead of moving the instruction pointer
//     forward to the next command, jump it forward to the command after the matching ] command.
//
// ']' if the byte at the data pointer is nonzero, then instead of moving the instruction pointer
//     forward to the next command, jump it back to the command after the matching [ command.

fn brain_luck(code: &str, input: Vec<u8>) -> Vec<u8> {

    for c in code.chars() {
        match c {
            '>' => {

            }
            '<' => {

            }
            '+' => {

            }
            '-' => {

            }
            '.' => {

            }
            ',' => {

            }
            '[' => {

            }
            ']' => {

            }
            _ => {}
        }
        //
    }

    vec![]
  // your solution here
}
<commit_msg>luck passing 4 of 5<commit_after>fn main() {
    println!("yolo world");
}

// the function ez_vec takes a static string and a terminating byte and returns an owned Vec<u8> for convenience
// Without it, character-based tests are a pain

fn ez_vec(s: &str, term_byte: u8) -> Vec<u8> {
    let mut v: Vec<u8> = vec![0; s.len() + 1];

    let mut idx = 0;
    for b in s.bytes() {
        v[idx] = b;
        idx += 1;
    }
    v[s.len()] = term_byte;

    v
}

#[test]
fn t1() {
// Echo until byte 255 encountered
  assert_eq!(String::from_utf8(brain_luck(",+[-.,+]", ez_vec("Codewars", 255))).unwrap(), "Codewars");
}

#[test]
fn t2() {
// Echo until byte 0 encountered
  assert_eq!(String::from_utf8(brain_luck(",[.[-],]", ez_vec("Codewars", 0))).unwrap(), "Codewars");
}

#[test]
fn t3() {
// Multiply two numbers
  assert_eq!(brain_luck(",>,<[>[->+>+<<]>>[-<<+>>]<<<-]>>.", vec![8, 9]), vec![72]);
}

#[test]
fn t4() {
// Divide two numbers
  assert_eq!(brain_luck(",>,<[>[->+>+<<]>[-<<-[>]>>>[<[-<->]<[>]>>[[-]>>+<]>-<]<<]>>>+<<[-<<+>>]<<<]>>>>>[-<<<<<+>>>>>]<<<<<.", vec![12, 2]), vec![6]);
}

// fn t5() {

// }

fn tape_forward(data:&mut Vec<u8>, dptr: &mut usize) {
    if *dptr == (data.len() - 1) {
        data.push(0);
    }

    *dptr += 1;
}

fn tape_back(data:&mut Vec<u8>, dptr: &mut usize) {
    if *dptr == 0 {
        data.insert(0,0);
    } else {
        *dptr -= 1;
    }
}

fn tape_val_inc(data:&mut Vec<u8>, dptr: usize) {
    if data[dptr] == 255 {
        data[dptr] = 0;
    } else {
        data[dptr] += 1;
    }
}

fn tape_val_dec(data:&mut Vec<u8>, dptr: usize) {
    if data[dptr] == 0 {
        data[dptr] = 255;
    } else {
        data[dptr] -= 1;
    }
}

fn tape_write(data:&mut Vec<u8>, dptr: usize, input: &Vec<u8>, input_ptr: &mut usize) {
     data[dptr] = input[*input_ptr];
    *input_ptr += 1;
}

fn tape_seek_forward(instructions: &Vec<char>, data: u8, instr_ptr: &mut usize) {
    if data == 0 {
        let mut found = false;
        let mut mine = true;

        *instr_ptr += 1;

        while found == false {
            match instructions[*instr_ptr] {
                '[' => {
                    mine = false;
                }
                ']' => {
                    if mine == true {
                        found = true;
                    } else {
                        mine = true;
                    }
                }
                _ => {}
            }
            *instr_ptr += 1;
        }
    } else {
        *instr_ptr += 1;
    }
}

fn tape_seek_back(instructions: &Vec<char>, data: u8, instr_ptr: &mut usize) {
    if data != 0 {
        let mut found = false;
        let mut mine = true;

        *instr_ptr -= 1;

        while found == false {
            match instructions[*instr_ptr] {
                ']' => {
                    mine = false;
                    *instr_ptr -= 1;
                }
                '[' => {
                    if mine == true {
                        found = true;
                        *instr_ptr += 1;
                    } else {
                        mine = true;
                        *instr_ptr -= 1;
                    }
                }
                _ => {
                    *instr_ptr -= 1;
                }
            }
        }
    } else {
        *instr_ptr += 1;
    }
}

fn brain_luck(code: &str, input: Vec<u8>) -> Vec<u8> {
    // println!("code: {:?} -- input: {:?}", code, input);
    let instructions: Vec<char> = code.chars().collect();
    let mut dptr = 0;
    let mut instr_ptr = 0;
    let mut input_ptr = 0;
    let mut output = vec![];
    let mut data: Vec<u8> = vec![0;1];
    let instr_len = instructions.len();
    // println!("1");
    while instr_ptr < instr_len {
    // loop {
        // println!("{}", instructions[instr_ptr]);
        match instructions[instr_ptr] {
            '>' => {
                tape_forward(&mut data, &mut dptr);
                instr_ptr +=1;
            }
            '<' => {
                tape_back(&mut data, &mut dptr);
                instr_ptr +=1;
            }
            '+' => {
                tape_val_inc(&mut data, dptr);
                instr_ptr +=1;
            }
            '-' => {
                tape_val_dec(&mut data, dptr);
                instr_ptr +=1;
            }
            '.' => {
                output.push(data[dptr]);
                instr_ptr +=1;
            }
            ',' => {
                tape_write(&mut data, dptr, &input, &mut input_ptr);
                instr_ptr +=1;
            }
            '[' => {
                tape_seek_forward(&instructions, data[dptr], &mut instr_ptr);
            }
            ']' => {
                tape_seek_back(&instructions, data[dptr], &mut instr_ptr);
            }
            _ => { panic!("BAD INSTRUCTION!"); }
        }
    }

    println!("\n\n{:?}\n\n", data);
    output
}
<|endoftext|>


<commit_before>
use std::collections::hashmap::HashMap;
use std::io::TcpStream;
use url::percent_encoding::{ utf8_percent_encode, DEFAULT_ENCODE_SET };

/// A structure which holds the data for a Phant data stream
///
/// # Example
/// ```
/// let mut phant = phant::Phant::new("data.sparkfun.com", "your_public_key", "your_private_key");
///
/// phant.add("computer_name", "my-computer");
/// phant.add("external_ip", "123.321.111.222");
/// phant.add("internal_ip", "192.168.1.104");
///
/// phant.push().ok().expect("Pushing to server did not succeed");
/// ```

#[deriving(Show)]
pub struct Phant {
    hostname: String,
    public_key: String,
    private_key: String,
    data: HashMap<String, String>
}

impl Phant {
    pub fn new(hostname: &str, public_key: &str, private_key: &str) -> Phant {
        Phant {
            hostname: String::from_str(hostname),
            public_key: String::from_str(public_key),
            private_key: String::from_str(private_key),
            data: HashMap::new()
        }
    }

    /// Adds a key-value pair to the current phant dataset.  The `key` is the
    /// phant column name.  The `value` is a `.to_string()`-able data item. This function
    /// does not manipulate server data.
    pub fn add<T: ToString>(&mut self, key: &str, value: T) {
        self.data.insert(key.to_string(), value.to_string());
    }

    /// Pushes data to the server. All the data that has been `add`ed will be pushed as a row
    /// to the phant server located at `hostname`. The local row will then be cleared so `add`
    /// can be called again to repeat the process.
    ///
    /// Returns an [IoResult](http://doc.rust-lang.org/std/io/type.IoResult.html) where a successful
    /// push will return the response from the server in `String` form.
    pub fn push(&mut self) -> ::std::io::IoResult<String> {
        let query_string = self.data_query_string();
        let request: String = format!("POST /input/{} HTTP/1.0\nPhant-Private-Key: {}\nContent-Type: application/x-www-form-urlencoded\nContent-Length: {}\n\n{}\n\n",
            self.public_key, self.private_key, query_string.len(), query_string);
        let mut socket = try!(TcpStream::connect(self.hostname.as_slice(), 80));
        try!(socket.write_str(request.as_slice()));
        let result = try!(socket.read_to_string());
        self.clear_local();
        Ok(result)
    }

    /// Clears the data locally.  Any key-value pairs that have been added since creation or
    /// previous clear will be removed.
    pub fn clear_local(&mut self) {
        self.data.clear();
    }

    /// Clears the data on the server.
    pub fn clear_server(&mut self) -> ::std::io::IoResult<String> {
        let request: String = format!("DELETE /input/{} HTTP/1.0\nPhant-Private-Key: {}\n\n", self.public_key, self.private_key);
        let mut socket = TcpStream::connect(self.hostname.as_slice(), 80).unwrap();
        try!(socket.write_str(request.as_slice()));
        socket.read_to_string()
    }

    /// Gets a formatted URL in string form for adding the current row to the server.
    /// Local data is _not_ cleared, unlike the `push()` method.
    ///
    /// # Example
    /// ```
    /// let mut phant = phant::Phant::new("data.sparkfun.com", "your_public_key", "your_private_key");
    ///
    /// phant.add("apple_color", "red");
    /// let url = phant.get_url();
    /// assert!(url.as_slice() == "http://data.sparkfun.com/input/your_public_key?private_key=your_private_key&apple_color=red")
    /// ```
    pub fn get_url(&self) -> String {
        format!("http://{}/input/{}?private_key={}&{}", self.hostname, self.public_key, self.private_key, self.data_query_string())
    }

    /// Returns a clone of the data for the current row being added to. Notice: it's a
    /// clone, so manipulations done to this returned object will _not_ modify the
    /// data being held locally in the `Phant` object.
    pub fn row_data(&self) -> HashMap<String, String> {
        self.data.clone()
    }

    fn data_query_string(&self) -> String {
        let mut result_list = Vec::new();
        for (key, value) in self.data.iter() {
            result_list.push(format!("{}={}", key, value));
        }
        utf8_percent_encode(result_list.connect("&").as_slice(), DEFAULT_ENCODE_SET)
    }
}

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

    #[test]
    fn test_get_url() {
        let expected = "http://data.com/input/pub?private_key=priv&color=red".to_string();
        let p = basic_phant();
        assert_eq!(p.row_data().len(), 1);
        assert_eq!(p.get_url(), expected);
        assert_eq!(p.row_data().len(), 1);
    }

    #[test]
    fn test_row_data() {
        let expected_key = "color".to_string();
        let expected_value = "red".to_string();
        let p = basic_phant();
        let mut row_data = p.row_data();
        assert_eq!(row_data.len(), 1);
        assert_eq!(*row_data.get(&expected_key), expected_value);

        // Test that row_data actually makes a clone of the data, and not returning it directly
        row_data.insert("size".to_string(), "large".to_string());
        assert_eq!(p.row_data().len(), 1);
    }

    #[test]
    fn test_overwrite_column() {
        let key = "color".to_string();
        let first_value = "red".to_string();
        let second_value = "green".to_string();
        let mut p = basic_phant();
        assert_eq!(*p.row_data().get(&key), first_value);

        p.add(key.as_slice(), second_value.as_slice());
        assert_eq!(p.row_data().len(), 1);
        assert_eq!(p.row_data().get(&key), &second_value);
    }

    #[test]
    fn test_clear_local() {
        let mut p = basic_phant();
        assert!(p.row_data().len() > 0);
        p.clear_local();
        assert_eq!(p.row_data().len(), 0);
    }

    fn basic_phant() -> Phant {
        let mut p = Phant::new("data.com", "pub", "priv");
        p.add("color", "red");
        p
    }
}
<commit_msg>removed deprecated hashmap issues<commit_after>
use std::collections::hashmap::HashMap;
use std::io::TcpStream;
use url::percent_encoding::{ utf8_percent_encode, DEFAULT_ENCODE_SET };

/// A structure which holds the data for a Phant data stream
///
/// # Example
/// ```
/// let mut phant = phant::Phant::new("data.sparkfun.com", "your_public_key", "your_private_key");
///
/// phant.add("computer_name", "my-computer");
/// phant.add("external_ip", "123.321.111.222");
/// phant.add("internal_ip", "192.168.1.104");
///
/// phant.push().ok().expect("Pushing to server did not succeed");
/// ```

#[deriving(Show)]
pub struct Phant {
    hostname: String,
    public_key: String,
    private_key: String,
    data: HashMap<String, String>
}

impl Phant {
    pub fn new(hostname: &str, public_key: &str, private_key: &str) -> Phant {
        Phant {
            hostname: String::from_str(hostname),
            public_key: String::from_str(public_key),
            private_key: String::from_str(private_key),
            data: HashMap::new()
        }
    }

    /// Adds a key-value pair to the current phant dataset.  The `key` is the
    /// phant column name.  The `value` is a `.to_string()`-able data item. This function
    /// does not manipulate server data.
    pub fn add<T: ToString>(&mut self, key: &str, value: T) {
        self.data.insert(key.to_string(), value.to_string());
    }

    /// Pushes data to the server. All the data that has been `add`ed will be pushed as a row
    /// to the phant server located at `hostname`. The local row will then be cleared so `add`
    /// can be called again to repeat the process.
    ///
    /// Returns an [IoResult](http://doc.rust-lang.org/std/io/type.IoResult.html) where a successful
    /// push will return the response from the server in `String` form.
    pub fn push(&mut self) -> ::std::io::IoResult<String> {
        let query_string = self.data_query_string();
        let request: String = format!("POST /input/{} HTTP/1.0\nPhant-Private-Key: {}\nContent-Type: application/x-www-form-urlencoded\nContent-Length: {}\n\n{}\n\n",
            self.public_key, self.private_key, query_string.len(), query_string);
        let mut socket = try!(TcpStream::connect(self.hostname.as_slice(), 80));
        try!(socket.write_str(request.as_slice()));
        let result = try!(socket.read_to_string());
        self.clear_local();
        Ok(result)
    }

    /// Clears the data locally.  Any key-value pairs that have been added since creation or
    /// previous clear will be removed.
    pub fn clear_local(&mut self) {
        self.data.clear();
    }

    /// Clears the data on the server.
    pub fn clear_server(&mut self) -> ::std::io::IoResult<String> {
        let request: String = format!("DELETE /input/{} HTTP/1.0\nPhant-Private-Key: {}\n\n", self.public_key, self.private_key);
        let mut socket = TcpStream::connect(self.hostname.as_slice(), 80).unwrap();
        try!(socket.write_str(request.as_slice()));
        socket.read_to_string()
    }

    /// Gets a formatted URL in string form for adding the current row to the server.
    /// Local data is _not_ cleared, unlike the `push()` method.
    ///
    /// # Example
    /// ```
    /// let mut phant = phant::Phant::new("data.sparkfun.com", "your_public_key", "your_private_key");
    ///
    /// phant.add("apple_color", "red");
    /// let url = phant.get_url();
    /// assert!(url.as_slice() == "http://data.sparkfun.com/input/your_public_key?private_key=your_private_key&apple_color=red")
    /// ```
    pub fn get_url(&self) -> String {
        format!("http://{}/input/{}?private_key={}&{}", self.hostname, self.public_key, self.private_key, self.data_query_string())
    }

    /// Returns a clone of the data for the current row being added to. Notice: it's a
    /// clone, so manipulations done to this returned object will _not_ modify the
    /// data being held locally in the `Phant` object.
    pub fn row_data(&self) -> HashMap<String, String> {
        self.data.clone()
    }

    fn data_query_string(&self) -> String {
        let mut result_list = Vec::new();
        for (key, value) in self.data.iter() {
            result_list.push(format!("{}={}", key, value));
        }
        utf8_percent_encode(result_list.connect("&").as_slice(), DEFAULT_ENCODE_SET)
    }
}

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

    #[test]
    fn test_get_url() {
        let expected = "http://data.com/input/pub?private_key=priv&color=red".to_string();
        let p = basic_phant();
        assert_eq!(p.row_data().len(), 1);
        assert_eq!(p.get_url(), expected);
        assert_eq!(p.row_data().len(), 1);
    }

    #[test]
    fn test_row_data() {
        let expected_key = "color".to_string();
        let expected_value = "red".to_string();
        let p = basic_phant();
        let mut row_data = p.row_data();
        assert_eq!(row_data.len(), 1);
        assert_eq!(row_data[expected_key], expected_value);

        // Test that row_data actually makes a clone of the data, and not returning it directly
        row_data.insert("size".to_string(), "large".to_string());
        assert_eq!(p.row_data().len(), 1);
    }

    #[test]
    fn test_overwrite_column() {
        let key = "color".to_string();
        let first_value = "red".to_string();
        let second_value = "green".to_string();
        let mut p = basic_phant();
        assert_eq!(p.row_data()[key], first_value);

        p.add(key.as_slice(), second_value.as_slice());
        assert_eq!(p.row_data().len(), 1);
        assert_eq!(p.row_data()[key], second_value);
    }

    #[test]
    fn test_clear_local() {
        let mut p = basic_phant();
        assert!(p.row_data().len() > 0);
        p.clear_local();
        assert_eq!(p.row_data().len(), 0);
    }

    fn basic_phant() -> Phant {
        let mut p = Phant::new("data.com", "pub", "priv");
        p.add("color", "red");
        p
    }
}
<|endoftext|>


<commit_before>
use std::collections::HashMap;
use std::io::TcpStream;
use url::percent_encoding::{ utf8_percent_encode, DEFAULT_ENCODE_SET };

/// A structure which holds the data for a Phant data stream
///
/// # Example
/// ```
/// let mut phant = phant::Phant::new("data.sparkfun.com", "your_public_key", "your_private_key");
///
/// phant.add("computer_name", "my-computer");
/// phant.add("external_ip", "123.321.111.222");
/// phant.add("internal_ip", "192.168.1.104");
///
/// phant.push().ok().expect("Pushing to server did not succeed");
/// ```

#[derive(Show)]
pub struct Phant {
    hostname: String,
    public_key: String,
    private_key: String,
    data: HashMap<String, String>
}

impl Phant {
    pub fn new(hostname: &str, public_key: &str, private_key: &str) -> Phant {
        Phant {
            hostname: String::from_str(hostname),
            public_key: String::from_str(public_key),
            private_key: String::from_str(private_key),
            data: HashMap::new()
        }
    }

    /// Adds a key-value pair to the current phant dataset.  The `key` is the
    /// phant column name.  The `value` is a `.to_string()`-able data item. This function
    /// does not manipulate server data.
    pub fn add<T: ToString>(&mut self, key: &str, value: T) {
        self.data.insert(key.to_string(), value.to_string());
    }

    /// Pushes data to the server. All the data that has been `add`ed will be pushed as a row
    /// to the phant server located at `hostname`. The local row will then be cleared so `add`
    /// can be called again to repeat the process.
    ///
    /// Returns an [IoResult](http://doc.rust-lang.org/std/io/type.IoResult.html) where a successful
    /// push will return the response from the server in `String` form.
    pub fn push(&mut self) -> ::std::io::IoResult<String> {
        let query_string = self.data_query_string();
        let request: String = format!("POST /input/{} HTTP/1.0\nPhant-Private-Key: {}\nContent-Type: application/x-www-form-urlencoded\nContent-Length: {}\n\n{}\n\n",
            self.public_key, self.private_key, query_string.len(), query_string);
        let mut socket = try!(TcpStream::connect(format!("{0}:{1}", self.hostname, "80").as_slice()));
        try!(socket.write_str(request.as_slice()));
        let result = try!(socket.read_to_string());
        self.clear_local();
        Ok(result)
    }

    /// Clears the data locally.  Any key-value pairs that have been added since creation or
    /// previous clear will be removed.
    pub fn clear_local(&mut self) {
        self.data.clear();
    }

    /// Clears the data on the server.
    pub fn clear_server(&mut self) -> ::std::io::IoResult<String> {
        let request: String = format!("DELETE /input/{} HTTP/1.0\nPhant-Private-Key: {}\n\n", self.public_key, self.private_key);
        let mut socket = TcpStream::connect(format!("{0}:{1}", self.hostname, "80").as_slice()).unwrap();
        try!(socket.write_str(request.as_slice()));
        socket.read_to_string()
    }

    /// Gets a formatted URL in string form for adding the current row to the server.
    /// Local data is _not_ cleared, unlike the `push()` method.
    ///
    /// # Example
    /// ```
    /// let mut phant = phant::Phant::new("data.sparkfun.com", "your_public_key", "your_private_key");
    ///
    /// phant.add("apple_color", "red");
    /// let url = phant.get_url();
    /// assert!(url.as_slice() == "http://data.sparkfun.com/input/your_public_key?private_key=your_private_key&apple_color=red")
    /// ```
    pub fn get_url(&self) -> String {
        format!("http://{}/input/{}?private_key={}&{}", self.hostname, self.public_key, self.private_key, self.data_query_string())
    }

    /// Returns a clone of the data for the current row being added to. Notice: it's a
    /// clone, so manipulations done to this returned object will _not_ modify the
    /// data being held locally in the `Phant` object.
    pub fn row_data(&self) -> HashMap<String, String> {
        self.data.clone()
    }

    fn data_query_string(&self) -> String {
        let mut result_list = Vec::new();
        for (key, value) in self.data.iter() {
            result_list.push(format!("{}={}", key, value));
        }
        utf8_percent_encode(result_list.connect("&").as_slice(), DEFAULT_ENCODE_SET)
    }
}

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

    #[test]
    fn test_get_url() {
        let expected = "http://data.com/input/pub?private_key=priv&color=red".to_string();
        let p = basic_phant();
        assert_eq!(p.row_data().len(), 1);
        assert_eq!(p.get_url(), expected);
        assert_eq!(p.row_data().len(), 1);
    }

    #[test]
    fn test_row_data() {
        let expected_key = "color".to_string();
        let expected_value = "red".to_string();
        let p = basic_phant();
        let mut row_data = p.row_data();
        assert_eq!(row_data.len(), 1);
        assert_eq!(row_data[expected_key], expected_value);

        // Test that row_data actually makes a clone of the data, and not returning it directly
        row_data.insert("size".to_string(), "large".to_string());
        assert_eq!(p.row_data().len(), 1);
    }

    #[test]
    fn test_overwrite_column() {
        let key = "color".to_string();
        let first_value = "red".to_string();
        let second_value = "green".to_string();
        let mut p = basic_phant();
        assert_eq!(p.row_data()[key], first_value);

        p.add(key.as_slice(), second_value.as_slice());
        assert_eq!(p.row_data().len(), 1);
        assert_eq!(p.row_data()[key], second_value);
    }

    #[test]
    fn test_clear_local() {
        let mut p = basic_phant();
        assert!(p.row_data().len() > 0);
        p.clear_local();
        assert_eq!(p.row_data().len(), 0);
    }

    fn basic_phant() -> Phant {
        let mut p = Phant::new("data.com", "pub", "priv");
        p.add("color", "red");
        p
    }
}
<commit_msg>got phant building again. doc test problems<commit_after>#![allow(unstable)]

use std::collections::HashMap;
use std::io::TcpStream;
use url::percent_encoding::{ utf8_percent_encode, DEFAULT_ENCODE_SET };

/// A structure which holds the data for a Phant data stream
///
/// # Example
/// ```
/// let mut phant = phant::Phant::new("data.sparkfun.com", "your_public_key", "your_private_key");
///
/// phant.add("computer_name", "my-computer");
/// phant.add("external_ip", "123.321.111.222");
/// phant.add("internal_ip", "192.168.1.104");
///
/// phant.push().ok().expect("Pushing to server did not succeed");
/// ```

#[derive(Show)]
pub struct Phant {
    hostname: String,
    public_key: String,
    private_key: String,
    data: HashMap<String, String>
}

impl Phant {
    pub fn new(hostname: &str, public_key: &str, private_key: &str) -> Phant {
        Phant {
            hostname: String::from_str(hostname),
            public_key: String::from_str(public_key),
            private_key: String::from_str(private_key),
            data: HashMap::new()
        }
    }

    /// Adds a key-value pair to the current phant dataset.  The `key` is the
    /// phant column name.  The `value` is a `.to_string()`-able data item. This function
    /// does not manipulate server data.
    pub fn add<T: ToString>(&mut self, key: &str, value: T) {
        self.data.insert(key.to_string(), value.to_string());
    }

    /// Pushes data to the server. All the data that has been `add`ed will be pushed as a row
    /// to the phant server located at `hostname`. The local row will then be cleared so `add`
    /// can be called again to repeat the process.
    ///
    /// Returns an [IoResult](http://doc.rust-lang.org/std/io/type.IoResult.html) where a successful
    /// push will return the response from the server in `String` form.
    pub fn push(&mut self) -> ::std::io::IoResult<String> {
        let query_string = self.data_query_string();
        let request: String = format!("POST /input/{} HTTP/1.0\nPhant-Private-Key: {}\nContent-Type: application/x-www-form-urlencoded\nContent-Length: {}\n\n{}\n\n",
            self.public_key, self.private_key, query_string.len(), query_string);
        let mut socket = try!(TcpStream::connect(format!("{0}:{1}", self.hostname, "80").as_slice()));
        try!(socket.write_str(request.as_slice()));
        let result = try!(socket.read_to_string());
        self.clear_local();
        Ok(result)
    }

    /// Clears the data locally.  Any key-value pairs that have been added since creation or
    /// previous clear will be removed.
    pub fn clear_local(&mut self) {
        self.data.clear();
    }

    /// Clears the data on the server.
    pub fn clear_server(&mut self) -> ::std::io::IoResult<String> {
        let request: String = format!("DELETE /input/{} HTTP/1.0\nPhant-Private-Key: {}\n\n", self.public_key, self.private_key);
        let mut socket = TcpStream::connect(format!("{0}:{1}", self.hostname, "80").as_slice()).unwrap();
        try!(socket.write_str(request.as_slice()));
        socket.read_to_string()
    }

    /// Gets a formatted URL in string form for adding the current row to the server.
    /// Local data is _not_ cleared, unlike the `push()` method.
    ///
    /// # Example
    /// ```
    /// #![allow(unstable)]
    /// let mut phant = phant::Phant::new("data.sparkfun.com", "your_public_key", "your_private_key");
    ///
    /// phant.add("apple_color", "red");
    /// let url = phant.get_url();
    /// assert!(url.as_slice() == "http://data.sparkfun.com/input/your_public_key?private_key=your_private_key&apple_color=red")
    /// ```
    pub fn get_url(&self) -> String {
        format!("http://{}/input/{}?private_key={}&{}", self.hostname, self.public_key, self.private_key, self.data_query_string())
    }

    /// Returns a clone of the data for the current row being added to. Notice: it's a
    /// clone, so manipulations done to this returned object will _not_ modify the
    /// data being held locally in the `Phant` object.
    pub fn row_data(&self) -> HashMap<String, String> {
        self.data.clone()
    }

    fn data_query_string(&self) -> String {
        let mut result_list = Vec::new();
        for (key, value) in self.data.iter() {
            result_list.push(format!("{}={}", key, value));
        }
        utf8_percent_encode(result_list.connect("&").as_slice(), DEFAULT_ENCODE_SET)
    }
}

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

    #[test]
    fn test_get_url() {
        let expected = "http://data.com/input/pub?private_key=priv&color=red".to_string();
        let p = basic_phant();
        assert_eq!(p.row_data().len(), 1);
        assert_eq!(p.get_url(), expected);
        assert_eq!(p.row_data().len(), 1);
    }

    #[test]
    fn test_row_data() {
        let expected_key = "color".to_string();
        let expected_value = "red".to_string();
        let p = basic_phant();
        let mut row_data = p.row_data();
        assert_eq!(row_data.len(), 1);
        assert_eq!(row_data[expected_key], expected_value);

        // Test that row_data actually makes a clone of the data, and not returning it directly
        row_data.insert("size".to_string(), "large".to_string());
        assert_eq!(p.row_data().len(), 1);
    }

    #[test]
    fn test_overwrite_column() {
        let key = "color".to_string();
        let first_value = "red".to_string();
        let second_value = "green".to_string();
        let mut p = basic_phant();
        assert_eq!(p.row_data()[key], first_value);

        p.add(key.as_slice(), second_value.as_slice());
        assert_eq!(p.row_data().len(), 1);
        assert_eq!(p.row_data()[key], second_value);
    }

    #[test]
    fn test_clear_local() {
        let mut p = basic_phant();
        assert!(p.row_data().len() > 0);
        p.clear_local();
        assert_eq!(p.row_data().len(), 0);
    }

    fn basic_phant() -> Phant {
        let mut p = Phant::new("data.com", "pub", "priv");
        p.add("color", "red");
        p
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! record type definitions

use std::convert::From;
use std::cmp::Ordering;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::str::FromStr;

use serialize::binary::*;
use error::*;

#[cfg(feature = "dnssec")]
use rr::dnssec::rdata::DNSSECRecordType;

/// The type of the resource record.
///
/// This specifies the type of data in the RData field of the Resource Record
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
#[allow(dead_code)]
pub enum RecordType {
    /// RFC 1035[1]	IPv4 Address record
    A,
    /// RFC 3596[2]	IPv6 address record
    AAAA,
    //  AFSDB,      //	18	RFC 1183	AFS database record
    /// RFC 1035[1]	All cached records, aka ANY
    ANY,
    //  APL,        //	42	RFC 3123	Address Prefix List
    /// RFC 1035[1]	Authoritative Zone Transfer
    AXFR,
    /// RFC 6844 Certification Authority Authorization
    CAA,
    //  CERT,       //	37	RFC 4398	Certificate record
    /// RFC 1035[1]	Canonical name record
    CNAME,
    //  DHCID,      //	49	RFC 4701	DHCP identifier
    //  DNAME,      //	39	RFC 2672	Delegation Name
    //  HIP,        //	55	RFC 5205	Host Identity Protocol
    //  IPSECKEY,   //	45	RFC 4025	IPsec Key
    /// RFC 1996	Incremental Zone Transfer
    IXFR,
    //  KX,         //	36	RFC 2230	Key eXchanger record
    //  LOC,        //	29	RFC 1876	Location record
    /// RFC 1035[1]	Mail exchange record
    MX,
    //  NAPTR,      //	35	RFC 3403	Naming Authority Pointer
    /// RFC 1035[1]	Name server record
    NS,
    /// RFC 1035[1]	Null server record, for testing
    NULL,
    /// RFC 6891	Option
    OPT,
    /// RFC 1035[1]	Pointer record
    PTR,
    //  RP,         //	17	RFC 1183	Responsible person
    /// RFC 1035[1] and RFC 2308[9]	Start of [a zone of] authority record
    SOA,
    /// RFC 2782	Service locator
    SRV,
    //  SSHFP,      //	44	RFC 4255	SSH Public Key Fingerprint
    //  TA,         //	32768	N/A	DNSSEC Trust Authorities
    //  TKEY,       //	249	RFC 2930	Secret key record
    ///	RFC 6698	TLSA certificate association
    TLSA,
    //  TSIG,       //	250	RFC 2845	Transaction Signature
    /// RFC 1035[1]	Text record
    TXT,

    /// A DNSSEC- or SIG(0)- specific record type.
    ///
    /// These types are in `DNSSECRecordType` to make them easy to disable when
    /// crypto functionality isn't needed.
    #[cfg(feature = "dnssec")]
    DNSSEC(DNSSECRecordType),

    /// Unknown Record type, or unsupported
    Unknown(u16),
}

impl RecordType {
    /// Returns true if this is an ANY
    #[inline]
    pub fn is_any(&self) -> bool {
        *self == RecordType::ANY
    }

    /// Returns true if this is a CNAME
    #[inline]
    pub fn is_cname(&self) -> bool {
        *self == RecordType::CNAME
    }

    /// Returns true if this is an SRV
    #[inline]
    pub fn is_srv(&self) -> bool {
        *self == RecordType::SRV
    }
}

impl FromStr for RecordType {
    type Err = ProtoError;

    /// Convert `&str` to `RecordType`
    ///
    /// ```
    /// use std::str::FromStr;
    /// use trust_dns_proto::rr::record_type::RecordType;
    ///
    /// let var: RecordType = RecordType::from_str("A").unwrap();
    /// assert_eq!(RecordType::A, var);
    /// ```
    fn from_str(str: &str) -> ProtoResult<Self> {
        match str {
            "A" => Ok(RecordType::A),
            "AAAA" => Ok(RecordType::AAAA),
            "CAA" => Ok(RecordType::CAA),
            "CNAME" => Ok(RecordType::CNAME),
            "NULL" => Ok(RecordType::NULL),
            "MX" => Ok(RecordType::MX),
            "NS" => Ok(RecordType::NS),
            "PTR" => Ok(RecordType::PTR),
            "SOA" => Ok(RecordType::SOA),
            "SRV" => Ok(RecordType::SRV),
            "TLSA" => Ok(RecordType::TLSA),
            "TXT" => Ok(RecordType::TXT),
            "ANY" | "*" => Ok(RecordType::ANY),
            "AXFR" => Ok(RecordType::AXFR),
            _ => Err(ProtoErrorKind::UnknownRecordTypeStr(str.to_string()).into()),
        }
    }
}

impl From<u16> for RecordType {
    /// Convert from `u16` to `RecordType`
    ///
    /// ```
    /// use trust_dns_proto::rr::record_type::RecordType;
    ///
    /// let var = RecordType::from(1);
    /// assert_eq!(RecordType::A, var);
    /// ```
    fn from(value: u16) -> Self {
        match value {
            1 => RecordType::A,
            28 => RecordType::AAAA,
            255 => RecordType::ANY,
            252 => RecordType::AXFR,
            257 => RecordType::CAA,
            5 => RecordType::CNAME,
            15 => RecordType::MX,
            2 => RecordType::NS,
            0 => RecordType::NULL,
            41 => RecordType::OPT,
            12 => RecordType::PTR,
            6 => RecordType::SOA,
            33 => RecordType::SRV,
            52 => RecordType::TLSA,
            16 => RecordType::TXT,
            #[cfg(feature = "dnssec")]
            48/*DNSKEY*/ |
            43/*DS*/ |
            25/*KEY*/ |
            47/*NSEC*/|
            50/*NSEC3*/|
            51/*NSEC3PARAM*/|
            46/*RRSIG*/|
            24/*SIG*/ => RecordType::DNSSEC(DNSSECRecordType::from(value)),
            // all unknown record types
            _ => RecordType::Unknown(value),
        }
    }
}

impl BinEncodable for RecordType {
    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
        encoder.emit_u16((*self).into())
    }
}

impl<'r> BinDecodable<'r> for RecordType {
    fn read(decoder: &mut BinDecoder) -> ProtoResult<Self> {
        decoder.read_u16().map(Self::from)
    }
}

// TODO make these a macro...

/// Convert from RecordType to &str
///
/// ```
/// use std::convert::From;
/// use trust_dns_proto::rr::record_type::RecordType;
///
/// let var: &'static str = From::from(RecordType::A);
/// assert_eq!("A", var);
///
/// let var: &'static str = RecordType::A.into();
/// assert_eq!("A", var);
/// ```
impl From<RecordType> for &'static str {
    fn from(rt: RecordType) -> &'static str {
        match rt {
            RecordType::A => "A",
            RecordType::AAAA => "AAAA",
            RecordType::ANY => "ANY",
            RecordType::AXFR => "AXFR",
            RecordType::CAA => "CAA",
            RecordType::CNAME => "CNAME",
            RecordType::IXFR => "IXFR",
            RecordType::MX => "MX",
            RecordType::NULL => "NULL",
            RecordType::NS => "NS",
            RecordType::OPT => "OPT",
            RecordType::PTR => "PTR",
            RecordType::SOA => "SOA",
            RecordType::SRV => "SRV",
            RecordType::TLSA => "TLSA",
            RecordType::TXT => "TXT",
            #[cfg(feature = "dnssec")]
            RecordType::DNSSEC(rt) => rt.into(),
            RecordType::Unknown(_) => "Unknown",
        }
    }
}

/// Convert from RecordType to &str
///
/// ```
/// use std::convert::From;
/// use trust_dns_proto::rr::record_type::RecordType;
///
/// let var: u16 = RecordType::A.into();
/// assert_eq!(1, var);
/// ```
impl From<RecordType> for u16 {
    fn from(rt: RecordType) -> Self {
        match rt {
            RecordType::A => 1,
            RecordType::AAAA => 28,
            RecordType::ANY => 255,
            RecordType::AXFR => 252,
            RecordType::CAA => 257,
            RecordType::CNAME => 5,
            RecordType::IXFR => 251,
            RecordType::MX => 15,
            RecordType::NS => 2,
            RecordType::NULL => 0,
            RecordType::OPT => 41,
            RecordType::PTR => 12,
            RecordType::SOA => 6,
            RecordType::SRV => 33,
            RecordType::TLSA => 52,
            RecordType::TXT => 16,
            #[cfg(feature = "dnssec")]
            RecordType::DNSSEC(rt) => rt.into(),
            RecordType::Unknown(code) => code,
        }
    }
}

impl PartialOrd<RecordType> for RecordType {
    fn partial_cmp(&self, other: &RecordType) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for RecordType {
    fn cmp(&self, other: &Self) -> Ordering {
        u16::from(*self).cmp(&u16::from(*other))
    }
}

impl Display for RecordType {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        f.write_str(Into::<&str>::into(*self))
    }
}

#[test]
fn test_order() {
    let ordered = vec![
        RecordType::NULL,
        RecordType::A,
        RecordType::NS,
        RecordType::CNAME,
        RecordType::SOA,
        RecordType::PTR,
        RecordType::MX,
        RecordType::TXT,
        RecordType::AAAA,
        RecordType::SRV,
        RecordType::AXFR,
        RecordType::ANY,
    ];

    let mut unordered = vec![
        RecordType::ANY,
        RecordType::NULL,
        RecordType::AXFR,
        RecordType::A,
        RecordType::NS,
        RecordType::SOA,
        RecordType::SRV,
        RecordType::PTR,
        RecordType::MX,
        RecordType::CNAME,
        RecordType::TXT,
        RecordType::AAAA,
    ];

    unordered.sort();

    for rtype in unordered.clone() {
        println!("u16 for {:?}: {}", rtype, u16::from(rtype));
    }

    assert_eq!(5.partial_cmp(&28), Some(Ordering::Less));

    assert_eq!(ordered, unordered);
}
<commit_msg>type value of RecordType::NULL should be 10<commit_after>/*
 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! record type definitions

use std::convert::From;
use std::cmp::Ordering;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::str::FromStr;

use serialize::binary::*;
use error::*;

#[cfg(feature = "dnssec")]
use rr::dnssec::rdata::DNSSECRecordType;

/// The type of the resource record.
///
/// This specifies the type of data in the RData field of the Resource Record
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
#[allow(dead_code)]
pub enum RecordType {
    /// RFC 1035[1]	IPv4 Address record
    A,
    /// RFC 3596[2]	IPv6 address record
    AAAA,
    //  AFSDB,      //	18	RFC 1183	AFS database record
    /// RFC 1035[1]	All cached records, aka ANY
    ANY,
    //  APL,        //	42	RFC 3123	Address Prefix List
    /// RFC 1035[1]	Authoritative Zone Transfer
    AXFR,
    /// RFC 6844 Certification Authority Authorization
    CAA,
    //  CERT,       //	37	RFC 4398	Certificate record
    /// RFC 1035[1]	Canonical name record
    CNAME,
    //  DHCID,      //	49	RFC 4701	DHCP identifier
    //  DNAME,      //	39	RFC 2672	Delegation Name
    //  HIP,        //	55	RFC 5205	Host Identity Protocol
    //  IPSECKEY,   //	45	RFC 4025	IPsec Key
    /// RFC 1996	Incremental Zone Transfer
    IXFR,
    //  KX,         //	36	RFC 2230	Key eXchanger record
    //  LOC,        //	29	RFC 1876	Location record
    /// RFC 1035[1]	Mail exchange record
    MX,
    //  NAPTR,      //	35	RFC 3403	Naming Authority Pointer
    /// RFC 1035[1]	Name server record
    NS,
    /// RFC 1035[1]	Null server record, for testing
    NULL,
    /// RFC 6891	Option
    OPT,
    /// RFC 1035[1]	Pointer record
    PTR,
    //  RP,         //	17	RFC 1183	Responsible person
    /// RFC 1035[1] and RFC 2308[9]	Start of [a zone of] authority record
    SOA,
    /// RFC 2782	Service locator
    SRV,
    //  SSHFP,      //	44	RFC 4255	SSH Public Key Fingerprint
    //  TA,         //	32768	N/A	DNSSEC Trust Authorities
    //  TKEY,       //	249	RFC 2930	Secret key record
    ///	RFC 6698	TLSA certificate association
    TLSA,
    //  TSIG,       //	250	RFC 2845	Transaction Signature
    /// RFC 1035[1]	Text record
    TXT,

    /// A DNSSEC- or SIG(0)- specific record type.
    ///
    /// These types are in `DNSSECRecordType` to make them easy to disable when
    /// crypto functionality isn't needed.
    #[cfg(feature = "dnssec")]
    DNSSEC(DNSSECRecordType),

    /// Unknown Record type, or unsupported
    Unknown(u16),
}

impl RecordType {
    /// Returns true if this is an ANY
    #[inline]
    pub fn is_any(&self) -> bool {
        *self == RecordType::ANY
    }

    /// Returns true if this is a CNAME
    #[inline]
    pub fn is_cname(&self) -> bool {
        *self == RecordType::CNAME
    }

    /// Returns true if this is an SRV
    #[inline]
    pub fn is_srv(&self) -> bool {
        *self == RecordType::SRV
    }
}

impl FromStr for RecordType {
    type Err = ProtoError;

    /// Convert `&str` to `RecordType`
    ///
    /// ```
    /// use std::str::FromStr;
    /// use trust_dns_proto::rr::record_type::RecordType;
    ///
    /// let var: RecordType = RecordType::from_str("A").unwrap();
    /// assert_eq!(RecordType::A, var);
    /// ```
    fn from_str(str: &str) -> ProtoResult<Self> {
        match str {
            "A" => Ok(RecordType::A),
            "AAAA" => Ok(RecordType::AAAA),
            "CAA" => Ok(RecordType::CAA),
            "CNAME" => Ok(RecordType::CNAME),
            "NULL" => Ok(RecordType::NULL),
            "MX" => Ok(RecordType::MX),
            "NS" => Ok(RecordType::NS),
            "PTR" => Ok(RecordType::PTR),
            "SOA" => Ok(RecordType::SOA),
            "SRV" => Ok(RecordType::SRV),
            "TLSA" => Ok(RecordType::TLSA),
            "TXT" => Ok(RecordType::TXT),
            "ANY" | "*" => Ok(RecordType::ANY),
            "AXFR" => Ok(RecordType::AXFR),
            _ => Err(ProtoErrorKind::UnknownRecordTypeStr(str.to_string()).into()),
        }
    }
}

impl From<u16> for RecordType {
    /// Convert from `u16` to `RecordType`
    ///
    /// ```
    /// use trust_dns_proto::rr::record_type::RecordType;
    ///
    /// let var = RecordType::from(1);
    /// assert_eq!(RecordType::A, var);
    /// ```
    fn from(value: u16) -> Self {
        match value {
            1 => RecordType::A,
            28 => RecordType::AAAA,
            255 => RecordType::ANY,
            252 => RecordType::AXFR,
            257 => RecordType::CAA,
            5 => RecordType::CNAME,
            15 => RecordType::MX,
            2 => RecordType::NS,
            10 => RecordType::NULL,
            41 => RecordType::OPT,
            12 => RecordType::PTR,
            6 => RecordType::SOA,
            33 => RecordType::SRV,
            52 => RecordType::TLSA,
            16 => RecordType::TXT,
            #[cfg(feature = "dnssec")]
            48/*DNSKEY*/ |
            43/*DS*/ |
            25/*KEY*/ |
            47/*NSEC*/|
            50/*NSEC3*/|
            51/*NSEC3PARAM*/|
            46/*RRSIG*/|
            24/*SIG*/ => RecordType::DNSSEC(DNSSECRecordType::from(value)),
            // all unknown record types
            _ => RecordType::Unknown(value),
        }
    }
}

impl BinEncodable for RecordType {
    fn emit(&self, encoder: &mut BinEncoder) -> ProtoResult<()> {
        encoder.emit_u16((*self).into())
    }
}

impl<'r> BinDecodable<'r> for RecordType {
    fn read(decoder: &mut BinDecoder) -> ProtoResult<Self> {
        decoder.read_u16().map(Self::from)
    }
}

// TODO make these a macro...

/// Convert from RecordType to &str
///
/// ```
/// use std::convert::From;
/// use trust_dns_proto::rr::record_type::RecordType;
///
/// let var: &'static str = From::from(RecordType::A);
/// assert_eq!("A", var);
///
/// let var: &'static str = RecordType::A.into();
/// assert_eq!("A", var);
/// ```
impl From<RecordType> for &'static str {
    fn from(rt: RecordType) -> &'static str {
        match rt {
            RecordType::A => "A",
            RecordType::AAAA => "AAAA",
            RecordType::ANY => "ANY",
            RecordType::AXFR => "AXFR",
            RecordType::CAA => "CAA",
            RecordType::CNAME => "CNAME",
            RecordType::IXFR => "IXFR",
            RecordType::MX => "MX",
            RecordType::NULL => "NULL",
            RecordType::NS => "NS",
            RecordType::OPT => "OPT",
            RecordType::PTR => "PTR",
            RecordType::SOA => "SOA",
            RecordType::SRV => "SRV",
            RecordType::TLSA => "TLSA",
            RecordType::TXT => "TXT",
            #[cfg(feature = "dnssec")]
            RecordType::DNSSEC(rt) => rt.into(),
            RecordType::Unknown(_) => "Unknown",
        }
    }
}

/// Convert from RecordType to &str
///
/// ```
/// use std::convert::From;
/// use trust_dns_proto::rr::record_type::RecordType;
///
/// let var: u16 = RecordType::A.into();
/// assert_eq!(1, var);
/// ```
impl From<RecordType> for u16 {
    fn from(rt: RecordType) -> Self {
        match rt {
            RecordType::A => 1,
            RecordType::AAAA => 28,
            RecordType::ANY => 255,
            RecordType::AXFR => 252,
            RecordType::CAA => 257,
            RecordType::CNAME => 5,
            RecordType::IXFR => 251,
            RecordType::MX => 15,
            RecordType::NS => 2,
            RecordType::NULL => 10,
            RecordType::OPT => 41,
            RecordType::PTR => 12,
            RecordType::SOA => 6,
            RecordType::SRV => 33,
            RecordType::TLSA => 52,
            RecordType::TXT => 16,
            #[cfg(feature = "dnssec")]
            RecordType::DNSSEC(rt) => rt.into(),
            RecordType::Unknown(code) => code,
        }
    }
}

impl PartialOrd<RecordType> for RecordType {
    fn partial_cmp(&self, other: &RecordType) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for RecordType {
    fn cmp(&self, other: &Self) -> Ordering {
        u16::from(*self).cmp(&u16::from(*other))
    }
}

impl Display for RecordType {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        f.write_str(Into::<&str>::into(*self))
    }
}

#[test]
fn test_order() {
    let ordered = vec![
        RecordType::NULL,
        RecordType::A,
        RecordType::NS,
        RecordType::CNAME,
        RecordType::SOA,
        RecordType::PTR,
        RecordType::MX,
        RecordType::TXT,
        RecordType::AAAA,
        RecordType::SRV,
        RecordType::AXFR,
        RecordType::ANY,
    ];

    let mut unordered = vec![
        RecordType::ANY,
        RecordType::NULL,
        RecordType::AXFR,
        RecordType::A,
        RecordType::NS,
        RecordType::SOA,
        RecordType::SRV,
        RecordType::PTR,
        RecordType::MX,
        RecordType::CNAME,
        RecordType::TXT,
        RecordType::AAAA,
    ];

    unordered.sort();

    for rtype in unordered.clone() {
        println!("u16 for {:?}: {}", rtype, u16::from(rtype));
    }

    assert_eq!(5.partial_cmp(&28), Some(Ordering::Less));

    assert_eq!(ordered, unordered);
}
<|endoftext|>


<commit_before>//! Test script with a simple instrument using `VoiceArray`.
//!
//! The test creates an instrument that can play up to five sine wavs at
//! a time. Then, in the main loop, we check for MIDI events and tick the
//! instrument, sendingn its output to a speaker.

extern crate oxcable;

#[cfg(not(test))]
mod instrument {
    use oxcable::io::midi::MidiIn;
    use oxcable::oscillator::*;
    use oxcable::types::{AudioDevice, MessageReceiver, MidiDevice, MidiEvent,
            MidiMessage, Sample, Time};
    use oxcable::voice_array::VoiceArray;
    use oxcable::utils::helpers::midi_note_to_freq;

    struct MyVoice {
        osc: Oscillator,
        playing: bool
    }

    pub struct MyInstrument {
        voices: VoiceArray<MyVoice>,
        midi: MidiIn
    }

    impl MyInstrument {
        pub fn new(midi: MidiIn) -> MyInstrument {
            // Initialize five voices
            let mut voices = Vec::new();
            for _ in 0..5 {
                voices.push(MyVoice {
                    osc: Oscillator::new(Sine),
                    playing: false,
                });
            }

            // Move our voices into the VoiceArray
            MyInstrument {
                voices: VoiceArray::new(voices),
                midi: midi,
            }
        }

        fn handle_event(&mut self, event: MidiEvent) {
            match event.payload {
                MidiMessage::NoteOn(note, _) => {
                    // For a note on, get a new voice to trigger
                    let voice = self.voices.note_on(note);

                    // Mark the voice as playing
                    voice.playing = true;

                    // Set the oscillator frequency to the new note
                    voice.osc.handle_message(SetFreq(midi_note_to_freq(note)));
                },
                MidiMessage::NoteOff(note, _) => {
                    // Find the voice playing this note...
                    let voice = self.voices.note_off(note);

                    // If we found one, stop it from playing
                    voice.map_or((), |d| {
                        d.playing = true;
                    });
                },
                _ => ()
            }
        }
    }

    impl AudioDevice for MyInstrument {
        fn num_inputs(&self) -> usize { 0 }
        fn num_outputs(&self) -> usize { 1 }
        fn tick(&mut self, t: Time, _: &[Sample], outputs: &mut[Sample]) {
            // First handle any events
            for event in self.midi.get_events(t) {
                self.handle_event(event);
            }

            // For each voice in the array...
            outputs[0] = 0.0;
            for voice in self.voices.iter_mut() {
                // Tick the oscillator
                let input = [];
                let mut output = [0.0];
                voice.osc.tick(t, &input, &mut output);

                // If this oscillator is playing, then add it to the output
                // signal
                if voice.playing {
                    outputs[0] += output[0];
                }
            }
        }
    }
}

#[cfg(not(test))]
fn main() {
    use oxcable::chain::{DeviceChain, Tick};
    use oxcable::io::audio::AudioEngine;
    use oxcable::io::midi::MidiEngine;
    use self::instrument::MyInstrument;

    println!("Initializing signal chain...");
    let audio_engine = AudioEngine::with_buffer_size(256).unwrap();
    let midi_engine = MidiEngine::open().unwrap();
    let mut chain = DeviceChain::from(
        MyInstrument::new(midi_engine.choose_input().unwrap())
    ).into(
        audio_engine.default_output(1).unwrap()
    );

    println!("Playing. Press Enter to quit...");
    chain.tick_until_enter();
    println!("Done!");
}
<commit_msg>Fix voice array test<commit_after>//! Test script with a simple instrument using `VoiceArray`.
//!
//! The test creates an instrument that can play up to five sine wavs at
//! a time. Then, in the main loop, we check for MIDI events and tick the
//! instrument, sendingn its output to a speaker.

extern crate oxcable;

#[cfg(not(test))]
mod instrument {
    use oxcable::io::midi::MidiIn;
    use oxcable::oscillator::*;
    use oxcable::types::{AudioDevice, MessageReceiver, MidiDevice, MidiEvent,
            MidiMessage, Sample, Time};
    use oxcable::voice_array::VoiceArray;
    use oxcable::utils::helpers::midi_note_to_freq;

    struct MyVoice {
        osc: Oscillator,
        playing: bool
    }

    pub struct MyInstrument {
        voices: VoiceArray<MyVoice>,
        midi: MidiIn
    }

    impl MyInstrument {
        pub fn new(midi: MidiIn) -> MyInstrument {
            // Initialize five voices
            let mut voices = Vec::new();
            for _ in 0..5 {
                voices.push(MyVoice {
                    osc: Oscillator::new(Sine),
                    playing: false,
                });
            }

            // Move our voices into the VoiceArray
            MyInstrument {
                voices: VoiceArray::new(voices),
                midi: midi,
            }
        }

        fn handle_event(&mut self, event: MidiEvent) {
            match event.payload {
                MidiMessage::NoteOn(note, _) => {
                    // For a note on, get a new voice to trigger
                    let voice = self.voices.note_on(note);

                    // Mark the voice as playing
                    voice.playing = true;

                    // Set the oscillator frequency to the new note
                    voice.osc.handle_message(SetFreq(midi_note_to_freq(note)));
                },
                MidiMessage::NoteOff(note, _) => {
                    // Find the voice playing this note...
                    let voice = self.voices.note_off(note);

                    // If we found one, stop it from playing
                    voice.map_or((), |d| {
                        d.playing = false;
                    });
                },
                _ => ()
            }
        }
    }

    impl AudioDevice for MyInstrument {
        fn num_inputs(&self) -> usize { 0 }
        fn num_outputs(&self) -> usize { 1 }
        fn tick(&mut self, t: Time, _: &[Sample], outputs: &mut[Sample]) {
            // First handle any events
            for event in self.midi.get_events(t) {
                self.handle_event(event);
            }

            // For each voice in the array...
            outputs[0] = 0.0;
            for voice in self.voices.iter_mut() {
                // Tick the oscillator
                let input = [];
                let mut output = [0.0];
                voice.osc.tick(t, &input, &mut output);

                // If this oscillator is playing, then add it to the output
                // signal
                if voice.playing {
                    outputs[0] += output[0];
                }
            }
        }
    }
}

#[cfg(not(test))]
fn main() {
    use oxcable::chain::{DeviceChain, Tick};
    use oxcable::io::audio::AudioEngine;
    use oxcable::io::midi::MidiEngine;
    use self::instrument::MyInstrument;

    println!("Initializing signal chain...");
    let audio_engine = AudioEngine::with_buffer_size(256).unwrap();
    let midi_engine = MidiEngine::open().unwrap();
    let mut chain = DeviceChain::from(
        MyInstrument::new(midi_engine.choose_input().unwrap())
    ).into(
        audio_engine.default_output(1).unwrap()
    );

    println!("Playing. Press Enter to quit...");
    chain.tick_until_enter();
    println!("Done!");
}
<|endoftext|>


<commit_before>//! Types and functions related to PG's and Sqlite's `ON CONFLICT` clause
//!
//! See [the methods on `InsertStatement`](../../query_builder/struct.InsertStatement.html#impl-1)
//! for usage examples.

mod on_conflict_actions;
mod on_conflict_clause;
mod on_conflict_extension;
mod on_conflict_target;

pub use self::on_conflict_actions::excluded;
pub use self::on_conflict_extension::*;
pub use self::on_conflict_target::{ConflictTarget, OnConflictTarget};

#[cfg(feature = "postgres")]
pub use self::on_conflict_target::*;
<commit_msg>Remove unneseccery attrubutes<commit_after>//! Types and functions related to PG's and Sqlite's `ON CONFLICT` clause
//!
//! See [the methods on `InsertStatement`](../../query_builder/struct.InsertStatement.html#impl-1)
//! for usage examples.

mod on_conflict_actions;
mod on_conflict_clause;
mod on_conflict_extension;
mod on_conflict_target;

pub use self::on_conflict_actions::excluded;
pub use self::on_conflict_extension::*;
pub use self::on_conflict_target::*;
<|endoftext|>


<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::env;
use std::ffi::OsString;

use common::ui::UI;
use hcore::crypto::CACHE_KEY_PATH_ENV_VAR;
use hcore::env as henv;
use hcore::fs::CACHE_KEY_PATH;
use hcore::os::users;

use config;
use error::Result;

pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
    try!(inner::rerun_with_sudo_if_needed(ui));

    // If the `$HAB_ORIGIN` environment variable is not present, then see if a default is set in
    // the CLI config. If so, set it as the `$HAB_ORIGIN` environment variable for the `hab-studio`
    // or `docker` execv call.
    if henv::var("HAB_ORIGIN").is_err() {
        let config = try!(config::load_with_sudo_user());
        if let Some(default_origin) = config.origin {
            debug!("Setting default origin {} via CLI config", &default_origin);
            env::set_var("HAB_ORIGIN", default_origin);
        }
    }

    // If the `$HAB_CACHE_KEY_PATH` environment variable is not present, check if we are running
    // under a `sudo` invocation. If so, determine the non-root user that issued the command in
    // order to set their key cache location in the environment variable. This is done so that the
    // `hab-studio` command will find the correct key cache or so that the correct directory will
    // be volume mounted when used with Docker.
    if henv::var(CACHE_KEY_PATH_ENV_VAR).is_err() {
        if let Some(sudo_user) = henv::sudo_user() {
            if let Some(home) = users::get_home_for_user(&sudo_user) {
                let cache_key_path = home.join(format!(".{}", CACHE_KEY_PATH));
                debug!("Setting cache_key_path for SUDO_USER={} to: {}",
                       &sudo_user,
                       cache_key_path.display());
                env::set_var(CACHE_KEY_PATH_ENV_VAR, cache_key_path);
                // Prevent any inner `hab` invocations from triggering similar logic: we will be
                // operating in the context `hab-studio` which is running with rootlike privileges.
                env::remove_var("SUDO_USER");
            }
        }
    }

    inner::start(ui, args)
}

#[cfg(target_os = "linux")]
mod inner {
    use std::env;
    use std::ffi::OsString;
    use std::path::PathBuf;
    use std::str::FromStr;

    use common::ui::UI;
    use hcore::crypto::{init, default_cache_key_path};
    use hcore::env as henv;
    use hcore::fs::{am_i_root, find_command};
    use hcore::os::process;
    use hcore::package::PackageIdent;

    use error::{Error, Result};
    use exec;

    const STUDIO_CMD: &'static str = "hab-studio";
    const STUDIO_CMD_ENVVAR: &'static str = "HAB_STUDIO_BINARY";
    const STUDIO_PACKAGE_IDENT: &'static str = "core/hab-studio";
    const SUDO_CMD: &'static str = "sudo";

    pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let command = match henv::var(STUDIO_CMD_ENVVAR) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let ident = try!(PackageIdent::from_str(STUDIO_PACKAGE_IDENT));
                try!(exec::command_from_pkg(ui,
                                            STUDIO_CMD,
                                            &ident,
                                            &default_cache_key_path(None),
                                            0))
            }
        };

        if let Some(cmd) = find_command(command.to_string_lossy().as_ref()) {
            try!(process::become_command(cmd, args));
        } else {
            return Err(Error::ExecCommandNotFound(command.to_string_lossy().into_owned()));
        }
        Ok(())
    }

    pub fn rerun_with_sudo_if_needed(ui: &mut UI) -> Result<()> {
        // If I have root permissions, early return, we are done.
        if am_i_root() {
            return Ok(());
        }

        // Otherwise we will try to re-run this program using `sudo`
        match find_command(SUDO_CMD) {
            Some(sudo_prog) => {
                let mut args: Vec<OsString> =
                    vec!["-p".into(), "[sudo hab-studio] password for %u: ".into(), "-E".into()];
                args.append(&mut env::args_os().collect());
                Ok(try!(process::become_command(sudo_prog, args)))
            }
            None => {
                try!(ui.warn(format!("Could not find the `{}' command, is it in your PATH?",
                                     SUDO_CMD)));
                try!(ui.warn("Running Habitat Studio requires root or administrator privileges. \
                              Please retry this command as a super user or use a \
                              privilege-granting facility such as sudo."));
                try!(ui.br());
                Err(Error::RootRequired)
            }
        }
    }
}

#[cfg(not(target_os = "linux"))]
mod inner {
    use std::env;
    use std::ffi::OsString;
    use std::process::{Command, Stdio};

    use common::ui::UI;
    use hcore::crypto::default_cache_key_path;
    use hcore::env as henv;
    use hcore::fs::{CACHE_KEY_PATH, find_command};
    use hcore::os::process;

    use error::{Error, Result};
    use VERSION;

    const DOCKER_CMD: &'static str = "docker";
    const DOCKER_CMD_ENVVAR: &'static str = "HAB_DOCKER_BINARY";
    const DOCKER_IMAGE: &'static str = "habitat-docker-registry.bintray.io/studio";
    const DOCKER_IMAGE_ENVVAR: &'static str = "HAB_DOCKER_STUDIO_IMAGE";
    const DOCKER_OPS: &'static str = "HAB_DOCKER_OPS";

    pub fn start(_ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let docker = henv::var(DOCKER_CMD_ENVVAR).unwrap_or(DOCKER_CMD.to_string());

        let cmd = match find_command(&docker) {
            Some(cmd) => cmd,
            None => return Err(Error::ExecCommandNotFound(docker.to_string())),
        };

        let child = Command::new(&cmd)
            .arg("pull")
            .arg(&image_identifier())
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .expect("docker failed to start");

        let output = child.wait_with_output()
            .expect("failed to wait on child");

        if output.status.success() {
            debug!("Docker image is reachable. Proceeding with launching docker.");
        } else {
            debug!("Docker image is unreachable. Exit code = {:?}",
                   output.status);

            let err_output = String::from_utf8(output.stderr).unwrap();

            if err_output.contains("image") && err_output.contains("not found") {
                return Err(Error::DockerImageNotFound(image_identifier().to_string()));
            } else if err_output.contains("Cannot connect to the Docker daemon") {
                return Err(Error::DockerDaemonDown);
            } else {
                return Err(Error::DockerNetworkDown(image_identifier().to_string()));
            }
        }

        let mut cmd_args: Vec<OsString> = vec!["run".into(),
                                               "--rm".into(),
                                               "--tty".into(),
                                               "--interactive".into(),
                                               "--privileged".into()];

        // All the args already placed in `cmd_args` are things that we don't want to insert again.
        // Later args such as `--env` will overwrite any options (potentially) set mistakenly here.
        if let Ok(ops) = henv::var(DOCKER_OPS) {
            let ops = ops.split(" ")
                .map(|v| v.into())
                // Ensure we're not passing something like `--tty` again here.
                .filter(|v| !cmd_args.contains(v))
                .collect::<Vec<_>>();
            debug!("Docker ops originating from DOCKER_OPS = {:?}", ops);
            cmd_args.extend_from_slice(ops.as_slice());
        }

        let env_vars = vec!["HAB_DEPOT_URL", "HAB_ORIGIN", "http_proxy", "https_proxy"];
        for var in env_vars {
            if let Ok(val) = henv::var(var) {
                debug!("Propagating environment variable into container: {}={}",
                       var,
                       val);
                cmd_args.push("--env".into());
                cmd_args.push(format!("{}={}", var, val).into());
            }
        }

        cmd_args.push("--volume".into());
        cmd_args.push("/var/run/docker.sock:/var/run/docker.sock".into());
        cmd_args.push("--volume".into());
        cmd_args.push(format!("{}:/{}",
                              default_cache_key_path(None).to_string_lossy(),
                              CACHE_KEY_PATH)
            .into());
        cmd_args.push("--volume".into());
        cmd_args.push(format!("{}:/src", env::current_dir().unwrap().to_string_lossy()).into());

        cmd_args.push(image_identifier().into());
        cmd_args.extend_from_slice(args.as_slice());

        for var in vec!["http_proxy", "https_proxy"] {
            if let Ok(_) = henv::var(var) {
                debug!("Unsetting proxy environment variable '{}' before calling `{}'",
                       var,
                       docker);
                env::remove_var(var);
            }
        }

        debug!("Docker arguments = {:?}", cmd_args);
        Ok(try!(process::become_command(cmd, cmd_args)))
    }

    pub fn rerun_with_sudo_if_needed(_ui: &mut UI) -> Result<()> {
        // No sudo calls necessary here--we are calling `docker` commands instead
        Ok(())
    }

    /// Returns the Docker Studio image with tag for the desired version which corresponds to the
    /// same version (minus release) as this program.
    fn image_identifier() -> String {
        let version: Vec<&str> = VERSION.split("/").collect();
        henv::var(DOCKER_IMAGE_ENVVAR).unwrap_or(format!("{}:{}", DOCKER_IMAGE, version[0]))
    }

    #[cfg(test)]
    mod tests {
        use super::{image_identifier, DOCKER_IMAGE};
        use VERSION;

        #[test]
        fn retrieve_image_identifier() {
            assert_eq!(image_identifier(), format!("{}:{}", DOCKER_IMAGE, VERSION));
        }
    }
}
<commit_msg>Renamed  to<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::env;
use std::ffi::OsString;

use common::ui::UI;
use hcore::crypto::CACHE_KEY_PATH_ENV_VAR;
use hcore::env as henv;
use hcore::fs::CACHE_KEY_PATH;
use hcore::os::users;

use config;
use error::Result;

pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
    try!(inner::rerun_with_sudo_if_needed(ui));

    // If the `$HAB_ORIGIN` environment variable is not present, then see if a default is set in
    // the CLI config. If so, set it as the `$HAB_ORIGIN` environment variable for the `hab-studio`
    // or `docker` execv call.
    if henv::var("HAB_ORIGIN").is_err() {
        let config = try!(config::load_with_sudo_user());
        if let Some(default_origin) = config.origin {
            debug!("Setting default origin {} via CLI config", &default_origin);
            env::set_var("HAB_ORIGIN", default_origin);
        }
    }

    // If the `$HAB_CACHE_KEY_PATH` environment variable is not present, check if we are running
    // under a `sudo` invocation. If so, determine the non-root user that issued the command in
    // order to set their key cache location in the environment variable. This is done so that the
    // `hab-studio` command will find the correct key cache or so that the correct directory will
    // be volume mounted when used with Docker.
    if henv::var(CACHE_KEY_PATH_ENV_VAR).is_err() {
        if let Some(sudo_user) = henv::sudo_user() {
            if let Some(home) = users::get_home_for_user(&sudo_user) {
                let cache_key_path = home.join(format!(".{}", CACHE_KEY_PATH));
                debug!("Setting cache_key_path for SUDO_USER={} to: {}",
                       &sudo_user,
                       cache_key_path.display());
                env::set_var(CACHE_KEY_PATH_ENV_VAR, cache_key_path);
                // Prevent any inner `hab` invocations from triggering similar logic: we will be
                // operating in the context `hab-studio` which is running with rootlike privileges.
                env::remove_var("SUDO_USER");
            }
        }
    }

    inner::start(ui, args)
}

#[cfg(target_os = "linux")]
mod inner {
    use std::env;
    use std::ffi::OsString;
    use std::path::PathBuf;
    use std::str::FromStr;

    use common::ui::UI;
    use hcore::crypto::{init, default_cache_key_path};
    use hcore::env as henv;
    use hcore::fs::{am_i_root, find_command};
    use hcore::os::process;
    use hcore::package::PackageIdent;

    use error::{Error, Result};
    use exec;

    const STUDIO_CMD: &'static str = "hab-studio";
    const STUDIO_CMD_ENVVAR: &'static str = "HAB_STUDIO_BINARY";
    const STUDIO_PACKAGE_IDENT: &'static str = "core/hab-studio";
    const SUDO_CMD: &'static str = "sudo";

    pub fn start(ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let command = match henv::var(STUDIO_CMD_ENVVAR) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let ident = try!(PackageIdent::from_str(STUDIO_PACKAGE_IDENT));
                try!(exec::command_from_pkg(ui,
                                            STUDIO_CMD,
                                            &ident,
                                            &default_cache_key_path(None),
                                            0))
            }
        };

        if let Some(cmd) = find_command(command.to_string_lossy().as_ref()) {
            try!(process::become_command(cmd, args));
        } else {
            return Err(Error::ExecCommandNotFound(command.to_string_lossy().into_owned()));
        }
        Ok(())
    }

    pub fn rerun_with_sudo_if_needed(ui: &mut UI) -> Result<()> {
        // If I have root permissions, early return, we are done.
        if am_i_root() {
            return Ok(());
        }

        // Otherwise we will try to re-run this program using `sudo`
        match find_command(SUDO_CMD) {
            Some(sudo_prog) => {
                let mut args: Vec<OsString> =
                    vec!["-p".into(), "[sudo hab-studio] password for %u: ".into(), "-E".into()];
                args.append(&mut env::args_os().collect());
                Ok(try!(process::become_command(sudo_prog, args)))
            }
            None => {
                try!(ui.warn(format!("Could not find the `{}' command, is it in your PATH?",
                                     SUDO_CMD)));
                try!(ui.warn("Running Habitat Studio requires root or administrator privileges. \
                              Please retry this command as a super user or use a \
                              privilege-granting facility such as sudo."));
                try!(ui.br());
                Err(Error::RootRequired)
            }
        }
    }
}

#[cfg(not(target_os = "linux"))]
mod inner {
    use std::env;
    use std::ffi::OsString;
    use std::process::{Command, Stdio};

    use common::ui::UI;
    use hcore::crypto::default_cache_key_path;
    use hcore::env as henv;
    use hcore::fs::{CACHE_KEY_PATH, find_command};
    use hcore::os::process;

    use error::{Error, Result};
    use VERSION;

    const DOCKER_CMD: &'static str = "docker";
    const DOCKER_CMD_ENVVAR: &'static str = "HAB_DOCKER_BINARY";
    const DOCKER_IMAGE: &'static str = "habitat-docker-registry.bintray.io/studio";
    const DOCKER_IMAGE_ENVVAR: &'static str = "HAB_DOCKER_STUDIO_IMAGE";
    const DOCKER_OPTS: &'static str = "HAB_DOCKER_OPTS";

    pub fn start(_ui: &mut UI, args: Vec<OsString>) -> Result<()> {
        let docker = henv::var(DOCKER_CMD_ENVVAR).unwrap_or(DOCKER_CMD.to_string());

        let cmd = match find_command(&docker) {
            Some(cmd) => cmd,
            None => return Err(Error::ExecCommandNotFound(docker.to_string())),
        };

        let child = Command::new(&cmd)
            .arg("pull")
            .arg(&image_identifier())
            .stdout(Stdio::inherit())
            .stderr(Stdio::inherit())
            .spawn()
            .expect("docker failed to start");

        let output = child.wait_with_output()
            .expect("failed to wait on child");

        if output.status.success() {
            debug!("Docker image is reachable. Proceeding with launching docker.");
        } else {
            debug!("Docker image is unreachable. Exit code = {:?}",
                   output.status);

            let err_output = String::from_utf8(output.stderr).unwrap();

            if err_output.contains("image") && err_output.contains("not found") {
                return Err(Error::DockerImageNotFound(image_identifier().to_string()));
            } else if err_output.contains("Cannot connect to the Docker daemon") {
                return Err(Error::DockerDaemonDown);
            } else {
                return Err(Error::DockerNetworkDown(image_identifier().to_string()));
            }
        }

        let mut cmd_args: Vec<OsString> = vec!["run".into(),
                                               "--rm".into(),
                                               "--tty".into(),
                                               "--interactive".into(),
                                               "--privileged".into()];

        // All the args already placed in `cmd_args` are things that we don't want to insert again.
        // Later args such as `--env` will overwrite any options (potentially) set mistakenly here.
        if let Ok(ops) = henv::var(DOCKER_OPTS) {
            let ops = ops.split(" ")
                .map(|v| v.into())
                // Ensure we're not passing something like `--tty` again here.
                .filter(|v| !cmd_args.contains(v))
                .collect::<Vec<_>>();
            debug!("Docker ops originating from DOCKER_OPTS = {:?}", ops);
            cmd_args.extend_from_slice(ops.as_slice());
        }

        let env_vars = vec!["HAB_DEPOT_URL", "HAB_ORIGIN", "http_proxy", "https_proxy"];
        for var in env_vars {
            if let Ok(val) = henv::var(var) {
                debug!("Propagating environment variable into container: {}={}",
                       var,
                       val);
                cmd_args.push("--env".into());
                cmd_args.push(format!("{}={}", var, val).into());
            }
        }

        cmd_args.push("--volume".into());
        cmd_args.push("/var/run/docker.sock:/var/run/docker.sock".into());
        cmd_args.push("--volume".into());
        cmd_args.push(format!("{}:/{}",
                              default_cache_key_path(None).to_string_lossy(),
                              CACHE_KEY_PATH)
            .into());
        cmd_args.push("--volume".into());
        cmd_args.push(format!("{}:/src", env::current_dir().unwrap().to_string_lossy()).into());

        cmd_args.push(image_identifier().into());
        cmd_args.extend_from_slice(args.as_slice());

        for var in vec!["http_proxy", "https_proxy"] {
            if let Ok(_) = henv::var(var) {
                debug!("Unsetting proxy environment variable '{}' before calling `{}'",
                       var,
                       docker);
                env::remove_var(var);
            }
        }

        debug!("Docker arguments = {:?}", cmd_args);
        Ok(try!(process::become_command(cmd, cmd_args)))
    }

    pub fn rerun_with_sudo_if_needed(_ui: &mut UI) -> Result<()> {
        // No sudo calls necessary here--we are calling `docker` commands instead
        Ok(())
    }

    /// Returns the Docker Studio image with tag for the desired version which corresponds to the
    /// same version (minus release) as this program.
    fn image_identifier() -> String {
        let version: Vec<&str> = VERSION.split("/").collect();
        henv::var(DOCKER_IMAGE_ENVVAR).unwrap_or(format!("{}:{}", DOCKER_IMAGE, version[0]))
    }

    #[cfg(test)]
    mod tests {
        use super::{image_identifier, DOCKER_IMAGE};
        use VERSION;

        #[test]
        fn retrieve_image_identifier() {
            assert_eq!(image_identifier(), format!("{}:{}", DOCKER_IMAGE, VERSION));
        }
    }
}
<|endoftext|>


<commit_before>//! The root scope of all timely dataflow computations.

use std::rc::Rc;
use std::cell::RefCell;

use progress::timestamp::RootTimestamp;
use progress::{Timestamp, Operate, Subgraph};
use progress::nested::{Source, Target};
use timely_communication::{Allocate, Data};
use {Push, Pull};

use super::Scope;

/// A `Root` is the entry point to a timely dataflow computation. It wraps a `Allocate`,
/// and has a list of child `Operate`s. The primary intended use of `Root` is through its
/// implementation of the `Scope` trait.
pub struct Root<A: Allocate> {
    allocator: Rc<RefCell<A>>,
    graph: Rc<RefCell<Vec<Box<Operate<RootTimestamp>>>>>,
    identifiers: Rc<RefCell<usize>>,
}

impl<A: Allocate> Root<A> {
    /// Allocates a new `Root` bound to a channel allocator.
    pub fn new(c: A) -> Root<A> {
        let mut result = Root {
            allocator: Rc::new(RefCell::new(c)),
            graph: Rc::new(RefCell::new(Vec::new())),
            identifiers: Rc::new(RefCell::new(0)),
        };

        // LOGGING
        if cfg!(feature = "logging") {
            ::logging::initialize(&mut result);
        }

        result
    }
    /// Performs one step of the computation.
    ///
    /// A step gives each dataflow operator a chance to run, and is the
    /// main way to ensure that a computation procedes.
    pub fn step(&mut self) -> bool {

        if cfg!(feature = "logging") {
            ::logging::flush_logs();
        }

        let mut active = false;
        for scope in self.graph.borrow_mut().iter_mut() {
            let sub_active = scope.pull_internal_progress(&mut [], &mut [], &mut []);
            active = active || sub_active;
        }
        active
    }
    /// Calls `self.step()` as long as `func` evaluates to true.
    pub fn step_while<F: FnMut()->bool>(&mut self, mut func: F) {
        while func() { self.step(); }
    }

    /// The index of the worker out of its peers.
    pub fn index(&self) -> usize { self.allocator.borrow().index() }
    /// The total number of peer workers.
    pub fn peers(&self) -> usize { self.allocator.borrow().peers() }
}

impl<A: Allocate> Scope for Root<A> {
    type Timestamp = RootTimestamp;

    fn name(&self) -> String { format!("Worker[{}]", self.allocator.borrow().index()) }
    fn addr(&self) -> Vec<usize> { vec![self.allocator.borrow().index() ] }
    fn add_edge(&self, _source: Source, _target: Target) {
        panic!("Root::connect(): root doesn't maintain edges; who are you, how did you get here?")
    }

    fn add_operator<SC: Operate<Self::Timestamp>+'static>(&mut self, scope: SC) -> usize {
        let index = self.graph.borrow().len();
        self.add_operator_with_index(scope, index);
        index
    }

    fn add_operator_with_index<SC: Operate<RootTimestamp>+'static>(&mut self, mut scope: SC, index: usize) {
        assert_eq!(index, self.graph.borrow().len());

        scope.get_internal_summary();
        scope.set_external_summary(Vec::new(), &mut []);
        self.graph.borrow_mut().push(Box::new(scope));
    }
    fn new_identifier(&mut self) -> usize {
        *self.identifiers.borrow_mut() += 1;
        *self.identifiers.borrow() - 1
    }

    fn new_subscope<T: Timestamp>(&mut self) -> Subgraph<RootTimestamp, T>  {
        let addr = vec![self.allocator.borrow().index()];
        Subgraph::new_from(&mut (*self.allocator.borrow_mut()), self.graph.borrow().len(), addr)
    }
}

impl<A: Allocate> Allocate for Root<A> {
    fn index(&self) -> usize { self.allocator.borrow().index() }
    fn peers(&self) -> usize { self.allocator.borrow().peers() }
    fn allocate<D: Data>(&mut self) -> (Vec<Box<Push<D>>>, Box<Pull<D>>) {
        self.allocator.borrow_mut().allocate()
    }
}

impl<A: Allocate> Clone for Root<A> {
    fn clone(&self) -> Self {
        Root {
            allocator: self.allocator.clone(),
            graph: self.graph.clone(),
            identifiers: self.identifiers.clone(),
        }
    }
}
<commit_msg>added dataflow method to root, mimicing scoped<commit_after>//! The root scope of all timely dataflow computations.

use std::rc::Rc;
use std::cell::RefCell;

use progress::timestamp::RootTimestamp;
use progress::{Timestamp, Operate, Subgraph};
use progress::nested::{Source, Target};
use timely_communication::{Allocate, Data};
use {Push, Pull};

use super::{Scope, Child};

/// A `Root` is the entry point to a timely dataflow computation. It wraps a `Allocate`,
/// and has a list of child `Operate`s. The primary intended use of `Root` is through its
/// implementation of the `Scope` trait.
pub struct Root<A: Allocate> {
    allocator: Rc<RefCell<A>>,
    graph: Rc<RefCell<Vec<Box<Operate<RootTimestamp>>>>>,
    identifiers: Rc<RefCell<usize>>,
}

impl<A: Allocate> Root<A> {
    /// Allocates a new `Root` bound to a channel allocator.
    pub fn new(c: A) -> Root<A> {
        let mut result = Root {
            allocator: Rc::new(RefCell::new(c)),
            graph: Rc::new(RefCell::new(Vec::new())),
            identifiers: Rc::new(RefCell::new(0)),
        };

        // LOGGING
        if cfg!(feature = "logging") {
            ::logging::initialize(&mut result);
        }

        result
    }
    /// Performs one step of the computation.
    ///
    /// A step gives each dataflow operator a chance to run, and is the
    /// main way to ensure that a computation procedes.
    pub fn step(&mut self) -> bool {

        if cfg!(feature = "logging") {
            ::logging::flush_logs();
        }

        let mut active = false;
        for scope in self.graph.borrow_mut().iter_mut() {
            let sub_active = scope.pull_internal_progress(&mut [], &mut [], &mut []);
            active = active || sub_active;
        }
        active
    }
    /// Calls `self.step()` as long as `func` evaluates to true.
    pub fn step_while<F: FnMut()->bool>(&mut self, mut func: F) {
        while func() { self.step(); }
    }

    /// The index of the worker out of its peers.
    pub fn index(&self) -> usize { self.allocator.borrow().index() }
    /// The total number of peer workers.
    pub fn peers(&self) -> usize { self.allocator.borrow().peers() }

    /// Introduces a new dataflow constructed in the supplied closure.
    ///
    /// NOTE: This is the same code as in the `scoped` method for scopes, but it has been extracted
    /// so that the `Root` type does not need to implement `Scope`.
    pub fn dataflow<T: Timestamp, R, F:FnOnce(&mut Child<Self, T>)->R>(&mut self, func: F) -> R {
        let subscope = RefCell::new(self.new_subscope());

        let result = {
            let mut builder = Child {
                subgraph: &subscope,
                parent: self.clone(),
            };
            func(&mut builder)
        };

        let index = subscope.borrow().index;
        self.add_operator_with_index(subscope.into_inner(), index);

        result
    }}

impl<A: Allocate> Scope for Root<A> {
    type Timestamp = RootTimestamp;

    fn name(&self) -> String { format!("Worker[{}]", self.allocator.borrow().index()) }
    fn addr(&self) -> Vec<usize> { vec![self.allocator.borrow().index() ] }
    fn add_edge(&self, _source: Source, _target: Target) {
        panic!("Root::connect(): root doesn't maintain edges; who are you, how did you get here?")
    }

    fn add_operator<SC: Operate<Self::Timestamp>+'static>(&mut self, scope: SC) -> usize {
        let index = self.graph.borrow().len();
        self.add_operator_with_index(scope, index);
        index
    }

    fn add_operator_with_index<SC: Operate<RootTimestamp>+'static>(&mut self, mut scope: SC, index: usize) {
        assert_eq!(index, self.graph.borrow().len());

        scope.get_internal_summary();
        scope.set_external_summary(Vec::new(), &mut []);
        self.graph.borrow_mut().push(Box::new(scope));
    }
    fn new_identifier(&mut self) -> usize {
        *self.identifiers.borrow_mut() += 1;
        *self.identifiers.borrow() - 1
    }

    fn new_subscope<T: Timestamp>(&mut self) -> Subgraph<RootTimestamp, T>  {
        let addr = vec![self.allocator.borrow().index()];
        Subgraph::new_from(&mut (*self.allocator.borrow_mut()), self.graph.borrow().len(), addr)
    }
}

impl<A: Allocate> Allocate for Root<A> {
    fn index(&self) -> usize { self.allocator.borrow().index() }
    fn peers(&self) -> usize { self.allocator.borrow().peers() }
    fn allocate<D: Data>(&mut self) -> (Vec<Box<Push<D>>>, Box<Pull<D>>) {
        self.allocator.borrow_mut().allocate()
    }
}

impl<A: Allocate> Clone for Root<A> {
    fn clone(&self) -> Self {
        Root {
            allocator: self.allocator.clone(),
            graph: self.graph.clone(),
            identifiers: self.identifiers.clone(),
        }
    }
}
<|endoftext|>