<commit_before>/// The Toml Delete extensions

use toml::Value;

use tokenizer::Token;
use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueDeleteExt {

    /// Extension function for deleting a value in the current toml::Value document
    /// using a custom seperator.
    ///
    /// # Semantics
    ///
    /// The function does _not_ delete non-empty data structures. So deleting `array` from
    ///
    /// ```toml
    /// array = [ 1 ]
    /// ```
    ///
    /// does _not_ work.
    ///
    /// # Return value
    ///
    /// If the delete operation worked correctly, `Ok(Option<Value>)` is returned.
    ///
    /// The `Option<Value>` part is `None` if no value was actually removed as there was no value
    /// there. For example, if you're deleting `table.a` and the Table `table` has no key `a`, then
    /// `Ok(None)` is returned. Also, if you're deleting from an Array, but there is nothing in the
    /// array, or the array is shorter than the index you're deleting.
    /// If the delete operation actually removed something from the toml document, this value is
    /// returned as `Ok(Some(Value))`.
    ///
    /// On failure, `Err(e)` is returned
    ///
    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>>;

    /// Extension function for inserting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueinsertExt::insert_with_seperator`
    fn delete(&mut self, query: &String) -> Result<Option<Value>> {
        self.delete_with_seperator(query, '.')
    }

}

impl TomlValueDeleteExt for Value {

    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last_token = tokens.pop_last();

        if last_token.is_none() {
            match self {
                &mut Value::Table(ref mut tab) => {
                    match tokens {
                        Token::Identifier { ident, .. } => {
                            println!("Removing {} from {:?}", ident, tab);
                            Ok(tab.remove(&ident))
                        },
                        _ => Ok(None)
                    }
                },
                _ => unimplemented!()
            }
        } else {
            let mut val = try!(resolve(self, &tokens));
            Ok(None)
        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use error::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_delete_from_empty_document() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.delete_with_seperator(&String::from("a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_from_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_integer() {
        let mut toml : Value = toml_from_str(r#"
        value = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(1)));
    }

    #[test]
    fn test_delete_string() {
        let mut toml : Value = toml_from_str(r#"
        value = "foo"
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::String(_)));
        match res {
            Value::String(ref s) => assert_eq!("foo", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Table(_)));
        match res {
            Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Array(_)));
        match res {
            Value::Array(ref a) => assert!(a.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_nonempty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyTable(_)));
    }

    #[test]
    fn test_delete_nonempty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0]"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyArray(_)));
    }

}

<commit_msg>Impl Value::delete_with_seperator to fix test_delete_nonempty_table<commit_after>/// The Toml Delete extensions

use toml::Value;

use tokenizer::Token;
use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueDeleteExt {

    /// Extension function for deleting a value in the current toml::Value document
    /// using a custom seperator.
    ///
    /// # Semantics
    ///
    /// The function does _not_ delete non-empty data structures. So deleting `array` from
    ///
    /// ```toml
    /// array = [ 1 ]
    /// ```
    ///
    /// does _not_ work.
    ///
    /// # Return value
    ///
    /// If the delete operation worked correctly, `Ok(Option<Value>)` is returned.
    ///
    /// The `Option<Value>` part is `None` if no value was actually removed as there was no value
    /// there. For example, if you're deleting `table.a` and the Table `table` has no key `a`, then
    /// `Ok(None)` is returned. Also, if you're deleting from an Array, but there is nothing in the
    /// array, or the array is shorter than the index you're deleting.
    /// If the delete operation actually removed something from the toml document, this value is
    /// returned as `Ok(Some(Value))`.
    ///
    /// On failure, `Err(e)` is returned
    ///
    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>>;

    /// Extension function for inserting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueinsertExt::insert_with_seperator`
    fn delete(&mut self, query: &String) -> Result<Option<Value>> {
        self.delete_with_seperator(query, '.')
    }

}

impl TomlValueDeleteExt for Value {

    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last_token = tokens.pop_last();

        if last_token.is_none() {
            match self {
                &mut Value::Table(ref mut tab) => {
                    match tokens {
                        Token::Identifier { ident, .. } => {
                            if !tab.is_empty() {
                                let kind = ErrorKind::CannotDeleteNonEmptyTable(ident.clone());
                                Err(Error::from(kind))
                            } else {
                                Ok(tab.remove(&ident))
                            }
                        },
                        _ => Ok(None)
                    }
                },
                _ => unimplemented!()
            }
        } else {
            let mut val = try!(resolve(self, &tokens));
            Ok(None)
        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use error::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_delete_from_empty_document() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.delete_with_seperator(&String::from("a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_from_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_integer() {
        let mut toml : Value = toml_from_str(r#"
        value = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(1)));
    }

    #[test]
    fn test_delete_string() {
        let mut toml : Value = toml_from_str(r#"
        value = "foo"
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::String(_)));
        match res {
            Value::String(ref s) => assert_eq!("foo", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Table(_)));
        match res {
            Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Array(_)));
        match res {
            Value::Array(ref a) => assert!(a.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_nonempty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyTable(_)));
    }

    #[test]
    fn test_delete_nonempty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0]"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyArray(_)));
    }

}

<|endoftext|>


<commit_before>//! Cursor movement.

use std::fmt;
use std::ops;
use std::io::{self, Write, Error, ErrorKind, Read};
use async::async_stdin_until;
use std::time::{SystemTime, Duration};
use raw::CONTROL_SEQUENCE_TIMEOUT;
use numtoa::NumToA;

derive_csi_sequence!("Hide the cursor.", Hide, "?25l");
derive_csi_sequence!("Show the cursor.", Show, "?25h");

derive_csi_sequence!("Restore the cursor.", Restore, "u");
derive_csi_sequence!("Save the cursor.", Save, "s");

/// Goto some position ((1,1)-based).
///
/// # Why one-based?
///
/// ANSI escapes are very poorly designed, and one of the many odd aspects is being one-based. This
/// can be quite strange at first, but it is not that big of an obstruction once you get used to
/// it.
///
/// # Example
///
/// ```rust
/// extern crate termion;
///
/// fn main() {
///     print!("{}{}Stuff", termion::clear::All, termion::cursor::Goto(5, 3));
/// }
/// ```
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Goto(pub u16, pub u16);

impl From<Goto> for String {
    fn from(this: Goto) -> String {
        let (mut x, mut y) = ([0u8; 20], [0u8; 20]);
        ["\x1B[", this.1.numtoa_str(10, &mut x), ";", this.0.numtoa_str(10, &mut y), "H"].concat()
    }
}

impl Default for Goto {
    fn default() -> Goto {
        Goto(1, 1)
    }
}

impl fmt::Display for Goto {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        debug_assert!(self != &Goto(0, 0), "Goto is one-based.");
        f.write_str(&String::from(*self))
    }
}

/// Move cursor left.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Left(pub u16);

impl From<Left> for String {
    fn from(this: Left) -> String {
        let mut buf = [0u8; 20];
        ["\x1B[", this.0.numtoa_str(10, &mut buf), "D"].concat()
    }
}

impl fmt::Display for Left {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&String::from(*self))
    }
}

/// Move cursor right.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Right(pub u16);

impl From<Right> for String {
    fn from(this: Right) -> String {
        let mut buf = [0u8; 20];
        ["\x1B[", this.0.numtoa_str(10, &mut buf), "C"].concat()
    }
}

impl fmt::Display for Right {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&String::from(*self))
    }
}

/// Move cursor up.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Up(pub u16);

impl From<Up> for String {
    fn from(this: Up) -> String {
        let mut buf = [0u8; 20];
        ["\x1B[", this.0.numtoa_str(10, &mut buf), "A"].concat()
    }
}

impl fmt::Display for Up {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&String::from(*self))
    }
}

/// Move cursor down.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Down(pub u16);

impl From<Down> for String {
    fn from(this: Down) -> String {
        let mut buf = [0u8; 20];
        ["\x1B[", this.0.numtoa_str(10, &mut buf), "B"].concat()
    }
}

impl fmt::Display for Down {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&String::from(*self))
    }
}

/// Types that allow detection of the cursor position.
pub trait DetectCursorPos {
    /// Get the (1,1)-based cursor position from the terminal.
    fn cursor_pos(&mut self) -> io::Result<(u16, u16)>;
}

impl<W: Write> DetectCursorPos for W {
    fn cursor_pos(&mut self) -> io::Result<(u16, u16)> {
        let delimiter = b'R';
        let mut stdin = async_stdin_until(delimiter);

        // Where is the cursor?
        // Use `ESC [ 6 n`.
        write!(self, "\x1B[6n")?;
        self.flush()?;

        let mut buf: [u8; 1] = [0];
        let mut read_chars = Vec::new();

        let timeout = Duration::from_millis(CONTROL_SEQUENCE_TIMEOUT);
        let now = SystemTime::now();

        // Either consume all data up to R or wait for a timeout.
        while buf[0] != delimiter && now.elapsed().unwrap() < timeout {
            if stdin.read(&mut buf)? > 0 {
                read_chars.push(buf[0]);
            }
        }

        if read_chars.is_empty() {
            return Err(Error::new(ErrorKind::Other, "Cursor position detection timed out."));
        }

        // The answer will look like `ESC [ Cy ; Cx R`.

        read_chars.pop(); // remove trailing R.
        let read_str = String::from_utf8(read_chars).unwrap();
        let beg = read_str.rfind('[').unwrap();
        let coords: String = read_str.chars().skip(beg + 1).collect();
        let mut nums = coords.split(';');

        let cy = nums.next()
            .unwrap()
            .parse::<u16>()
            .unwrap();
        let cx = nums.next()
            .unwrap()
            .parse::<u16>()
            .unwrap();

        Ok((cx, cy))
    }
}

/// Hide the cursor for the lifetime of this struct.
/// It will hide the cursor on creation with from() and show it back on drop().
pub struct HideCursor<W: Write> {
    /// The output target.
    output: W,
}

impl<W: Write> HideCursor<W> {
    /// Create a hide cursor wrapper struct for the provided output and hides the cursor.
    pub fn from(mut output: W) -> Self {
        write!(output, "{}", Hide).expect("hide the cursor");
        HideCursor { output: output }
    }
}

impl<W: Write> Drop for HideCursor<W> {
    fn drop(&mut self) {
        write!(self, "{}", Show).expect("show the cursor");
    }
}

impl<W: Write> ops::Deref for HideCursor<W> {
    type Target = W;

    fn deref(&self) -> &W {
        &self.output
    }
}

impl<W: Write> ops::DerefMut for HideCursor<W> {
    fn deref_mut(&mut self) -> &mut W {
        &mut self.output
    }
}

impl<W: Write> Write for HideCursor<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.output.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.output.flush()
    }
}
<commit_msg>feature: changing cursor style<commit_after>//! Cursor movement.

use std::fmt;
use std::ops;
use std::io::{self, Write, Error, ErrorKind, Read};
use async::async_stdin_until;
use std::time::{SystemTime, Duration};
use raw::CONTROL_SEQUENCE_TIMEOUT;
use numtoa::NumToA;

derive_csi_sequence!("Hide the cursor.", Hide, "?25l");
derive_csi_sequence!("Show the cursor.", Show, "?25h");

derive_csi_sequence!("Restore the cursor.", Restore, "u");
derive_csi_sequence!("Save the cursor.", Save, "s");

derive_csi_sequence!("Change the cursor style to blinking block", BlinkingBlock, "\x31 q");
derive_csi_sequence!("Change the cursor style to steady block", SteadyBlock, "\x32 q");
derive_csi_sequence!("Change the cursor style to blinking underline", BlinkingUnderline, "\x33 q");
derive_csi_sequence!("Change the cursor style to steady underline", SteadyUnderline, "\x34 q");
derive_csi_sequence!("Change the cursor style to blinking bar", BlinkingBar, "\x35 q");
derive_csi_sequence!("Change the cursor style to steady bar", SteadyBar, "\x36 q");

/// Goto some position ((1,1)-based).
///
/// # Why one-based?
///
/// ANSI escapes are very poorly designed, and one of the many odd aspects is being one-based. This
/// can be quite strange at first, but it is not that big of an obstruction once you get used to
/// it.
///
/// # Example
///
/// ```rust
/// extern crate termion;
///
/// fn main() {
///     print!("{}{}Stuff", termion::clear::All, termion::cursor::Goto(5, 3));
/// }
/// ```
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Goto(pub u16, pub u16);

impl From<Goto> for String {
    fn from(this: Goto) -> String {
        let (mut x, mut y) = ([0u8; 20], [0u8; 20]);
        ["\x1B[", this.1.numtoa_str(10, &mut x), ";", this.0.numtoa_str(10, &mut y), "H"].concat()
    }
}

impl Default for Goto {
    fn default() -> Goto {
        Goto(1, 1)
    }
}

impl fmt::Display for Goto {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        debug_assert!(self != &Goto(0, 0), "Goto is one-based.");
        f.write_str(&String::from(*self))
    }
}

/// Move cursor left.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Left(pub u16);

impl From<Left> for String {
    fn from(this: Left) -> String {
        let mut buf = [0u8; 20];
        ["\x1B[", this.0.numtoa_str(10, &mut buf), "D"].concat()
    }
}

impl fmt::Display for Left {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&String::from(*self))
    }
}

/// Move cursor right.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Right(pub u16);

impl From<Right> for String {
    fn from(this: Right) -> String {
        let mut buf = [0u8; 20];
        ["\x1B[", this.0.numtoa_str(10, &mut buf), "C"].concat()
    }
}

impl fmt::Display for Right {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&String::from(*self))
    }
}

/// Move cursor up.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Up(pub u16);

impl From<Up> for String {
    fn from(this: Up) -> String {
        let mut buf = [0u8; 20];
        ["\x1B[", this.0.numtoa_str(10, &mut buf), "A"].concat()
    }
}

impl fmt::Display for Up {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&String::from(*self))
    }
}

/// Move cursor down.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Down(pub u16);

impl From<Down> for String {
    fn from(this: Down) -> String {
        let mut buf = [0u8; 20];
        ["\x1B[", this.0.numtoa_str(10, &mut buf), "B"].concat()
    }
}

impl fmt::Display for Down {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&String::from(*self))
    }
}

/// Types that allow detection of the cursor position.
pub trait DetectCursorPos {
    /// Get the (1,1)-based cursor position from the terminal.
    fn cursor_pos(&mut self) -> io::Result<(u16, u16)>;
}

impl<W: Write> DetectCursorPos for W {
    fn cursor_pos(&mut self) -> io::Result<(u16, u16)> {
        let delimiter = b'R';
        let mut stdin = async_stdin_until(delimiter);

        // Where is the cursor?
        // Use `ESC [ 6 n`.
        write!(self, "\x1B[6n")?;
        self.flush()?;

        let mut buf: [u8; 1] = [0];
        let mut read_chars = Vec::new();

        let timeout = Duration::from_millis(CONTROL_SEQUENCE_TIMEOUT);
        let now = SystemTime::now();

        // Either consume all data up to R or wait for a timeout.
        while buf[0] != delimiter && now.elapsed().unwrap() < timeout {
            if stdin.read(&mut buf)? > 0 {
                read_chars.push(buf[0]);
            }
        }

        if read_chars.is_empty() {
            return Err(Error::new(ErrorKind::Other, "Cursor position detection timed out."));
        }

        // The answer will look like `ESC [ Cy ; Cx R`.

        read_chars.pop(); // remove trailing R.
        let read_str = String::from_utf8(read_chars).unwrap();
        let beg = read_str.rfind('[').unwrap();
        let coords: String = read_str.chars().skip(beg + 1).collect();
        let mut nums = coords.split(';');

        let cy = nums.next()
            .unwrap()
            .parse::<u16>()
            .unwrap();
        let cx = nums.next()
            .unwrap()
            .parse::<u16>()
            .unwrap();

        Ok((cx, cy))
    }
}

/// Hide the cursor for the lifetime of this struct.
/// It will hide the cursor on creation with from() and show it back on drop().
pub struct HideCursor<W: Write> {
    /// The output target.
    output: W,
}

impl<W: Write> HideCursor<W> {
    /// Create a hide cursor wrapper struct for the provided output and hides the cursor.
    pub fn from(mut output: W) -> Self {
        write!(output, "{}", Hide).expect("hide the cursor");
        HideCursor { output: output }
    }
}

impl<W: Write> Drop for HideCursor<W> {
    fn drop(&mut self) {
        write!(self, "{}", Show).expect("show the cursor");
    }
}

impl<W: Write> ops::Deref for HideCursor<W> {
    type Target = W;

    fn deref(&self) -> &W {
        &self.output
    }
}

impl<W: Write> ops::DerefMut for HideCursor<W> {
    fn deref_mut(&mut self) -> &mut W {
        &mut self.output
    }
}

impl<W: Write> Write for HideCursor<W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.output.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.output.flush()
    }
}
<|endoftext|>


<commit_before>//! ICWS '94 draft
//!

use std::ops::{Index, IndexMut};

// #[derive(Clone, Copy, Debug, Default)]
// pub struct Address(u32);
pub type Address = u32;

#[derive(Clone, Copy, Debug)]
pub enum Opcode {
    DAT, // terminate process
    MOV, // move from A to B
    ADD, // add A to B, store result in B
    SUB, // subtract A from B, store result in B
    MUL, // multiply A by B, store result in B
    DIV, // divide B by A, store result in B if A <> 0, else terminate
    MOD, // divide B by A, store remainder in B if A <> 0, else terminate
    JMP, // transfer execution to A
    JMZ, // transfer execution to A if B is zero
    JMN, // transfer execution to A if B is non-zero
    DJN, // decrement B, if B is non-zero, transfer execution to A
    CMP, // same as SEQ
    SLT, // skip next instruction if A is less than B
    SPL, // split off process to A
    SEQ, // (*) Skip next instruction if A is equal to B
    SNE, // (*) Skip next instruction if A is not equal to B
    NOP, // (*) No operation
    LDP, // (+) Load P-space cell A into core address B
    STP, // (+) Store A-number into P-space cell B
}

impl Default for Opcode {
    fn default() -> Self {
        Opcode::DAT
    }
}

#[derive(Clone, Copy, Debug)]
pub enum Modifier {
    A,
    B,
    AB,
    BA,
    F,
    X,
    I,
}

impl Default for Modifier {
    fn default() -> Self {
        Modifier::A
    }
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Mode {
    IMMEDIATE, // #
    DIRECT, // $ (Default)
    INDIRECT, // @
    DECREMENT, // <
    INCREMENT, // >
}

impl Default for Mode {
    fn default() -> Self {
        Mode::IMMEDIATE
    }
}

#[derive(Clone, Copy, Debug, Default)]
pub struct Instruction {
    pub opcode: Opcode,
    pub modifier: Modifier,
    pub a_mode: Mode,
    pub a_number: Address,
    pub b_mode: Mode,
    pub b_number: Address,
}

impl Instruction {
    pub fn random() -> Self {
        Instruction::default()  // XXX Need real random implementation
    }
}

#[derive(Clone, Copy, Debug, Default)]
pub struct Warrior(u32);

#[derive(Debug)]
pub struct TaskQueue {
    task_limit: usize,
    task_pointer: Vec<Address>,
}

impl TaskQueue {
    fn new(limit: usize) -> Self {
        TaskQueue {
            task_limit: limit,
            task_pointer: Vec::<Address>::with_capacity(limit),
        }
    }

    pub fn queue(&mut self, addr: Address) {
        if self.task_pointer.len() < self.task_limit {
            self.task_pointer.push(addr);
        }
    }

    pub fn next(&mut self) -> Option<Address> {
        if self.task_pointer.len() > 0 {
            Some(self.task_pointer.remove(0))
        } else {
            None
        }
    }
}

#[derive(Debug)]
struct CoreMemory(Vec<Instruction>);

impl Index<Address> for CoreMemory {
    type Output = Instruction;

    fn index<'a>(&'a self, _index: Address) -> &'a Instruction {
        &self.0[_index as usize]
    }
}

impl IndexMut<Address> for CoreMemory {
    fn index_mut<'a>(&'a mut self, _index: Address) -> &'a mut Instruction {
        &mut self.0[_index as usize]
    }
}

#[derive(Debug)]
pub struct Core {
    core_size: Address,
    core: CoreMemory,
    warrior: [TaskQueue; 2],
    pc: Address,
    read_limit: Address,
    write_limit: Address,
}

impl Core {
    pub fn queue(&mut self, warrior: usize, task_pointer: Address) {
        self.warrior[warrior].queue(task_pointer)
    }

    fn fold(&self, pointer: Address, limit: Address) -> Address {
        let mut result = pointer % limit;
        if result > limit / 2 {
            result += self.core_size - limit;
        }
        result
    }

    pub fn emi94(&mut self) {
        let ir: Instruction;
        let ira: Instruction;
        let irb: Instruction;
        let mut rpa: Address;
        let mut wpa: Address;
        let rpb: Address;
        let wpb: Address;
        let pip: Address;

        ir = self.core[self.pc];

        // Evaluate A-operand
        //
        if ir.a_mode == Mode::IMMEDIATE {
            // For instructions with an Immediate A-mode, the Pointer A
            // points to the source of the current instruction.
            rpa = 0;
            wpa = 0;
        } else {
            // For instructions with a Direct A-mode, the Pointer A
            // points to the instruction IR.ANumber away, relative to
            // the Program Counter.
            rpa = self.fold(ir.a_number, self.read_limit);
            wpa = self.fold(ir.a_number, self.write_limit);

            if ir.a_mode != Mode::DIRECT {
                if ir.a_mode == Mode::DECREMENT {
                    self.core[((self.pc + wpa) % self.core_size)].b_number =
                        (self.core[((self.pc + wpa) % self.core_size)].b_number +
                         self.core_size - 1) % self.core_size;
                }

                if ir.a_mode == Mode::INCREMENT {
                    pip = (self.pc + wpa) % self.core_size;
                }

                rpa = self.fold((rpa + self.core[((self.pc + rpa) % self.core_size)].b_number),
                                self.read_limit);
                wpa = self.fold((wpa + self.core[((self.pc + wpa) % self.core_size)].b_number),
                                self.write_limit);
            }
        }

    }
}

#[derive(Debug)]
pub enum InitialInstruction {
    Default,
    Random,
    Instruction(Instruction),
}

#[derive(Debug)]
pub struct CoreBuilder {
    core_size: u32,
    initial_instruction: InitialInstruction,
    task_limit: usize,
}

impl CoreBuilder {
    pub fn new() -> Self {
        CoreBuilder {
            core_size: 8192,
            initial_instruction: InitialInstruction::Default,
            task_limit: 64,
        }
    }

    pub fn coresize(&mut self, size: u32) -> &Self {
        self.core_size = size;
        self
    }

    pub fn initial_instruction(&mut self, insn: InitialInstruction) -> &Self {
        self.initial_instruction = insn;
        self
    }

    pub fn task_limit(&mut self, limit: usize) -> &Self {
        self.task_limit = limit;
        self
    }

    pub fn build(&self) -> Core {
        let mut instructions = Vec::<Instruction>::new();
        for _ in 0..self.core_size {
            instructions.push(match self.initial_instruction {
                InitialInstruction::Default => Instruction::default(),
                InitialInstruction::Random => Instruction::random(),
                InitialInstruction::Instruction(insn) => insn,
            })
        }

        Core {
            core_size: self.core_size,
            core: CoreMemory(instructions),
            warrior: [TaskQueue::new(self.task_limit), TaskQueue::new(self.task_limit)],
            pc: 0,
            read_limit: 300,
            write_limit: 300,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn task_queue_simple() {
        let mut tq = TaskQueue::new(2);
        tq.queue(1);
        tq.queue(3);
        assert_eq!(tq.next(), Some(1));
        assert_eq!(tq.next(), Some(3));
        assert_eq!(tq.next(), None);
    }

    #[test]
    fn task_queue_limit() {
        let mut tq = TaskQueue::new(3);
        tq.queue(100);
        tq.queue(200);
        tq.queue(300);
        tq.queue(400);

        assert_eq!(tq.next(), Some(100));
        assert_eq!(tq.next(), Some(200));
        assert_eq!(tq.next(), Some(300));
        assert_eq!(tq.next(), None);
    }

    #[test]
    fn task_queue_empty() {
        let mut tq = TaskQueue::new(100);

        assert_eq!(tq.next(), None);
    }
}
<commit_msg>Drop PC from Core struct<commit_after>//! ICWS '94 draft
//!

use std::ops::{Index, IndexMut};

// #[derive(Clone, Copy, Debug, Default)]
// pub struct Address(u32);
pub type Address = u32;

#[derive(Clone, Copy, Debug)]
pub enum Opcode {
    DAT, // terminate process
    MOV, // move from A to B
    ADD, // add A to B, store result in B
    SUB, // subtract A from B, store result in B
    MUL, // multiply A by B, store result in B
    DIV, // divide B by A, store result in B if A <> 0, else terminate
    MOD, // divide B by A, store remainder in B if A <> 0, else terminate
    JMP, // transfer execution to A
    JMZ, // transfer execution to A if B is zero
    JMN, // transfer execution to A if B is non-zero
    DJN, // decrement B, if B is non-zero, transfer execution to A
    CMP, // same as SEQ
    SLT, // skip next instruction if A is less than B
    SPL, // split off process to A
    SEQ, // (*) Skip next instruction if A is equal to B
    SNE, // (*) Skip next instruction if A is not equal to B
    NOP, // (*) No operation
    LDP, // (+) Load P-space cell A into core address B
    STP, // (+) Store A-number into P-space cell B
}

impl Default for Opcode {
    fn default() -> Self {
        Opcode::DAT
    }
}

#[derive(Clone, Copy, Debug)]
pub enum Modifier {
    A,
    B,
    AB,
    BA,
    F,
    X,
    I,
}

impl Default for Modifier {
    fn default() -> Self {
        Modifier::A
    }
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Mode {
    IMMEDIATE, // #
    DIRECT, // $ (Default)
    INDIRECT, // @
    DECREMENT, // <
    INCREMENT, // >
}

impl Default for Mode {
    fn default() -> Self {
        Mode::IMMEDIATE
    }
}

#[derive(Clone, Copy, Debug, Default)]
pub struct Instruction {
    pub opcode: Opcode,
    pub modifier: Modifier,
    pub a_mode: Mode,
    pub a_number: Address,
    pub b_mode: Mode,
    pub b_number: Address,
}

impl Instruction {
    pub fn random() -> Self {
        Instruction::default()  // XXX Need real random implementation
    }
}

#[derive(Clone, Copy, Debug, Default)]
pub struct Warrior(u32);

#[derive(Debug)]
pub struct TaskQueue {
    task_limit: usize,
    task_pointer: Vec<Address>,
}

impl TaskQueue {
    fn new(limit: usize) -> Self {
        TaskQueue {
            task_limit: limit,
            task_pointer: Vec::<Address>::with_capacity(limit),
        }
    }

    pub fn queue(&mut self, addr: Address) {
        if self.task_pointer.len() < self.task_limit {
            self.task_pointer.push(addr);
        }
    }

    pub fn next(&mut self) -> Option<Address> {
        if self.task_pointer.len() > 0 {
            Some(self.task_pointer.remove(0))
        } else {
            None
        }
    }
}

#[derive(Debug)]
struct CoreMemory(Vec<Instruction>);

impl Index<Address> for CoreMemory {
    type Output = Instruction;

    fn index<'a>(&'a self, _index: Address) -> &'a Instruction {
        &self.0[_index as usize]
    }
}

impl IndexMut<Address> for CoreMemory {
    fn index_mut<'a>(&'a mut self, _index: Address) -> &'a mut Instruction {
        &mut self.0[_index as usize]
    }
}

#[derive(Debug)]
pub struct Core {
    core_size: Address,
    core: CoreMemory,
    warrior: [TaskQueue; 2],
    // pc: Address,
    read_limit: Address,
    write_limit: Address,
}

impl Core {
    pub fn queue(&mut self, warrior: usize, task_pointer: Address) {
        self.warrior[warrior].queue(task_pointer)
    }

    fn fold(&self, pointer: Address, limit: Address) -> Address {
        let mut result = pointer % limit;
        if result > limit / 2 {
            result += self.core_size - limit;
        }
        result
    }

    pub fn emi94(&mut self) {
        let ir: Instruction;
        let ira: Instruction;
        let irb: Instruction;
        let mut rpa: Address;
        let mut wpa: Address;
        let rpb: Address;
        let wpb: Address;
        let pip: Address;

        ir = self.core[pc];

        // Evaluate A-operand
        //
        if ir.a_mode == Mode::IMMEDIATE {
            // For instructions with an Immediate A-mode, the Pointer A
            // points to the source of the current instruction.
            rpa = 0;
            wpa = 0;
        } else {
            // For instructions with a Direct A-mode, the Pointer A
            // points to the instruction IR.ANumber away, relative to
            // the Program Counter.
            rpa = self.fold(ir.a_number, self.read_limit);
            wpa = self.fold(ir.a_number, self.write_limit);

            if ir.a_mode != Mode::DIRECT {
                if ir.a_mode == Mode::DECREMENT {
                    self.core[((pc + wpa) % self.core_size)].b_number =
                        (self.core[((pc + wpa) % self.core_size)].b_number + self.core_size - 1) %
                        self.core_size;
                }

                if ir.a_mode == Mode::INCREMENT {
                    pip = (pc + wpa) % self.core_size;
                }

                rpa = self.fold((rpa + self.core[((pc + rpa) % self.core_size)].b_number),
                                self.read_limit);
                wpa = self.fold((wpa + self.core[((pc + wpa) % self.core_size)].b_number),
                                self.write_limit);
            }
        }

    }
}

#[derive(Debug)]
pub enum InitialInstruction {
    Default,
    Random,
    Instruction(Instruction),
}

#[derive(Debug)]
pub struct CoreBuilder {
    core_size: u32,
    initial_instruction: InitialInstruction,
    task_limit: usize,
}

impl CoreBuilder {
    pub fn new() -> Self {
        CoreBuilder {
            core_size: 8192,
            initial_instruction: InitialInstruction::Default,
            task_limit: 64,
        }
    }

    pub fn coresize(&mut self, size: u32) -> &Self {
        self.core_size = size;
        self
    }

    pub fn initial_instruction(&mut self, insn: InitialInstruction) -> &Self {
        self.initial_instruction = insn;
        self
    }

    pub fn task_limit(&mut self, limit: usize) -> &Self {
        self.task_limit = limit;
        self
    }

    pub fn build(&self) -> Core {
        let mut instructions = Vec::<Instruction>::new();
        for _ in 0..self.core_size {
            instructions.push(match self.initial_instruction {
                InitialInstruction::Default => Instruction::default(),
                InitialInstruction::Random => Instruction::random(),
                InitialInstruction::Instruction(insn) => insn,
            })
        }

        Core {
            core_size: self.core_size,
            core: CoreMemory(instructions),
            warrior: [TaskQueue::new(self.task_limit), TaskQueue::new(self.task_limit)],
            read_limit: 300,
            write_limit: 300,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn task_queue_simple() {
        let mut tq = TaskQueue::new(2);
        tq.queue(1);
        tq.queue(3);
        assert_eq!(tq.next(), Some(1));
        assert_eq!(tq.next(), Some(3));
        assert_eq!(tq.next(), None);
    }

    #[test]
    fn task_queue_limit() {
        let mut tq = TaskQueue::new(3);
        tq.queue(100);
        tq.queue(200);
        tq.queue(300);
        tq.queue(400);

        assert_eq!(tq.next(), Some(100));
        assert_eq!(tq.next(), Some(200));
        assert_eq!(tq.next(), Some(300));
        assert_eq!(tq.next(), None);
    }

    #[test]
    fn task_queue_empty() {
        let mut tq = TaskQueue::new(100);

        assert_eq!(tq.next(), None);
    }
}
<|endoftext|>


<commit_before>use std::ptr;
use std::sync::Mutex;

use super::*;

pub struct Lru {
    shards: Vec<Mutex<Shard>>,
}

impl Lru {
    /// Instantiates a new `Lru` cache.
    pub fn new(cache_capacity: usize, cache_bits: usize) -> Lru {
        assert!(
            cache_bits <= 20,
            "way too many shards. use a smaller number of cache_bits"
        );
        let size = 1 << cache_bits;
        let shard_capacity = cache_capacity / size;

        Lru {
            shards: rep_no_copy![Mutex::new(Shard::new(shard_capacity)); size],
        }
    }

    /// Called when a page is accessed. Returns a Vec of pages to
    /// try to page-out. For each one of these, the caller is expected
    /// to call `page_out_succeeded` if the page-out succeeded.
    pub fn accessed(&self, pid: PageID, sz: usize) -> Vec<PageID> {
        let shard_idx = pid % self.shards.len();
        let rel_idx = pid / self.shards.len();
        let shard_mu = &self.shards[shard_idx];
        let mut shard = shard_mu.lock().unwrap();
        let mut rel_ids = shard.accessed(rel_idx, sz);

        for rel_id in &mut rel_ids {
            let real_id = (*rel_id * self.shards.len()) + shard_idx;
            *rel_id = real_id;
        }

        rel_ids
    }
}

#[derive(Clone)]
struct Entry {
    ptr: *mut dll::Node,
    sz: usize,
}

impl Default for Entry {
    fn default() -> Entry {
        Entry {
            ptr: ptr::null_mut(),
            sz: 0,
        }
    }
}

struct Shard {
    list: Dll,
    entries: Vec<Entry>,
    capacity: usize,
    sz: usize,
}

impl Shard {
    fn new(capacity: usize) -> Shard {
        Shard {
            list: Dll::default(),
            entries: vec![],
            capacity: capacity,
            sz: 0,
        }
    }

    fn accessed(&mut self, rel_idx: PageID, sz: usize) -> Vec<PageID> {
        if self.entries.len() <= rel_idx {
            self.entries.resize(rel_idx + 1, Entry::default());
        }

        {
            let entry = &mut self.entries[rel_idx];

            self.sz -= entry.sz;
            entry.sz = sz;
            self.sz += sz;

            if entry.ptr.is_null() {
                entry.ptr = self.list.push_head(rel_idx);
            } else {
                entry.ptr = self.list.promote(entry.ptr);
            }
        }

        let mut to_evict = vec![];
        while self.sz > self.capacity {
            if self.list.len() == 1 {
                // don't evict what we just added
                break;
            }

            let min_pid = self.list.pop_tail().unwrap();
            self.entries[min_pid].ptr = ptr::null_mut();

            to_evict.push(min_pid);

            self.sz -= self.entries[min_pid].sz;
            self.entries[min_pid].sz = 0;
        }

        to_evict
    }
}
<commit_msg>mark Lru sync for rayon compatibility<commit_after>use std::ptr;
use std::sync::Mutex;

use super::*;

pub struct Lru {
    shards: Vec<Mutex<Shard>>,
}

unsafe impl Sync for Lru {}

impl Lru {
    /// Instantiates a new `Lru` cache.
    pub fn new(cache_capacity: usize, cache_bits: usize) -> Lru {
        assert!(
            cache_bits <= 20,
            "way too many shards. use a smaller number of cache_bits"
        );
        let size = 1 << cache_bits;
        let shard_capacity = cache_capacity / size;

        Lru {
            shards: rep_no_copy![Mutex::new(Shard::new(shard_capacity)); size],
        }
    }

    /// Called when a page is accessed. Returns a Vec of pages to
    /// try to page-out. For each one of these, the caller is expected
    /// to call `page_out_succeeded` if the page-out succeeded.
    pub fn accessed(&self, pid: PageID, sz: usize) -> Vec<PageID> {
        let shard_idx = pid % self.shards.len();
        let rel_idx = pid / self.shards.len();
        let shard_mu = &self.shards[shard_idx];
        let mut shard = shard_mu.lock().unwrap();
        let mut rel_ids = shard.accessed(rel_idx, sz);

        for rel_id in &mut rel_ids {
            let real_id = (*rel_id * self.shards.len()) + shard_idx;
            *rel_id = real_id;
        }

        rel_ids
    }
}

#[derive(Clone)]
struct Entry {
    ptr: *mut dll::Node,
    sz: usize,
}

impl Default for Entry {
    fn default() -> Entry {
        Entry {
            ptr: ptr::null_mut(),
            sz: 0,
        }
    }
}

struct Shard {
    list: Dll,
    entries: Vec<Entry>,
    capacity: usize,
    sz: usize,
}

impl Shard {
    fn new(capacity: usize) -> Shard {
        Shard {
            list: Dll::default(),
            entries: vec![],
            capacity: capacity,
            sz: 0,
        }
    }

    fn accessed(&mut self, rel_idx: PageID, sz: usize) -> Vec<PageID> {
        if self.entries.len() <= rel_idx {
            self.entries.resize(rel_idx + 1, Entry::default());
        }

        {
            let entry = &mut self.entries[rel_idx];

            self.sz -= entry.sz;
            entry.sz = sz;
            self.sz += sz;

            if entry.ptr.is_null() {
                entry.ptr = self.list.push_head(rel_idx);
            } else {
                entry.ptr = self.list.promote(entry.ptr);
            }
        }

        let mut to_evict = vec![];
        while self.sz > self.capacity {
            if self.list.len() == 1 {
                // don't evict what we just added
                break;
            }

            let min_pid = self.list.pop_tail().unwrap();
            self.entries[min_pid].ptr = ptr::null_mut();

            to_evict.push(min_pid);

            self.sz -= self.entries[min_pid].sz;
            self.entries[min_pid].sz = 0;
        }

        to_evict
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::codegen::InheritTypes::EventCast;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::error::Error::{InvalidAccess, Syntax};
use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
use dom::bindings::str::USVString;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::reflect_dom_object;
use dom::closeevent::CloseEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use script_task::Runnable;
use script_task::ScriptMsg;
use std::cell::{Cell, RefCell};
use std::borrow::ToOwned;
use util::str::DOMString;

use websocket::Message;
use websocket::ws::sender::Sender as Sender_Object;
use websocket::client::sender::Sender;
use websocket::client::receiver::Receiver;
use websocket::stream::WebSocketStream;
use websocket::client::request::Url;
use websocket::Client;
use websocket::header::Origin;
use websocket::result::WebSocketResult;

#[derive(JSTraceable, PartialEq, Copy, Clone)]
enum WebSocketRequestState {
    Connecting = 0,
    Open = 1,
    Closing = 2,
    Closed = 3,
}

no_jsmanaged_fields!(Sender<WebSocketStream>);
no_jsmanaged_fields!(Receiver<WebSocketStream>);

#[dom_struct]
pub struct WebSocket {
    eventtarget: EventTarget,
    url: Url,
    global: GlobalField,
    ready_state: Cell<WebSocketRequestState>,
    sender: RefCell<Option<Sender<WebSocketStream>>>,
    receiver: RefCell<Option<Receiver<WebSocketStream>>>,
    failed: Cell<bool>, //Flag to tell if websocket was closed due to failure
    full: Cell<bool>, //Flag to tell if websocket queue is full
    clean_close: Cell<bool>, //Flag to tell if the websocket closed cleanly (not due to full or fail)
    code: Cell<u16>, //Closing code
    reason: DOMRefCell<DOMString>, //Closing reason
    data: DOMRefCell<DOMString>, //Data from send - TODO: Remove after buffer is added.
    sendCloseFrame: Cell<bool>
}

fn parse_web_socket_url(url_str: &str) -> Fallible<(Url, String, u16, String, bool)> {
    // https://html.spec.whatwg.org/multipage/#parse-a-websocket-url's-components
    // Steps 1 and 2
    let parsed_url = Url::parse(url_str);
    let parsed_url = match parsed_url {
        Ok(parsed_url) => parsed_url,
        Err(_) => return Err(Error::Syntax),
    };

    // Step 4
    if parsed_url.fragment != None {
        return Err(Error::Syntax);
    }

    // Steps 3 and 5
    let secure = match parsed_url.scheme.as_ref() {
        "ws" => false,
        "wss" => true,
        _ => return Err(Error::Syntax), // step 3
    };

    let host = parsed_url.host().unwrap().serialize(); // Step 6
    let port = parsed_url.port_or_default().unwrap(); // Steps 7 and 8
    let mut resource = parsed_url.path().unwrap().connect("/"); // Step 9
    if resource.is_empty() {
        resource = "/".to_owned(); // Step 10
    }

    // Step 11
    if let Some(ref query) = parsed_url.query {
        resource.push('?');
        resource.push_str(query);
    }

    // Step 12
    // FIXME remove parsed_url once it's no longer used in WebSocket::new
    Ok((parsed_url, host, port, resource, secure))
}

/// *Establish a WebSocket Connection* as defined in RFC 6455.
fn establish_a_websocket_connection(url: Url, origin: String)
    -> WebSocketResult<(Sender<WebSocketStream>, Receiver<WebSocketStream>)> {
    let mut request = try!(Client::connect(url));
    request.headers.set(Origin(origin));

    let response = try!(request.send());
    try!(response.validate());

    Ok(response.begin().split())
}

impl WebSocket {
    pub fn new_inherited(global: GlobalRef, url: Url) -> WebSocket {
        WebSocket {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::WebSocket),
            url: url,
            global: GlobalField::from_rooted(&global),
            ready_state: Cell::new(WebSocketRequestState::Connecting),
            failed: Cell::new(false),
            sender: RefCell::new(None),
            receiver: RefCell::new(None),
            full: Cell::new(false),
            clean_close: Cell::new(true),
            code: Cell::new(0),
            reason: DOMRefCell::new("".to_owned()),
            data: DOMRefCell::new("".to_owned()),
            sendCloseFrame: Cell::new(false)
        }

    }

    pub fn new(global: GlobalRef, url: DOMString) -> Fallible<Root<WebSocket>> {
        // Step 1.
        // FIXME extract the right variables once Client::connect
        // implementation is fixed to follow the RFC 6455 properly.
        let (url, _, _, _, _) = try!(parse_web_socket_url(&url));

        /*TODO: This constructor is only a prototype, it does not accomplish the specs
          defined here:
          http://html.spec.whatwg.org
          The remaining 8 items must be satisfied.
          TODO: This constructor should be responsible for spawning a thread for the
          receive loop after ws.r().Open() - See comment
        */
        let ws = reflect_dom_object(box WebSocket::new_inherited(global, url.clone()),
                                    global,
                                    WebSocketBinding::Wrap);

        let channel = establish_a_websocket_connection(url, global.get_url().serialize());
        let (temp_sender, temp_receiver) = match channel {
            Ok(channel) => channel,
            Err(e) => {
                debug!("Failed to establish a WebSocket connection: {:?}", e);
                let global_root = ws.r().global.root();
                let address = Trusted::new(global_root.r().get_cx(), ws.r(), global_root.r().script_chan().clone());
                let task = box WebSocketTaskHandler::new(address, WebSocketTask::Close);
                global_root.r().script_chan().send(ScriptMsg::RunnableMsg(task)).unwrap();
                return Ok(ws);
            }
        };

        *ws.r().sender.borrow_mut() = Some(temp_sender);
        *ws.r().receiver.borrow_mut() = Some(temp_receiver);

        //Create everything necessary for starting the open asynchronous task, then begin the task.
        let global_root = ws.r().global.root();
        let addr: Trusted<WebSocket> =
            Trusted::new(global_root.r().get_cx(), ws.r(), global_root.r().script_chan().clone());
        let open_task = box WebSocketTaskHandler::new(addr, WebSocketTask::ConnectionEstablished);
        global_root.r().script_chan().send(ScriptMsg::RunnableMsg(open_task)).unwrap();
        //TODO: Spawn thread here for receive loop
        /*TODO: Add receive loop here and make new thread run this
          Receive is an infinite loop "similiar" the one shown here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop however does need to follow the spec. These are outlined here
          under "WebSocket message has been received" items 1-5:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop also needs to dispatch an asynchronous event as stated here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: When the receive loop receives a close message from the server,
          it confirms the websocket is now closed. This requires the close event
          to be fired (dispatch_close fires the close event - see implementation below)
        */
        Ok(ws)
    }

    pub fn Constructor(global: GlobalRef, url: DOMString) -> Fallible<Root<WebSocket>> {
        WebSocket::new(global, url)
    }
}

impl<'a> WebSocketMethods for &'a WebSocket {
    event_handler!(open, GetOnopen, SetOnopen);
    event_handler!(close, GetOnclose, SetOnclose);
    event_handler!(error, GetOnerror, SetOnerror);

    fn Url(self) -> DOMString {
        self.url.serialize()
    }

    fn ReadyState(self) -> u16 {
        self.ready_state.get() as u16
    }

    fn Send(self, data: Option<USVString>) -> Fallible<()> {
        if self.ready_state.get() == WebSocketRequestState::Connecting {
            return Err(Error::InvalidState);
        }

        /*TODO: This is not up to spec see http://html.spec.whatwg.org/multipage/comms.html search for
                "If argument is a string"
          TODO: Need to buffer data
          TODO: bufferedAmount attribute returns the size of the buffer in bytes -
                this is a required attribute defined in the websocket.webidl file
          TODO: The send function needs to flag when full by using the following
          self.full.set(true). This needs to be done when the buffer is full
        */
        let mut other_sender = self.sender.borrow_mut();
        let my_sender = other_sender.as_mut().unwrap();
        if self.sendCloseFrame.get() { //TODO: Also check if the buffer is full
            self.sendCloseFrame.set(false);
            let _ = my_sender.send_message(Message::Close(None));
            return Ok(());
        }
        let _ = my_sender.send_message(Message::Text(data.unwrap().0));
        return Ok(())
    }

    fn Close(self, code: Option<u16>, reason: Option<USVString>) -> Fallible<()>{
        if let Some(code) = code {
            //Check code is NOT 1000 NOR in the range of 3000-4999 (inclusive)
            if  code != 1000 && (code < 3000 || code > 4999) {
                return Err(Error::InvalidAccess);
            }
        }
        if let Some(ref reason) = reason {
            if reason.0.as_bytes().len() > 123 { //reason cannot be larger than 123 bytes
                return Err(Error::Syntax);
            }
        }

        match self.ready_state.get() {
            WebSocketRequestState::Closing | WebSocketRequestState::Closed  => {} //Do nothing
            WebSocketRequestState::Connecting => { //Connection is not yet established
                /*By setting the state to closing, the open function
                  will abort connecting the websocket*/
                self.ready_state.set(WebSocketRequestState::Closing);
                self.failed.set(true);
                self.sendCloseFrame.set(true);
                //Dispatch send task to send close frame
                //TODO: Sending here is just empty string, though no string is really needed. Another send, empty
                //      send, could be used.
                let _ = self.Send(None);
                //Note: After sending the close message, the receive loop confirms a close message from the server and
                //      must fire a close event
            }
            WebSocketRequestState::Open => {
                //Closing handshake not started - still in open
                //Start the closing by setting the code and reason if they exist
                if let Some(code) = code {
                    self.code.set(code);
                }
                if let Some(reason) = reason {
                    *self.reason.borrow_mut() = reason.0;
                }
                self.ready_state.set(WebSocketRequestState::Closing);
                self.sendCloseFrame.set(true);
                //Dispatch send task to send close frame
                let _ = self.Send(None);
                //Note: After sending the close message, the receive loop confirms a close message from the server and
                //      must fire a close event
            }
        }
        Ok(()) //Return Ok
    }
}

pub enum WebSocketTask {
    /// Task queued when *the WebSocket connection is established*.
    ConnectionEstablished,
    Close,
}

pub struct WebSocketTaskHandler {
    addr: Trusted<WebSocket>,
    task: WebSocketTask,
}

impl WebSocketTaskHandler {
    pub fn new(addr: Trusted<WebSocket>, task: WebSocketTask) -> WebSocketTaskHandler {
        WebSocketTaskHandler {
            addr: addr,
            task: task,
        }
    }

    fn connection_established(&self) {
        /*TODO: Items 1, 3, 4, & 5 under "WebSocket connection is established" as specified here:
          https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol
        */
        let ws = self.addr.root();

        // Step 1: Protocols.

        // Step 2.
        ws.ready_state.set(WebSocketRequestState::Open);

        // Step 3: Extensions.
        // Step 4: Protocols.
        // Step 5: Cookies.

        // Step 6.
        let global = ws.global.root();
        let event = Event::new(global.r(), "open".to_owned(),
                               EventBubbles::DoesNotBubble,
                               EventCancelable::NotCancelable);
        event.fire(EventTargetCast::from_ref(ws.r()));
    }

    fn dispatch_close(&self) {
        let ws = self.addr.root();
        let ws = ws.r();
        let global = ws.global.root();
        ws.ready_state.set(WebSocketRequestState::Closed);
        //If failed or full, fire error event
        if ws.failed.get() || ws.full.get() {
            ws.failed.set(false);
            ws.full.set(false);
            //A Bad close
            ws.clean_close.set(false);
            let event = Event::new(global.r(),
                                   "error".to_owned(),
                                   EventBubbles::DoesNotBubble,
                                   EventCancelable::Cancelable);
            let target = EventTargetCast::from_ref(ws);
            event.r().fire(target);
        }
        let rsn = ws.reason.borrow();
        let rsn_clone = rsn.clone();
        /*In addition, we also have to fire a close even if error event fired
         https://html.spec.whatwg.org/multipage/#closeWebSocket
        */
        let close_event = CloseEvent::new(global.r(),
                                          "close".to_owned(),
                                          EventBubbles::DoesNotBubble,
                                          EventCancelable::NotCancelable,
                                          ws.clean_close.get(),
                                          ws.code.get(),
                                          rsn_clone);
        let target = EventTargetCast::from_ref(ws);
        let event = EventCast::from_ref(close_event.r());
        event.fire(target);
    }
}

impl Runnable for WebSocketTaskHandler {
    fn handler(self: Box<WebSocketTaskHandler>) {
        match self.task {
            WebSocketTask::ConnectionEstablished => {
                self.connection_established();
            }
            WebSocketTask::Close => {
                self.dispatch_close();
            }
        }
    }
}

<commit_msg>Auto merge of #6634 - Ms2ger:ws-parse, r=metajack<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::codegen::InheritTypes::EventCast;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::error::Error::{InvalidAccess, Syntax};
use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
use dom::bindings::str::USVString;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::reflect_dom_object;
use dom::closeevent::CloseEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use script_task::Runnable;
use script_task::ScriptMsg;
use std::cell::{Cell, RefCell};
use std::borrow::ToOwned;
use util::str::DOMString;

use hyper::header::Host;
use websocket::Message;
use websocket::ws::sender::Sender as Sender_Object;
use websocket::client::sender::Sender;
use websocket::client::receiver::Receiver;
use websocket::stream::WebSocketStream;
use websocket::client::request::Url;
use websocket::Client;
use websocket::header::Origin;
use websocket::result::WebSocketResult;
use websocket::ws::util::url::parse_url;

#[derive(JSTraceable, PartialEq, Copy, Clone)]
enum WebSocketRequestState {
    Connecting = 0,
    Open = 1,
    Closing = 2,
    Closed = 3,
}

no_jsmanaged_fields!(Sender<WebSocketStream>);
no_jsmanaged_fields!(Receiver<WebSocketStream>);

#[dom_struct]
pub struct WebSocket {
    eventtarget: EventTarget,
    url: Url,
    global: GlobalField,
    ready_state: Cell<WebSocketRequestState>,
    sender: RefCell<Option<Sender<WebSocketStream>>>,
    receiver: RefCell<Option<Receiver<WebSocketStream>>>,
    failed: Cell<bool>, //Flag to tell if websocket was closed due to failure
    full: Cell<bool>, //Flag to tell if websocket queue is full
    clean_close: Cell<bool>, //Flag to tell if the websocket closed cleanly (not due to full or fail)
    code: Cell<u16>, //Closing code
    reason: DOMRefCell<DOMString>, //Closing reason
    data: DOMRefCell<DOMString>, //Data from send - TODO: Remove after buffer is added.
    sendCloseFrame: Cell<bool>
}

/// *Establish a WebSocket Connection* as defined in RFC 6455.
fn establish_a_websocket_connection(url: (Host, String, bool), origin: String)
    -> WebSocketResult<(Sender<WebSocketStream>, Receiver<WebSocketStream>)> {
    let mut request = try!(Client::connect(url));
    request.headers.set(Origin(origin));

    let response = try!(request.send());
    try!(response.validate());

    Ok(response.begin().split())
}

impl WebSocket {
    pub fn new_inherited(global: GlobalRef, url: Url) -> WebSocket {
        WebSocket {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::WebSocket),
            url: url,
            global: GlobalField::from_rooted(&global),
            ready_state: Cell::new(WebSocketRequestState::Connecting),
            failed: Cell::new(false),
            sender: RefCell::new(None),
            receiver: RefCell::new(None),
            full: Cell::new(false),
            clean_close: Cell::new(true),
            code: Cell::new(0),
            reason: DOMRefCell::new("".to_owned()),
            data: DOMRefCell::new("".to_owned()),
            sendCloseFrame: Cell::new(false)
        }

    }

    pub fn new(global: GlobalRef, url: DOMString) -> Fallible<Root<WebSocket>> {
        // Step 1.
        let parsed_url = try!(Url::parse(&url).map_err(|_| Error::Syntax));
        let url = try!(parse_url(&parsed_url).map_err(|_| Error::Syntax));

        /*TODO: This constructor is only a prototype, it does not accomplish the specs
          defined here:
          http://html.spec.whatwg.org
          The remaining 8 items must be satisfied.
          TODO: This constructor should be responsible for spawning a thread for the
          receive loop after ws.r().Open() - See comment
        */
        let ws = reflect_dom_object(box WebSocket::new_inherited(global, parsed_url),
                                    global,
                                    WebSocketBinding::Wrap);

        let channel = establish_a_websocket_connection(url, global.get_url().serialize());
        let (temp_sender, temp_receiver) = match channel {
            Ok(channel) => channel,
            Err(e) => {
                debug!("Failed to establish a WebSocket connection: {:?}", e);
                let global_root = ws.r().global.root();
                let address = Trusted::new(global_root.r().get_cx(), ws.r(), global_root.r().script_chan().clone());
                let task = box WebSocketTaskHandler::new(address, WebSocketTask::Close);
                global_root.r().script_chan().send(ScriptMsg::RunnableMsg(task)).unwrap();
                return Ok(ws);
            }
        };

        *ws.r().sender.borrow_mut() = Some(temp_sender);
        *ws.r().receiver.borrow_mut() = Some(temp_receiver);

        //Create everything necessary for starting the open asynchronous task, then begin the task.
        let global_root = ws.r().global.root();
        let addr: Trusted<WebSocket> =
            Trusted::new(global_root.r().get_cx(), ws.r(), global_root.r().script_chan().clone());
        let open_task = box WebSocketTaskHandler::new(addr, WebSocketTask::ConnectionEstablished);
        global_root.r().script_chan().send(ScriptMsg::RunnableMsg(open_task)).unwrap();
        //TODO: Spawn thread here for receive loop
        /*TODO: Add receive loop here and make new thread run this
          Receive is an infinite loop "similiar" the one shown here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop however does need to follow the spec. These are outlined here
          under "WebSocket message has been received" items 1-5:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop also needs to dispatch an asynchronous event as stated here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: When the receive loop receives a close message from the server,
          it confirms the websocket is now closed. This requires the close event
          to be fired (dispatch_close fires the close event - see implementation below)
        */
        Ok(ws)
    }

    pub fn Constructor(global: GlobalRef, url: DOMString) -> Fallible<Root<WebSocket>> {
        WebSocket::new(global, url)
    }
}

impl<'a> WebSocketMethods for &'a WebSocket {
    event_handler!(open, GetOnopen, SetOnopen);
    event_handler!(close, GetOnclose, SetOnclose);
    event_handler!(error, GetOnerror, SetOnerror);

    fn Url(self) -> DOMString {
        self.url.serialize()
    }

    fn ReadyState(self) -> u16 {
        self.ready_state.get() as u16
    }

    fn Send(self, data: Option<USVString>) -> Fallible<()> {
        if self.ready_state.get() == WebSocketRequestState::Connecting {
            return Err(Error::InvalidState);
        }

        /*TODO: This is not up to spec see http://html.spec.whatwg.org/multipage/comms.html search for
                "If argument is a string"
          TODO: Need to buffer data
          TODO: bufferedAmount attribute returns the size of the buffer in bytes -
                this is a required attribute defined in the websocket.webidl file
          TODO: The send function needs to flag when full by using the following
          self.full.set(true). This needs to be done when the buffer is full
        */
        let mut other_sender = self.sender.borrow_mut();
        let my_sender = other_sender.as_mut().unwrap();
        if self.sendCloseFrame.get() { //TODO: Also check if the buffer is full
            self.sendCloseFrame.set(false);
            let _ = my_sender.send_message(Message::Close(None));
            return Ok(());
        }
        let _ = my_sender.send_message(Message::Text(data.unwrap().0));
        return Ok(())
    }

    fn Close(self, code: Option<u16>, reason: Option<USVString>) -> Fallible<()>{
        if let Some(code) = code {
            //Check code is NOT 1000 NOR in the range of 3000-4999 (inclusive)
            if  code != 1000 && (code < 3000 || code > 4999) {
                return Err(Error::InvalidAccess);
            }
        }
        if let Some(ref reason) = reason {
            if reason.0.as_bytes().len() > 123 { //reason cannot be larger than 123 bytes
                return Err(Error::Syntax);
            }
        }

        match self.ready_state.get() {
            WebSocketRequestState::Closing | WebSocketRequestState::Closed  => {} //Do nothing
            WebSocketRequestState::Connecting => { //Connection is not yet established
                /*By setting the state to closing, the open function
                  will abort connecting the websocket*/
                self.ready_state.set(WebSocketRequestState::Closing);
                self.failed.set(true);
                self.sendCloseFrame.set(true);
                //Dispatch send task to send close frame
                //TODO: Sending here is just empty string, though no string is really needed. Another send, empty
                //      send, could be used.
                let _ = self.Send(None);
                //Note: After sending the close message, the receive loop confirms a close message from the server and
                //      must fire a close event
            }
            WebSocketRequestState::Open => {
                //Closing handshake not started - still in open
                //Start the closing by setting the code and reason if they exist
                if let Some(code) = code {
                    self.code.set(code);
                }
                if let Some(reason) = reason {
                    *self.reason.borrow_mut() = reason.0;
                }
                self.ready_state.set(WebSocketRequestState::Closing);
                self.sendCloseFrame.set(true);
                //Dispatch send task to send close frame
                let _ = self.Send(None);
                //Note: After sending the close message, the receive loop confirms a close message from the server and
                //      must fire a close event
            }
        }
        Ok(()) //Return Ok
    }
}

pub enum WebSocketTask {
    /// Task queued when *the WebSocket connection is established*.
    ConnectionEstablished,
    Close,
}

pub struct WebSocketTaskHandler {
    addr: Trusted<WebSocket>,
    task: WebSocketTask,
}

impl WebSocketTaskHandler {
    pub fn new(addr: Trusted<WebSocket>, task: WebSocketTask) -> WebSocketTaskHandler {
        WebSocketTaskHandler {
            addr: addr,
            task: task,
        }
    }

    fn connection_established(&self) {
        /*TODO: Items 1, 3, 4, & 5 under "WebSocket connection is established" as specified here:
          https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol
        */
        let ws = self.addr.root();

        // Step 1: Protocols.

        // Step 2.
        ws.ready_state.set(WebSocketRequestState::Open);

        // Step 3: Extensions.
        // Step 4: Protocols.
        // Step 5: Cookies.

        // Step 6.
        let global = ws.global.root();
        let event = Event::new(global.r(), "open".to_owned(),
                               EventBubbles::DoesNotBubble,
                               EventCancelable::NotCancelable);
        event.fire(EventTargetCast::from_ref(ws.r()));
    }

    fn dispatch_close(&self) {
        let ws = self.addr.root();
        let ws = ws.r();
        let global = ws.global.root();
        ws.ready_state.set(WebSocketRequestState::Closed);
        //If failed or full, fire error event
        if ws.failed.get() || ws.full.get() {
            ws.failed.set(false);
            ws.full.set(false);
            //A Bad close
            ws.clean_close.set(false);
            let event = Event::new(global.r(),
                                   "error".to_owned(),
                                   EventBubbles::DoesNotBubble,
                                   EventCancelable::Cancelable);
            let target = EventTargetCast::from_ref(ws);
            event.r().fire(target);
        }
        let rsn = ws.reason.borrow();
        let rsn_clone = rsn.clone();
        /*In addition, we also have to fire a close even if error event fired
         https://html.spec.whatwg.org/multipage/#closeWebSocket
        */
        let close_event = CloseEvent::new(global.r(),
                                          "close".to_owned(),
                                          EventBubbles::DoesNotBubble,
                                          EventCancelable::NotCancelable,
                                          ws.clean_close.get(),
                                          ws.code.get(),
                                          rsn_clone);
        let target = EventTargetCast::from_ref(ws);
        let event = EventCast::from_ref(close_event.r());
        event.fire(target);
    }
}

impl Runnable for WebSocketTaskHandler {
    fn handler(self: Box<WebSocketTaskHandler>) {
        match self.task {
            WebSocketTask::ConnectionEstablished => {
                self.connection_established();
            }
            WebSocketTask::Close => {
                self.dispatch_close();
            }
        }
    }
}

<|endoftext|>


<commit_before>extern crate proc_macro;
use crate::proc_macro::TokenStream;

use quote::quote;
use syn::DeriveInput;

#[proc_macro_derive(CommandBoxClone)]
pub fn command_box_clone(input: TokenStream) -> TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    let name = input.ident;

    let expanded = quote! {
        impl CommandBoxClone for #name {
            fn box_clone(&self) -> Box<dyn Command> {
                Box::new(self.clone())
            }
        }
    };

    expanded.into()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<commit_msg>Added note to command_derive to clean it up later<commit_after>// TODO: Can this be better now that Rust 2018 is stable?

extern crate proc_macro;
use crate::proc_macro::TokenStream;

use quote::quote;
use syn::DeriveInput;

#[proc_macro_derive(CommandBoxClone)]
pub fn command_box_clone(input: TokenStream) -> TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    let name = input.ident;

    let expanded = quote! {
        impl CommandBoxClone for #name {
            fn box_clone(&self) -> Box<dyn Command> {
                Box::new(self.clone())
            }
        }
    };

    expanded.into()
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<|endoftext|>


<commit_before>use crate::{error::{Error as HabError,
                    Result},
            hcore::fs::{am_i_root,
                        FS_ROOT_PATH},
            CTL_SECRET_ENVVAR};
use habitat_core::{env as henv,
                   origin::Origin};
use habitat_sup_client::SrvClient;
use std::{fs::{self,
               File},
          io::{self,
               Write},
          path::{Path,
                 PathBuf}};

const CLI_CONFIG_PATH_POSTFIX: &str = "hab/etc/cli.toml";

lazy_static::lazy_static! {
    pub static ref CLI_CONFIG_PATH: PathBuf = cli_config_path();
    pub static ref CLI_CONFIG_PATH_PARENT: &'static Path = CLI_CONFIG_PATH
                                                    .parent()
                                                    .expect("cli config path parent");

    /// A cached reading of the config file. This avoids the need to continually read from disk.
    /// However, it also means changes to the file will not be picked up after the program has
    /// started. Ideally, we would repopulate this struct on file change or on some configured
    /// interval.
    /// https://github.com/habitat-sh/habitat/issues/7243
    pub static ref CACHED: Config = load().unwrap_or_default();
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("reading '{}' failed, err: {0}", CLI_CONFIG_PATH.display())]
    File(#[from] io::Error),
    #[error("parsing '{}' failed, err: {0}", CLI_CONFIG_PATH.display())]
    Toml(#[from] toml::de::Error),
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Config {
    pub auth_token: Option<String>,
    pub origin:     Option<Origin>,
    pub ctl_secret: Option<String>,
    pub bldr_url:   Option<String>,
}

impl Config {
    fn from_file<T: AsRef<Path>>(path: T) -> std::result::Result<Self, Error> {
        let raw = fs::read_to_string(path)?;
        Ok(toml::from_str(&raw)?)
    }
}

impl Default for Config {
    fn default() -> Self {
        Config { auth_token: None,
                 origin:     None,
                 ctl_secret: None,
                 bldr_url:   None, }
    }
}

pub fn load() -> std::result::Result<Config, Error> {
    if CLI_CONFIG_PATH.exists() {
        debug!("Loading CLI config from {}", CLI_CONFIG_PATH.display());
        Ok(Config::from_file(&*CLI_CONFIG_PATH)?)
    } else {
        debug!("No CLI config found, loading defaults");
        Ok(Config::default())
    }
}

pub fn save(config: &Config) -> Result<()> {
    fs::create_dir_all(&*CLI_CONFIG_PATH_PARENT)?;
    let raw = toml::ser::to_string(config)?;
    debug!("Raw config toml:\n---\n{}\n---", &raw);
    let mut file = File::create(&*CLI_CONFIG_PATH)?;
    file.write_all(raw.as_bytes())?;
    Ok(())
}

/// Check if the HAB_CTL_SECRET env var. If not, check the CLI config to see if there is a ctl
/// secret set and return a copy of that value.
pub fn ctl_secret_key(config: &Config) -> Result<String> {
    match henv::var(CTL_SECRET_ENVVAR) {
        Ok(v) => Ok(v),
        Err(_) => {
            match config.ctl_secret {
                Some(ref v) => Ok(v.to_string()),
                None => SrvClient::read_secret_key().map_err(HabError::from),
            }
        }
    }
}

fn cli_config_path() -> PathBuf {
    if !am_i_root() {
        if let Some(home) = dirs::home_dir() {
            return home.join(format!(".{}", CLI_CONFIG_PATH_POSTFIX));
        }
    }
    PathBuf::from(&*FS_ROOT_PATH).join(CLI_CONFIG_PATH_POSTFIX)
}
<commit_msg>[Refactor] derive(Default) for Config<commit_after>use crate::{error::{Error as HabError,
                    Result},
            hcore::fs::{am_i_root,
                        FS_ROOT_PATH},
            CTL_SECRET_ENVVAR};
use habitat_core::{env as henv,
                   origin::Origin};
use habitat_sup_client::SrvClient;
use std::{fs::{self,
               File},
          io::{self,
               Write},
          path::{Path,
                 PathBuf}};

const CLI_CONFIG_PATH_POSTFIX: &str = "hab/etc/cli.toml";

lazy_static::lazy_static! {
    pub static ref CLI_CONFIG_PATH: PathBuf = cli_config_path();
    pub static ref CLI_CONFIG_PATH_PARENT: &'static Path = CLI_CONFIG_PATH
                                                    .parent()
                                                    .expect("cli config path parent");

    /// A cached reading of the config file. This avoids the need to continually read from disk.
    /// However, it also means changes to the file will not be picked up after the program has
    /// started. Ideally, we would repopulate this struct on file change or on some configured
    /// interval.
    /// https://github.com/habitat-sh/habitat/issues/7243
    pub static ref CACHED: Config = load().unwrap_or_default();
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("reading '{}' failed, err: {0}", CLI_CONFIG_PATH.display())]
    File(#[from] io::Error),
    #[error("parsing '{}' failed, err: {0}", CLI_CONFIG_PATH.display())]
    Toml(#[from] toml::de::Error),
}

#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
pub struct Config {
    pub auth_token: Option<String>,
    pub origin:     Option<Origin>,
    pub ctl_secret: Option<String>,
    pub bldr_url:   Option<String>,
}

impl Config {
    fn from_file<T: AsRef<Path>>(path: T) -> std::result::Result<Self, Error> {
        let raw = fs::read_to_string(path)?;
        Ok(toml::from_str(&raw)?)
    }
}

pub fn load() -> std::result::Result<Config, Error> {
    if CLI_CONFIG_PATH.exists() {
        debug!("Loading CLI config from {}", CLI_CONFIG_PATH.display());
        Ok(Config::from_file(&*CLI_CONFIG_PATH)?)
    } else {
        debug!("No CLI config found, loading defaults");
        Ok(Config::default())
    }
}

pub fn save(config: &Config) -> Result<()> {
    fs::create_dir_all(&*CLI_CONFIG_PATH_PARENT)?;
    let raw = toml::ser::to_string(config)?;
    debug!("Raw config toml:\n---\n{}\n---", &raw);
    let mut file = File::create(&*CLI_CONFIG_PATH)?;
    file.write_all(raw.as_bytes())?;
    Ok(())
}

/// Check if the HAB_CTL_SECRET env var. If not, check the CLI config to see if there is a ctl
/// secret set and return a copy of that value.
pub fn ctl_secret_key(config: &Config) -> Result<String> {
    match henv::var(CTL_SECRET_ENVVAR) {
        Ok(v) => Ok(v),
        Err(_) => {
            match config.ctl_secret {
                Some(ref v) => Ok(v.to_string()),
                None => SrvClient::read_secret_key().map_err(HabError::from),
            }
        }
    }
}

fn cli_config_path() -> PathBuf {
    if !am_i_root() {
        if let Some(home) = dirs::home_dir() {
            return home.join(format!(".{}", CLI_CONFIG_PATH_POSTFIX));
        }
    }
    PathBuf::from(&*FS_ROOT_PATH).join(CLI_CONFIG_PATH_POSTFIX)
}
<|endoftext|>


<commit_before>use async_trait::async_trait;
use std::fmt::Debug;

use tokio::sync::mpsc::{channel, Receiver, Sender};

#[async_trait]
pub trait Actor<M> {
    async fn route_message(&mut self, message: M);
}

pub struct Router<A, M>
    where A: Actor<M>,
{
    actor_impl: A,
    receiver: Receiver<M>,
}

impl<A, M> Router<A, M> {
    pub fn new(
        actor_impl: A,
        receiver: Receiver<M>,
    ) -> Self {
        Self {
            actor_impl,
            receiver,
        }
    }
}

pub async fn route_wrapper<A, M>(mut router: Router<A, M>)
    where A: Actor<M>,
{
    tokio::task::yield_now().await;

    while let Some(msg) = router.receiver.recv().await {
        router.actor_impl.route_message(msg).await;
    }
}<commit_msg>Rewrite<commit_after>use async_trait::async_trait;
use std::fmt::Debug;

use tokio::sync::mpsc::{channel, Receiver, Sender};

#[async_trait]
pub trait Actor<M> {
    async fn route_message(&mut self, message: M);
}

pub struct Router<A, M>
    where A: Actor<M>,
{
    actor_impl: A,
    receiver: Receiver<M>,
}

impl<A, M> Router<A, M>
    where A: Actor<M>,
{
    pub fn new(
        actor_impl: A,
        receiver: Receiver<M>,
    ) -> Self {
        Self {
            actor_impl,
            receiver,
        }
    }
}

pub async fn route_wrapper<A, M>(mut router: Router<A, M>)
    where A: Actor<M>,
{
    tokio::task::yield_now().await;

    while let Some(msg) = router.receiver.recv().await {
        router.actor_impl.route_message(msg).await;
    }
}<|endoftext|>


<commit_before>// Copyright (c) 2015 T. Okubo
// This file is part of vlc-rs.
// Licensed under the MIT license, see the LICENSE file.

use sys;
use ::MediaPlayer;
use ::TrackDescription;
use ::tools::from_cstr;

pub trait MediaPlayerAudioEx {
    fn get_mute(&self) -> Option<bool>;
    fn set_mute(&self, bool);
    fn get_volume(&self) -> i32;
    fn set_volume(&self, volume: i32) -> Result<(), ()>;
    fn get_audio_track_description(&self) -> Option<Vec<TrackDescription>>;
}

impl MediaPlayerAudioEx for MediaPlayer {
    fn get_mute(&self) -> Option<bool> {
        let r = unsafe{ sys::libvlc_audio_get_mute(self.ptr) };

        if r == 0 {
            Some(false)
        }else if r == -1 {
            None
        }else{
            Some(true)
        }
    }

    fn set_mute(&self, status: bool) {
        unsafe{ sys::libvlc_audio_set_mute(self.ptr, if status { 1 }else{ 0 }) };
    }

    fn get_volume(&self) -> i32 {
        unsafe{ sys::libvlc_audio_get_volume(self.ptr) }
    }
    fn set_volume(&self, volume: i32) -> Result<(), ()> {
        unsafe{
            if sys::libvlc_audio_set_volume(self.ptr, volume) == 0 { Ok(()) }else{ Err(()) }
        }
    }
    fn get_audio_track_description(&self) -> Option<Vec<TrackDescription>> {
        unsafe{
            let p0 = sys::libvlc_audio_get_track_description(self.ptr);
            if p0.is_null() { return None; }
            let mut td = Vec::new();
            let mut p = p0;

            while !(*p).p_next.is_null() {
                td.push(TrackDescription{ id: (*p).i_id, name: from_cstr((*p).psz_name) });
                p = (*p).p_next;
            }
            sys::libvlc_track_description_list_release(p0);
            Some(td)
        }
    }

}
<commit_msg>audio: fix obsolete unnamed parameter<commit_after>// Copyright (c) 2015 T. Okubo
// This file is part of vlc-rs.
// Licensed under the MIT license, see the LICENSE file.

use sys;
use ::MediaPlayer;
use ::TrackDescription;
use ::tools::from_cstr;

pub trait MediaPlayerAudioEx {
    fn get_mute(&self) -> Option<bool>;
    fn set_mute(&self, muted: bool);
    fn get_volume(&self) -> i32;
    fn set_volume(&self, volume: i32) -> Result<(), ()>;
    fn get_audio_track_description(&self) -> Option<Vec<TrackDescription>>;
}

impl MediaPlayerAudioEx for MediaPlayer {
    fn get_mute(&self) -> Option<bool> {
        let r = unsafe{ sys::libvlc_audio_get_mute(self.ptr) };

        if r == 0 {
            Some(false)
        }else if r == -1 {
            None
        }else{
            Some(true)
        }
    }

    fn set_mute(&self, status: bool) {
        unsafe{ sys::libvlc_audio_set_mute(self.ptr, if status { 1 }else{ 0 }) };
    }

    fn get_volume(&self) -> i32 {
        unsafe{ sys::libvlc_audio_get_volume(self.ptr) }
    }
    fn set_volume(&self, volume: i32) -> Result<(), ()> {
        unsafe{
            if sys::libvlc_audio_set_volume(self.ptr, volume) == 0 { Ok(()) }else{ Err(()) }
        }
    }
    fn get_audio_track_description(&self) -> Option<Vec<TrackDescription>> {
        unsafe{
            let p0 = sys::libvlc_audio_get_track_description(self.ptr);
            if p0.is_null() { return None; }
            let mut td = Vec::new();
            let mut p = p0;

            while !(*p).p_next.is_null() {
                td.push(TrackDescription{ id: (*p).i_id, name: from_cstr((*p).psz_name) });
                p = (*p).p_next;
            }
            sys::libvlc_track_description_list_release(p0);
            Some(td)
        }
    }

}
<|endoftext|>