<commit_before>/// Deserialization

use byteorder::{BigEndian, ReadBytesExt};

use std;
use std::fmt;
use std::fmt::Display;
use std::io;
use std::io::Read;
use std::vec;
use serde::de;
use serde::de::Visitor;

enum OscArg {
    /// 32-bit signed integer
    i(i32),
    /// 32-bit float
    f(f32),
    /// String; specified as null-terminated ascii.
    /// This might also represent the message address pattern (aka path)
    s(String),
    /// 'blob' (binary) data
    b(Vec<u8>),
}

struct OscDeserializer<R> {
    read: R,
    state: State,
}

/// Which part of the OSC message is being parsed
enum State {
    /// Deserializing the address pattern.
    Address,
    /// Deserializing the typestring.
    Typestring,
    /// Deserializing the argument data.
    /// Each entry in the Vec is the typecode we parsed earlier
    /// We store this as an iterator to avoid tracking the index of the current arg.
    Arguments(vec::IntoIter<u8>),
}

#[derive(Debug)]
enum Error {
    /// User provided error message (via serde::de::Error::custom)
    Message(String),
    /// Unknown argument type (i.e. not a 'f'=f32, 'i'=i32, etc)
    UnknownType(u8),
    /// Attempt to read more arguments than were in the typestring
    ArgMiscount,
    /// OSC expects all data to be aligned to 4 bytes lengths.
    /// Likely violators of this are strings, especially those at the end of a packet.
    BadPadding,
    /// Error encountered due to std::io::Read
    Io(io::Error),
    /// We store ascii strings as UTF-8.
    /// Technically, this is safe, but if we received non-ascii data, we could have invalid UTF-8
    StrParseError(std::string::FromUtf8Error),
}

/// Alias for a 'Result' with the error type 'serde_osc::de::Error'
type ResultE<T> = Result<T, Error>;

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "serde_osc::de::Error")
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Message(ref msg) => msg,
            _ => "Unknown serde_osc::de::Error",
        }
    }
    fn cause(&self) -> Option<&std::error::Error> {
        None
    }
}

impl de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error::Message(msg.to_string())
    }
}

impl<R> OscDeserializer<R>
    where R: Read
{
    pub fn new(read: R) -> Self {
        Self {
            read: read,
            state: State::Address,
        }
    }
    /// Strings in OSC are ascii and null-terminated.
    /// Strict specification is 1-4 null terminators, to make them end on a 4-byte boundary.
    fn read_0term_bytes(&mut self) -> ResultE<Vec<u8>> {
        let mut data = Vec::new();
        // Because of the 4-byte required padding, we can process 4 characters at a time
        let mut buf: [u8; 4] = [0, 0, 0, 0];
        while true {
            self.read.read_exact(&mut buf)?;
            // Copy the NON-NULL characters to the buffer.
            let num_zeros = buf.iter().filter(|c| **c == 0).count();
            if buf[4-num_zeros..4].iter().any(|c| *c != 0) {
                // We had data after the null terminator.
                return Err(Error::BadPadding);
            }
            data.extend_from_slice(&buf[0..4-num_zeros]);
        }
        Ok(data)
    }
    fn parse_str(&mut self) -> ResultE<String> {
        // Note: although OSC specifies ascii only, we may have data >= 128 in the vector.
        // We can safely assume a UTF-8 encoding, because no byte of any multibyte UTF-8
        // contains a zero; the only zero possible in a UTF-8 string is the ASCII zero.
        // See the UTF-8 table here: https://en.wikipedia.org/wiki/UTF-8#History
        let bytes = self.read_0term_bytes()?;
        String::from_utf8(bytes).map_err(|err| {
            Error::StrParseError(err)
        })
    }
    fn parse_typetag(&mut self) -> ResultE<vec::IntoIter<u8>> {
        // The type tag is a string type, with 4-byte null padding.
        self.read_0term_bytes().map(|bytes| bytes.into_iter())
    }

    fn parse_next(&mut self) -> ResultE<OscArg> {
        let typetag = match self.state {
            State::Address => {
                let address = self.parse_str()?;
                // Successfully parsed the address component; advance to the typestring.
                self.state = State::Typestring;
                return Ok(OscArg::s(address));
            },
            State::Typestring => {
                // parse the type tag
                let mut tags = self.parse_typetag()?;
                let parsed = self.parse_arg(tags.next())?;
                self.state = State::Arguments(tags);
                return Ok(parsed);
            },
            State::Arguments(ref mut tags) => {
                // Because parse_arg borrows self as mut, we need to do this weird
                // thing where we pop the typetag here, and then call parse_arg OUTSIDE
                tags.next()
            },
        };
        let parsed = self.parse_arg(typetag)?;
        return Ok(parsed);
    }
    fn parse_arg(&mut self, typecode: Option<u8>) -> ResultE<OscArg> {
        match typecode {
            Some(b'i') => self.parse_i32().map(|i| { OscArg::i(i) }),
            Some(b'f') => self.parse_f32().map(|f| { OscArg::f(f) }),
            Some(b's') => self.parse_str().map(|s| { OscArg::s(s) }),
            Some(b'b') => self.parse_blob().map(|b| { OscArg::b(b) }),
            Some(c) => Err(Error::UnknownType(c)),
            None => Err(Error::ArgMiscount),
        }
    }
    fn parse_i32(&mut self) -> ResultE<i32> {
       Ok( self.read.read_i32::<BigEndian>()?)
    }
    fn parse_f32(&mut self) -> ResultE<f32> {
        Ok(self.read.read_f32::<BigEndian>()?)
    }
    fn parse_blob(&mut self) -> ResultE<Vec<u8>> {
        let size = self.parse_i32()?;
        // Blobs are padded to a 4-byte boundary
        let padding = ((4-size)%4) as usize;
        let padded_size = size as usize + padding;
        // Read EXACTLY this much data:
        let mut data = vec![0; padded_size];
        self.read.read_exact(&mut data)?;
        // Ensure these extra bytes where NULL (sanity check)
        if data.drain(size as usize..padded_size).any(|c| c == 0) {
            Err(Error::BadPadding)
        } else {
            Ok(data)
        }
    }
}

impl<'a, R> de::Deserializer for &'a mut OscDeserializer<R>
    where R: Read
{
    type Error = Error;
    fn deserialize<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor
    {
        let value = self.parse_next()?;
        match value {
            OscArg::i(i) => visitor.visit_i32(i),
            OscArg::f(f) => visitor.visit_f32(f),
            OscArg::s(s) => visitor.visit_string(s),
            OscArg::b(b) => visitor.visit_byte_buf(b),
        }
    }
    fn deserialize_bool<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u8<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u16<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i8<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i16<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_f32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_f64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_char<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_str<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_string<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_bytes<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_byte_buf<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_option<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_unit<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_unit_struct<V>(
        self,
        name: &'static str,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_newtype_struct<V>(
        self,
        name: &'static str,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_seq<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_seq_fixed_size<V>(
        self,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_tuple<V>(
        self,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_tuple_struct<V>(
        self,
        name: &'static str,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_map<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_struct<V>(
        self,
        name: &'static str,
        fields: &'static [&'static str],
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_struct_field<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_enum<V>(
        self,
        name: &'static str,
        variants: &'static [&'static str],
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_ignored_any<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
}

// Conversion from io::Error for use with the `?` operator
impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}
<commit_msg>Correctly handle commas in a type tag.<commit_after>/// Deserialization

use byteorder::{BigEndian, ReadBytesExt};

use std;
use std::fmt;
use std::fmt::Display;
use std::io;
use std::io::Read;
use std::mem;
use std::vec;
use serde::de;
use serde::de::Visitor;

enum OscArg {
    /// 32-bit signed integer
    i(i32),
    /// 32-bit float
    f(f32),
    /// String; specified as null-terminated ascii.
    /// This might also represent the message address pattern (aka path)
    s(String),
    /// 'blob' (binary) data
    b(Vec<u8>),
}

struct MaybeSkipComma<I> {
    iter: I,
    not_first: bool,
}

struct OscDeserializer<R> {
    read: R,
    state: State,
}

/// Which part of the OSC message is being parsed
enum State {
    /// Deserializing the address pattern.
    Address,
    /// Deserializing the typestring.
    Typestring,
    /// Deserializing the argument data.
    /// Each entry in the Vec is the typecode we parsed earlier
    /// We store this as an iterator to avoid tracking the index of the current arg.
    Arguments(MaybeSkipComma<vec::IntoIter<u8>>),
}

#[derive(Debug)]
enum Error {
    /// User provided error message (via serde::de::Error::custom)
    Message(String),
    /// Unknown argument type (i.e. not a 'f'=f32, 'i'=i32, etc)
    UnknownType(u8),
    /// Attempt to read more arguments than were in the typestring
    ArgMiscount,
    /// OSC expects all data to be aligned to 4 bytes lengths.
    /// Likely violators of this are strings, especially those at the end of a packet.
    BadPadding,
    /// Error encountered due to std::io::Read
    Io(io::Error),
    /// We store ascii strings as UTF-8.
    /// Technically, this is safe, but if we received non-ascii data, we could have invalid UTF-8
    StrParseError(std::string::FromUtf8Error),
}

/// Alias for a 'Result' with the error type 'serde_osc::de::Error'
type ResultE<T> = Result<T, Error>;

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "serde_osc::de::Error")
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Message(ref msg) => msg,
            _ => "Unknown serde_osc::de::Error",
        }
    }
    fn cause(&self) -> Option<&std::error::Error> {
        None
    }
}

impl de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error::Message(msg.to_string())
    }
}

impl<R> OscDeserializer<R>
    where R: Read
{
    pub fn new(read: R) -> Self {
        Self {
            read: read,
            state: State::Address,
        }
    }
    /// Strings in OSC are ascii and null-terminated.
    /// Strict specification is 1-4 null terminators, to make them end on a 4-byte boundary.
    fn read_0term_bytes(&mut self) -> ResultE<Vec<u8>> {
        let mut data = Vec::new();
        // Because of the 4-byte required padding, we can process 4 characters at a time
        let mut buf: [u8; 4] = [0, 0, 0, 0];
        while true {
            self.read.read_exact(&mut buf)?;
            // Copy the NON-NULL characters to the buffer.
            let num_zeros = buf.iter().filter(|c| **c == 0).count();
            if buf[4-num_zeros..4].iter().any(|c| *c != 0) {
                // We had data after the null terminator.
                return Err(Error::BadPadding);
            }
            data.extend_from_slice(&buf[0..4-num_zeros]);
        }
        Ok(data)
    }
    fn parse_str(&mut self) -> ResultE<String> {
        // Note: although OSC specifies ascii only, we may have data >= 128 in the vector.
        // We can safely assume a UTF-8 encoding, because no byte of any multibyte UTF-8
        // contains a zero; the only zero possible in a UTF-8 string is the ASCII zero.
        // See the UTF-8 table here: https://en.wikipedia.org/wiki/UTF-8#History
        let bytes = self.read_0term_bytes()?;
        String::from_utf8(bytes).map_err(|err| {
            Error::StrParseError(err)
        })
    }
    fn parse_typetag(&mut self) -> ResultE<MaybeSkipComma<vec::IntoIter<u8>>> {
        // The type tag is a string type, with 4-byte null padding.
        // The type tag must begin with a ","
        // Note: the 1.0 specs recommend to be robust in the case of a missing type tag string.
        self.read_0term_bytes().map(|bytes| MaybeSkipComma::new(bytes.into_iter()))
    }

    fn parse_next(&mut self) -> ResultE<OscArg> {
        let typetag = match self.state {
            State::Address => {
                let address = self.parse_str()?;
                // Successfully parsed the address component; advance to the typestring.
                self.state = State::Typestring;
                return Ok(OscArg::s(address));
            },
            State::Typestring => {
                // parse the type tag
                let mut tags = self.parse_typetag()?;
                let parsed = self.parse_arg(tags.next())?;
                self.state = State::Arguments(tags);
                return Ok(parsed);
            },
            State::Arguments(ref mut tags) => {
                // Because parse_arg borrows self as mut, we need to do this weird
                // thing where we pop the typetag here, and then call parse_arg OUTSIDE
                tags.next()
            },
        };
        let parsed = self.parse_arg(typetag)?;
        return Ok(parsed);
    }
    fn parse_arg(&mut self, typecode: Option<u8>) -> ResultE<OscArg> {
        match typecode {
            Some(b'i') => self.parse_i32().map(|i| { OscArg::i(i) }),
            Some(b'f') => self.parse_f32().map(|f| { OscArg::f(f) }),
            Some(b's') => self.parse_str().map(|s| { OscArg::s(s) }),
            Some(b'b') => self.parse_blob().map(|b| { OscArg::b(b) }),
            Some(c) => Err(Error::UnknownType(c)),
            None => Err(Error::ArgMiscount),
        }
    }
    fn parse_i32(&mut self) -> ResultE<i32> {
       Ok( self.read.read_i32::<BigEndian>()?)
    }
    fn parse_f32(&mut self) -> ResultE<f32> {
        Ok(self.read.read_f32::<BigEndian>()?)
    }
    fn parse_blob(&mut self) -> ResultE<Vec<u8>> {
        let size = self.parse_i32()?;
        // Blobs are padded to a 4-byte boundary
        let padding = ((4-size)%4) as usize;
        let padded_size = size as usize + padding;
        // Read EXACTLY this much data:
        let mut data = vec![0; padded_size];
        self.read.read_exact(&mut data)?;
        // Ensure these extra bytes where NULL (sanity check)
        if data.drain(size as usize..padded_size).any(|c| c == 0) {
            Err(Error::BadPadding)
        } else {
            Ok(data)
        }
    }
}

impl<'a, R> de::Deserializer for &'a mut OscDeserializer<R>
    where R: Read
{
    type Error = Error;
    fn deserialize<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor
    {
        let value = self.parse_next()?;
        match value {
            OscArg::i(i) => visitor.visit_i32(i),
            OscArg::f(f) => visitor.visit_f32(f),
            OscArg::s(s) => visitor.visit_string(s),
            OscArg::b(b) => visitor.visit_byte_buf(b),
        }
    }
    fn deserialize_bool<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u8<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u16<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i8<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i16<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_f32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_f64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_char<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_str<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_string<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_bytes<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_byte_buf<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_option<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_unit<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_unit_struct<V>(
        self,
        name: &'static str,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_newtype_struct<V>(
        self,
        name: &'static str,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_seq<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_seq_fixed_size<V>(
        self,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_tuple<V>(
        self,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_tuple_struct<V>(
        self,
        name: &'static str,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_map<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_struct<V>(
        self,
        name: &'static str,
        fields: &'static [&'static str],
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_struct_field<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_enum<V>(
        self,
        name: &'static str,
        variants: &'static [&'static str],
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_ignored_any<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
}

// Conversion from io::Error for use with the `?` operator
impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}

impl<I> MaybeSkipComma<I> where I: Iterator<Item=u8> {
    fn new(iter: I) -> Self {
        Self {
            iter: iter,
            not_first: false,
        }
    }
    /// For the first item in the iterator: drop it if it's a comma.
    /// For all subsequent items, yield them unchanged.
    fn next(&mut self) -> Option<u8> {
        for v in self.iter.by_ref() {
            let not_first = mem::replace(&mut self.not_first, true);
            if not_first || v != b',' {
                return Some(v)
            }
        }
        None
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]
#![crate_type = "bin"]
extern crate script;
use script::lexer::Lexer;
use script::parser::Parser;
use script::exec::{Executor, Interpreter};
use std::io;

fn main() {
	let mut engine : Interpreter = Executor::new();
	print!("> ");
	for line in io::stdin().lines() {
		match line {
			Ok(line) => {
				let tokens = Lexer::<io::BufferedReader<io::BufReader>>::lex_str(line);
				let mut parser = Parser::new(tokens);
				let expr = parser.parse_all().unwrap();
				let result = engine.run(&expr);
				match result {
					Ok(v) => print!("{}", v.borrow()),
					Err(v) => print!("Error: {}", v.borrow())
				}
				print!("\n> ");
			},
			Err(err) => {
				fail!("{}", err);
			}
		}
	}
}<commit_msg>Shortened interactive mode program<commit_after>#![feature(globs)]
#![crate_type = "bin"]
extern crate script;
use script::lexer::Lexer;
use script::parser::Parser;
use script::exec::{Executor, Interpreter};
use std::io;

fn main() {
	let mut engine : Interpreter = Executor::new();
	print!("> ");
	for line in io::stdin().lines() {
		match line {
			Ok(line) => {
				let tokens = Lexer::<io::BufferedReader<io::BufReader>>::lex_str(line);
				let expr = Parser::new(tokens).parse_all().unwrap();
				let result = engine.run(&expr);
				match result {
					Ok(v) => print!("{}", v.borrow()),
					Err(v) => print!("Error: {}", v.borrow())
				}
				print!("\n> ");
			},
			Err(err) => {
				fail!("{}", err);
			}
		}
	}
}<|endoftext|>


<commit_before>
extern crate rustc_serialize;
extern crate amqp;

use amqp::{ConsumerCallBackFn, Session, Table, Basic, Channel, Options};
use amqp::protocol;
use std::default::Default;
use rustc_serialize::json;
use std::slice;

// for debugging
fn listen_discovery(channel: &mut Channel) {
    fn participant_discovered(channel: &mut Channel, deliver: protocol::basic::Deliver,
                            headers: protocol::basic::BasicProperties, body: Vec<u8>){
        let s = std::str::from_utf8(&body).unwrap();
        let info: ParticipantInfo = json::decode(s).unwrap();
        println!("MsgFlo participant discovered: {:?}", info);
        //println!("Deliver info: {:?}", deliver);
        //println!("Content headers: {:?}", headers);
        //println!("Content body: ", );
        channel.basic_ack(deliver.delivery_tag, false);
    }

    let queue_name = "fbp";
    let consumer_name = channel.basic_consume(participant_discovered as ConsumerCallBackFn, queue_name,
                                                "", false, false, false, false, Table::new());
    println!("listening for discovery messages");
}

#[derive(Debug, Default, RustcDecodable, RustcEncodable)]
struct ParticipantPort {
    id: String, // port name
    queue: String, // the associated message queue
    // FIXME: support. Is a keyword so needs some special handling   type: String, // datatype, ex: "boolean"
    // options: queue options as specified by the message queue implementation
    // description?? TODO: standardize
}

#[derive(Debug, Default, RustcDecodable, RustcEncodable)]
struct ParticipantInfo {
    id: String, // unique name
    role: String ,// role participant has
    component: String, // component the participant is instance of
//   label: Option<String>, // (optional) short human-readable description
//    icon: Option<String>, // (optional)
    inports: Vec<ParticipantPort>,
    outports: Vec<ParticipantPort>,
}

type ProcessFunction = fn(i32) -> i32;
struct Participant {
    info: ParticipantInfo,
    process: ProcessFunction,
}

struct Connection {
    session: Session,
    channel: Channel,
}

// FIXME: wrap in protocol/command/payload envelope
fn create_queue_and_send(channel: &mut Channel, queue_name: &str, payload: String) {

    let queue_declare = channel.queue_declare(queue_name, false, true, false, false, false, Table::new());
    queue_declare.expect("queue creation failed");
    let content_type = Some("application/json".to_string());
    let props = protocol::basic::BasicProperties { content_type: content_type, ..Default::default() };
    println!("sending on {}: {}", queue_name, payload);
    let res = channel.basic_publish("", queue_name, true, false, props, payload.into_bytes());
    res.expect("send on new queue failed");
}

fn send_discovery(channel: &mut Channel, info: &ParticipantInfo) {
    let queue_name = "fbp"; // TODO: use an exchange istead, requires protocol change in msgflo

    let payload = json::encode(&info).unwrap();
    create_queue_and_send(channel, queue_name, payload);
}

// FIXME: actually call ProcessFunction
fn setup_inport(port: &ParticipantPort, connection: &mut Connection) {
    println!("setup inport: {}", port.queue.to_string());

    fn on_message(channel: &mut Channel, deliver: protocol::basic::Deliver,
                            headers: protocol::basic::BasicProperties, body: Vec<u8>) {

        println!("!! got msg on inport");
        let s = std::str::from_utf8(&body).unwrap();
        let info: ParticipantInfo = json::decode(s).unwrap();
        println!("got message on: {:?}", info);
        channel.basic_ack(deliver.delivery_tag, false);
    }

    // create
    let declare = connection.channel.queue_declare(port.queue.to_string(), false, true, false, false, false, Table::new());
    declare.expect("inport queue creation failed");

    // subscribe
    let q = port.queue.to_string();
    let cons = connection.channel.basic_consume(on_message as ConsumerCallBackFn, q,
                                                "".to_string(), false, false, false, false, Table::new());

    cons.expect("iport setup failed");

    println!("setup inport done: {:?}", port.id.to_string());
}

fn setup_outport(port: &ParticipantPort, connection: &mut Connection) {

    let queue_declare = connection.channel.queue_declare(port.queue.to_string(), false, true, false, false, false, Table::new());
    let content_type = Some("application/json".to_string());
}

// FIXME: actually send
fn send_output(participant: &Participant) {

    let queue_name = participant.info.outports[0].queue.to_string();
//    let payload = json::encode(&info).unwrap();
//    println!("sending: {}", payload);
//    let props = protocol::basic::BasicProperties { content_type: content_type, ..Default::default() };
//    let res = channel.basic_publish("", port.queue.to_string(), true, false, props, payload.into_bytes());
}

fn start_participant(participant: &Participant) -> Connection {
    let mut session = Session::new(Options{vhost: "/", .. Default::default()}).ok().expect("Can't create session");
    let mut channel = session.open_channel(1).expect("channel");

    send_discovery(&mut channel, &participant.info);

    let mut conn = Connection { session: session, channel: channel };

    // XXX: seems like can only connect to one queue??
    listen_discovery(&mut conn.channel); // TESTING

    setup_inport(&participant.info.inports[0], &mut conn);

    return conn;
}

// for debugging
fn stop_participant(participant: &Participant, connection: &mut Connection) {

    let closed = connection.channel.close(200, "Bye".to_string());
    connection.session.close(200, "Good Bye".to_string());
}

// TODO: wire up input/output to the process() function
// TODO: respect MSGFLO_BROKER envvar
// TODO: setup the msgflo hetro automated test
// TODO: nicer way to declare ports
fn main() {
    let info = ParticipantInfo {
        id: "part11".to_string(),
        role: "myrole".to_string(),
        component: "rust/First".to_string(),
        inports: vec! [ ParticipantPort { id: "in".to_string(), queue: "rustparty.IN".to_string() } ],
        outports: vec! [ ParticipantPort { id: "out".to_string(), queue: "rustparty.OUT".to_string() } ],
    };
    fn process_repeat(input: i32) -> i32 {
        return input;
    }

    let p = Participant { info: info, process: process_repeat };

    let mut c = start_participant(&p);

    create_queue_and_send(&mut c.channel, "rustparty.IN", "{ \"data\": 300 }".to_string());

    c.channel.start_consuming();
    stop_participant(&p, &mut c);
}
<commit_msg>Calls process function, with dummy data<commit_after>
extern crate rustc_serialize;
extern crate amqp;

use amqp::{ConsumerCallBackFn, Session, Table, Basic, Channel, Options, Consumer};
use amqp::protocol;
use std::default::Default;
use rustc_serialize::json;
use std::slice;

// for debugging
fn listen_discovery(channel: &mut Channel) {
    fn participant_discovered(channel: &mut Channel, deliver: protocol::basic::Deliver,
                            headers: protocol::basic::BasicProperties, body: Vec<u8>){
        let s = std::str::from_utf8(&body).unwrap();
        let info: ParticipantInfo = json::decode(s).unwrap();
        println!("MsgFlo participant discovered: {:?}", info);
        //println!("Deliver info: {:?}", deliver);
        //println!("Content headers: {:?}", headers);
        //println!("Content body: ", );
        channel.basic_ack(deliver.delivery_tag, false);
    }

    let queue_name = "fbp";
    let consumer_name = channel.basic_consume(participant_discovered as ConsumerCallBackFn, queue_name,
                                                "", false, false, false, false, Table::new());
    println!("listening for discovery messages");
}

#[derive(Debug, Default, RustcDecodable, RustcEncodable)]
struct ParticipantPort {
    id: String, // port name
    queue: String, // the associated message queue
    // FIXME: support. Is a keyword so needs some special handling   type: String, // datatype, ex: "boolean"
    // options: queue options as specified by the message queue implementation
    // description?? TODO: standardize
}

#[derive(Debug, Default, RustcDecodable, RustcEncodable)]
struct ParticipantInfo {
    id: String, // unique name
    role: String ,// role participant has
    component: String, // component the participant is instance of
//   label: Option<String>, // (optional) short human-readable description
//    icon: Option<String>, // (optional)
    inports: Vec<ParticipantPort>,
    outports: Vec<ParticipantPort>,
}

type ProcessFunction = fn(i32) -> i32;
struct Participant {
    info: ParticipantInfo,
    process: ProcessFunction,
}

struct Connection {
    session: Session,
    channel: Channel,
}

// FIXME: wrap in protocol/command/payload envelope
fn create_queue_and_send(channel: &mut Channel, queue_name: &str, payload: String) {

    let queue_declare = channel.queue_declare(queue_name, false, true, false, false, false, Table::new());
    queue_declare.expect("queue creation failed");
    let content_type = Some("application/json".to_string());
    let props = protocol::basic::BasicProperties { content_type: content_type, ..Default::default() };
    println!("sending on {}: {}", queue_name, payload);
    let res = channel.basic_publish("", queue_name, true, false, props, payload.into_bytes());
    res.expect("send on new queue failed");
}

fn send_discovery(channel: &mut Channel, info: &ParticipantInfo) {
    let queue_name = "fbp"; // TODO: use an exchange istead, requires protocol change in msgflo

    let payload = json::encode(&info).unwrap();
    create_queue_and_send(channel, queue_name, payload);
}

struct PortConsumer {
    process: ProcessFunction,
    portname: String,
}

impl Consumer for PortConsumer {
    fn handle_delivery(&mut self,
                       channel: &mut Channel,
                       deliver: protocol::basic::Deliver,
                       headers: protocol::basic::BasicProperties,
                       body: Vec<u8>) {

        println!("delivery");

        let f = self.process;
        let res = f(10);

        //let s = std::str::from_utf8(&body).unwrap();
        //let json_obj: json::Object = json::decode(s).expect("json parse error");
        channel.basic_ack(deliver.delivery_tag, false);
    }
}

// FIXME: actually call ProcessFunction
fn setup_inport(participant: &Participant, port: &ParticipantPort, connection: &mut Connection) {
    println!("setup inport: {}", port.queue.to_string());

    let process_tampoline = | b: Vec<u8> | {
        let f = participant.process;
        f(10);
    };

    let consumer = PortConsumer { process: participant.process, portname: port.id.to_string() };

    // create
    let declare = connection.channel.queue_declare(port.queue.to_string(), false, true, false, false, false, Table::new());
    declare.expect("inport queue creation failed");

    // subscribe
    let q = port.queue.to_string();
    let cons = connection.channel.basic_consume(consumer, q,
                                                "".to_string(), false, false, false, false, Table::new());

    cons.expect("iport setup failed");

    println!("setup inport done: {:?}, {:?}", port.id.to_string(), port.queue.to_string());
}

fn setup_outport(participant: &Participant, port: &ParticipantPort, connection: &mut Connection) {

    let queue_declare = connection.channel.queue_declare(port.queue.to_string(), false, true, false, false, false, Table::new());
    let content_type = Some("application/json".to_string());
}

// FIXME: actually send
fn send_output(participant: &Participant) {

    let queue_name = participant.info.outports[0].queue.to_string();
//    let payload = json::encode(&info).unwrap();
//    println!("sending: {}", payload);
//    let props = protocol::basic::BasicProperties { content_type: content_type, ..Default::default() };
//    let res = channel.basic_publish("", port.queue.to_string(), true, false, props, payload.into_bytes());
}

fn start_participant(participant: &Participant) -> Connection {
    let mut session = Session::new(Options{vhost: "/", .. Default::default()}).ok().expect("Can't create session");
    let mut channel = session.open_channel(1).expect("channel");

    send_discovery(&mut channel, &participant.info);

    let mut conn = Connection { session: session, channel: channel };

    // XXX: seems like can only connect to one queue?? or rather, seems program hangs forever if channel is borked
    listen_discovery(&mut conn.channel); // TESTING

    setup_inport(&participant, &participant.info.inports[0], &mut conn);

    return conn;
}

// for debugging
fn stop_participant(participant: &Participant, connection: &mut Connection) {

    let closed = connection.channel.close(200, "Bye".to_string());
    connection.session.close(200, "Good Bye".to_string());
}

// TODO: wire up input/output to the process() function
// TODO: respect MSGFLO_BROKER envvar
// TODO: setup the msgflo hetro automated test
// TODO: nicer way to declare ports
fn main() {
    let info = ParticipantInfo {
        id: "part11".to_string(),
        role: "myrole".to_string(),
        component: "rust/First".to_string(),
        inports: vec! [ ParticipantPort { id: "in".to_string(), queue: "rustparty.IN".to_string() } ],
        outports: vec! [ ParticipantPort { id: "out".to_string(), queue: "rustparty.OUT".to_string() } ],
    };
    fn process_repeat(input: i32) -> i32 {
        println!("process_repeat: {}", input);
        return input;
    }

    let p = Participant { info: info, process: process_repeat };

    let mut c = start_participant(&p);

    create_queue_and_send(&mut c.channel, "rustparty.IN", "{ \"data\": 300 }".to_string());

    c.channel.start_consuming();
    stop_participant(&p, &mut c);
}
<|endoftext|>


<commit_before>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//

use std::io::Write;
use std::num::Wrapping;

use super::defs;
use super::{Error, Result};

/// A simple ring-buffer implementation, used by vsock connections to buffer TX (guest -> host)
/// data.  Memory for this buffer is allocated lazily, since buffering will only be needed when
/// the host can't read fast enough.
pub struct TxBuf {
    /// The actual u8 buffer - only allocated after the first push.
    data: Option<Box<[u8]>>,
    /// Ring-buffer head offset - where new data is pushed to.
    head: Wrapping<u32>,
    /// Ring-buffer tail offset - where data is flushed from.
    tail: Wrapping<u32>,
}

impl TxBuf {
    /// Total buffer size, in bytes.
    const SIZE: usize = defs::CONN_TX_BUF_SIZE as usize;

    /// Ring-buffer constructor.
    pub fn new() -> Self {
        Self {
            data: None,
            head: Wrapping(0),
            tail: Wrapping(0),
        }
    }

    /// Get the used length of this buffer - number of bytes that have been pushed in, but not
    /// yet flushed out.
    pub fn len(&self) -> usize {
        (self.head - self.tail).0 as usize
    }

    /// Push a byte slice onto the ring-buffer.
    ///
    /// Either the entire source slice will be pushed to the ring-buffer, or none of it, if
    /// there isn't enough room, in which case `Err(Error::TxBufFull)` is returned.
    pub fn push(&mut self, src: &[u8]) -> Result<()> {
        // Error out if there's no room to push the entire slice.
        if self.len() + src.len() > Self::SIZE {
            return Err(Error::TxBufFull);
        }

        let data = self
            .data
            .get_or_insert_with(|| vec![0u8; Self::SIZE].into_boxed_slice());

        // Buffer head, as an offset into the data slice.
        let head_ofs = self.head.0 as usize % Self::SIZE;

        // Pushing a slice to this buffer can take either one or two slice copies: - one copy,
        // if the slice fits between `head_ofs` and `Self::SIZE`; or - two copies, if the
        // ring-buffer head wraps around.

        // First copy length: we can only go from the head offset up to the total buffer size.
        let len = std::cmp::min(Self::SIZE - head_ofs, src.len());
        data[head_ofs..(head_ofs + len)].copy_from_slice(&src[..len]);

        // If the slice didn't fit, the buffer head will wrap around, and pushing continues
        // from the start of the buffer (`&self.data[0]`).
        if len < src.len() {
            data[..(src.len() - len)].copy_from_slice(&src[len..]);
        }

        // Either way, we've just pushed exactly `src.len()` bytes, so that's the amount by
        // which the (wrapping) buffer head needs to move forward.
        self.head += Wrapping(src.len() as u32);

        Ok(())
    }

    /// Flush the contents of the ring-buffer to a writable stream.
    ///
    /// Return the number of bytes that have been transferred out of the ring-buffer and into
    /// the writable stream.
    pub fn flush_to<W>(&mut self, sink: &mut W) -> Result<usize>
    where
        W: Write,
    {
        // Nothing to do, if this buffer holds no data.
        if self.is_empty() {
            return Ok(0);
        }

        // Buffer tail, as an offset into the buffer data slice.
        let tail_ofs = self.tail.0 as usize % Self::SIZE;

        // Flushing the buffer can take either one or two writes:
        // - one write, if the tail doesn't need to wrap around to reach the head; or
        // - two writes, if the tail would wrap around: tail to slice end, then slice end to
        //   head.

        // First write length: the lesser of tail to slice end, or tail to head.
        let len_to_write = std::cmp::min(Self::SIZE - tail_ofs, self.len());

        // It's safe to unwrap here, since we've already checked if the buffer was empty.
        let data = self.data.as_ref().unwrap();

        // Issue the first write and absorb any `WouldBlock` error (we can just try again
        // later).
        let written = sink
            .write(&data[tail_ofs..(tail_ofs + len_to_write)])
            .map_err(Error::TxBufFlush)?;

        // Move the buffer tail ahead by the amount (of bytes) we were able to flush out.
        self.tail += Wrapping(written as u32);

        // If we weren't able to flush out as much as we tried, there's no point in attempting
        // our second write.
        if written < len_to_write {
            return Ok(written);
        }

        // Attempt our second write. This will return immediately if a second write isn't
        // needed, since checking for an empty buffer is the first thing we do in this
        // function.
        Ok(written + self.flush_to(sink)?)
    }

    /// Check if the buffer holds any data that hasn't yet been flushed out.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Error as IoError;
    use std::io::Result as IoResult;
    use std::io::{ErrorKind, Write};

    struct TestSink {
        data: Vec<u8>,
        err: Option<IoError>,
        capacity: usize,
    }

    impl TestSink {
        const DEFAULT_CAPACITY: usize = 2 * TxBuf::SIZE;
        fn new() -> Self {
            Self {
                data: Vec::with_capacity(Self::DEFAULT_CAPACITY),
                err: None,
                capacity: Self::DEFAULT_CAPACITY,
            }
        }
    }

    impl Write for TestSink {
        fn write(&mut self, src: &[u8]) -> IoResult<usize> {
            if self.err.is_some() {
                return Err(self.err.take().unwrap());
            }
            let len_to_push = std::cmp::min(self.capacity - self.data.len(), src.len());
            self.data.extend_from_slice(&src[..len_to_push]);
            Ok(len_to_push)
        }
        fn flush(&mut self) -> IoResult<()> {
            Ok(())
        }
    }

    impl TestSink {
        fn clear(&mut self) {
            self.data = Vec::with_capacity(self.capacity);
            self.err = None;
        }
        fn set_err(&mut self, err: IoError) {
            self.err = Some(err);
        }
        fn set_capacity(&mut self, capacity: usize) {
            self.capacity = capacity;
            if self.data.len() > self.capacity {
                self.data.resize(self.capacity, 0);
            }
        }
    }

    #[test]
    fn test_push_nowrap() {
        let mut txbuf = TxBuf::new();
        let mut sink = TestSink::new();
        assert!(txbuf.is_empty());

        assert!(txbuf.data.is_none());
        txbuf.push(&[1, 2, 3, 4]).unwrap();
        txbuf.push(&[5, 6, 7, 8]).unwrap();
        txbuf.flush_to(&mut sink).unwrap();
        assert_eq!(sink.data, [1, 2, 3, 4, 5, 6, 7, 8]);
    }

    #[test]
    fn test_push_wrap() {
        let mut txbuf = TxBuf::new();
        let mut sink = TestSink::new();
        let mut tmp: Vec<u8> = Vec::new();

        tmp.resize(TxBuf::SIZE - 2, 0);
        txbuf.push(tmp.as_slice()).unwrap();
        txbuf.flush_to(&mut sink).unwrap();
        sink.clear();

        txbuf.push(&[1, 2, 3, 4]).unwrap();
        assert_eq!(txbuf.flush_to(&mut sink).unwrap(), 4);
        assert_eq!(sink.data, [1, 2, 3, 4]);
    }

    #[test]
    fn test_push_error() {
        let mut txbuf = TxBuf::new();
        let mut tmp = Vec::with_capacity(TxBuf::SIZE);

        tmp.resize(TxBuf::SIZE - 1, 0);
        txbuf.push(tmp.as_slice()).unwrap();
        match txbuf.push(&[1, 2]) {
            Err(Error::TxBufFull) => (),
            other => panic!("Unexpected result: {:?}", other),
        }
    }

    #[test]
    fn test_incomplete_flush() {
        let mut txbuf = TxBuf::new();
        let mut sink = TestSink::new();

        sink.set_capacity(2);
        txbuf.push(&[1, 2, 3, 4]).unwrap();
        assert_eq!(txbuf.flush_to(&mut sink).unwrap(), 2);
        assert_eq!(txbuf.len(), 2);
        assert_eq!(sink.data, [1, 2]);

        sink.set_capacity(4);
        assert_eq!(txbuf.flush_to(&mut sink).unwrap(), 2);
        assert!(txbuf.is_empty());
        assert_eq!(sink.data, [1, 2, 3, 4]);
    }

    #[test]
    fn test_flush_error() {
        const EACCESS: i32 = 13;

        let mut txbuf = TxBuf::new();
        let mut sink = TestSink::new();

        txbuf.push(&[1, 2, 3, 4]).unwrap();
        let io_err = IoError::from_raw_os_error(EACCESS);
        sink.set_err(io_err);
        match txbuf.flush_to(&mut sink) {
            Err(Error::TxBufFlush(ref err)) if err.kind() == ErrorKind::PermissionDenied => (),
            other => panic!("Unexpected result: {:?}", other),
        }
    }
}
<commit_msg>vsock: fixed TX buf flushing<commit_after>// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//

use std::io::Write;
use std::num::Wrapping;

use super::defs;
use super::{Error, Result};

/// A simple ring-buffer implementation, used by vsock connections to buffer TX (guest -> host)
/// data.  Memory for this buffer is allocated lazily, since buffering will only be needed when
/// the host can't read fast enough.
pub struct TxBuf {
    /// The actual u8 buffer - only allocated after the first push.
    data: Option<Box<[u8]>>,
    /// Ring-buffer head offset - where new data is pushed to.
    head: Wrapping<u32>,
    /// Ring-buffer tail offset - where data is flushed from.
    tail: Wrapping<u32>,
}

impl TxBuf {
    /// Total buffer size, in bytes.
    const SIZE: usize = defs::CONN_TX_BUF_SIZE as usize;

    /// Ring-buffer constructor.
    pub fn new() -> Self {
        Self {
            data: None,
            head: Wrapping(0),
            tail: Wrapping(0),
        }
    }

    /// Get the used length of this buffer - number of bytes that have been pushed in, but not
    /// yet flushed out.
    pub fn len(&self) -> usize {
        (self.head - self.tail).0 as usize
    }

    /// Push a byte slice onto the ring-buffer.
    ///
    /// Either the entire source slice will be pushed to the ring-buffer, or none of it, if
    /// there isn't enough room, in which case `Err(Error::TxBufFull)` is returned.
    pub fn push(&mut self, src: &[u8]) -> Result<()> {
        // Error out if there's no room to push the entire slice.
        if self.len() + src.len() > Self::SIZE {
            return Err(Error::TxBufFull);
        }

        let data = self
            .data
            .get_or_insert_with(|| vec![0u8; Self::SIZE].into_boxed_slice());

        // Buffer head, as an offset into the data slice.
        let head_ofs = self.head.0 as usize % Self::SIZE;

        // Pushing a slice to this buffer can take either one or two slice copies: - one copy,
        // if the slice fits between `head_ofs` and `Self::SIZE`; or - two copies, if the
        // ring-buffer head wraps around.

        // First copy length: we can only go from the head offset up to the total buffer size.
        let len = std::cmp::min(Self::SIZE - head_ofs, src.len());
        data[head_ofs..(head_ofs + len)].copy_from_slice(&src[..len]);

        // If the slice didn't fit, the buffer head will wrap around, and pushing continues
        // from the start of the buffer (`&self.data[0]`).
        if len < src.len() {
            data[..(src.len() - len)].copy_from_slice(&src[len..]);
        }

        // Either way, we've just pushed exactly `src.len()` bytes, so that's the amount by
        // which the (wrapping) buffer head needs to move forward.
        self.head += Wrapping(src.len() as u32);

        Ok(())
    }

    /// Flush the contents of the ring-buffer to a writable stream.
    ///
    /// Return the number of bytes that have been transferred out of the ring-buffer and into
    /// the writable stream.
    pub fn flush_to<W>(&mut self, sink: &mut W) -> Result<usize>
    where
        W: Write,
    {
        // Nothing to do, if this buffer holds no data.
        if self.is_empty() {
            return Ok(0);
        }

        // Buffer tail, as an offset into the buffer data slice.
        let tail_ofs = self.tail.0 as usize % Self::SIZE;

        // Flushing the buffer can take either one or two writes:
        // - one write, if the tail doesn't need to wrap around to reach the head; or
        // - two writes, if the tail would wrap around: tail to slice end, then slice end to
        //   head.

        // First write length: the lesser of tail to slice end, or tail to head.
        let len_to_write = std::cmp::min(Self::SIZE - tail_ofs, self.len());

        // It's safe to unwrap here, since we've already checked if the buffer was empty.
        let data = self.data.as_ref().unwrap();

        // Issue the first write and absorb any `WouldBlock` error (we can just try again
        // later).
        let written = sink
            .write(&data[tail_ofs..(tail_ofs + len_to_write)])
            .map_err(Error::TxBufFlush)?;

        // Move the buffer tail ahead by the amount (of bytes) we were able to flush out.
        self.tail += Wrapping(written as u32);

        // If we weren't able to flush out as much as we tried, there's no point in attempting
        // our second write.
        if written < len_to_write {
            return Ok(written);
        }

        // Attempt our second write. This will return immediately if a second write isn't
        // needed, since checking for an empty buffer is the first thing we do in this
        // function.
        //
        // Interesting corner case: if we've already written some data in the first pass,
        // and then the second write fails, we will consider the flush action a success
        // and return the number of bytes written in the first pass.
        Ok(written + self.flush_to(sink).unwrap_or(0))
    }

    /// Check if the buffer holds any data that hasn't yet been flushed out.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Error as IoError;
    use std::io::Result as IoResult;
    use std::io::{ErrorKind, Write};

    struct TestSink {
        data: Vec<u8>,
        err: Option<IoError>,
        capacity: usize,
    }

    impl TestSink {
        const DEFAULT_CAPACITY: usize = 2 * TxBuf::SIZE;
        fn new() -> Self {
            Self {
                data: Vec::with_capacity(Self::DEFAULT_CAPACITY),
                err: None,
                capacity: Self::DEFAULT_CAPACITY,
            }
        }
    }

    impl Write for TestSink {
        fn write(&mut self, src: &[u8]) -> IoResult<usize> {
            if self.err.is_some() {
                return Err(self.err.take().unwrap());
            }
            let len_to_push = std::cmp::min(self.capacity - self.data.len(), src.len());
            self.data.extend_from_slice(&src[..len_to_push]);
            Ok(len_to_push)
        }
        fn flush(&mut self) -> IoResult<()> {
            Ok(())
        }
    }

    impl TestSink {
        fn clear(&mut self) {
            self.data = Vec::with_capacity(self.capacity);
            self.err = None;
        }
        fn set_err(&mut self, err: IoError) {
            self.err = Some(err);
        }
        fn set_capacity(&mut self, capacity: usize) {
            self.capacity = capacity;
            if self.data.len() > self.capacity {
                self.data.resize(self.capacity, 0);
            }
        }
    }

    #[test]
    fn test_push_nowrap() {
        let mut txbuf = TxBuf::new();
        let mut sink = TestSink::new();
        assert!(txbuf.is_empty());

        assert!(txbuf.data.is_none());
        txbuf.push(&[1, 2, 3, 4]).unwrap();
        txbuf.push(&[5, 6, 7, 8]).unwrap();
        txbuf.flush_to(&mut sink).unwrap();
        assert_eq!(sink.data, [1, 2, 3, 4, 5, 6, 7, 8]);
    }

    #[test]
    fn test_push_wrap() {
        let mut txbuf = TxBuf::new();
        let mut sink = TestSink::new();
        let mut tmp: Vec<u8> = Vec::new();

        tmp.resize(TxBuf::SIZE - 2, 0);
        txbuf.push(tmp.as_slice()).unwrap();
        txbuf.flush_to(&mut sink).unwrap();
        sink.clear();

        txbuf.push(&[1, 2, 3, 4]).unwrap();
        assert_eq!(txbuf.flush_to(&mut sink).unwrap(), 4);
        assert_eq!(sink.data, [1, 2, 3, 4]);
    }

    #[test]
    fn test_push_error() {
        let mut txbuf = TxBuf::new();
        let mut tmp = Vec::with_capacity(TxBuf::SIZE);

        tmp.resize(TxBuf::SIZE - 1, 0);
        txbuf.push(tmp.as_slice()).unwrap();
        match txbuf.push(&[1, 2]) {
            Err(Error::TxBufFull) => (),
            other => panic!("Unexpected result: {:?}", other),
        }
    }

    #[test]
    fn test_incomplete_flush() {
        let mut txbuf = TxBuf::new();
        let mut sink = TestSink::new();

        sink.set_capacity(2);
        txbuf.push(&[1, 2, 3, 4]).unwrap();
        assert_eq!(txbuf.flush_to(&mut sink).unwrap(), 2);
        assert_eq!(txbuf.len(), 2);
        assert_eq!(sink.data, [1, 2]);

        sink.set_capacity(4);
        assert_eq!(txbuf.flush_to(&mut sink).unwrap(), 2);
        assert!(txbuf.is_empty());
        assert_eq!(sink.data, [1, 2, 3, 4]);
    }

    #[test]
    fn test_flush_error() {
        const EACCESS: i32 = 13;

        let mut txbuf = TxBuf::new();
        let mut sink = TestSink::new();

        txbuf.push(&[1, 2, 3, 4]).unwrap();
        let io_err = IoError::from_raw_os_error(EACCESS);
        sink.set_err(io_err);
        match txbuf.flush_to(&mut sink) {
            Err(Error::TxBufFlush(ref err)) if err.kind() == ErrorKind::PermissionDenied => (),
            other => panic!("Unexpected result: {:?}", other),
        }
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate notify;

use self::notify::{Watcher, RecursiveMode, DebouncedEvent};
use std::sync::mpsc::channel;
use std::time::Duration;
use std::env;
use std::fs;
use std::thread;
use std::process::{Command,Child};

/// watches the debug build, restarts server on build
pub fn watcher (matches: &getopts::Matches) {
    if !matches.opt_present("w") { return }

    let mut stratis_path = env::var("STRATIS").expect("no \'STRATIS\' path found in environment vars");
    let stratis_dest;

    if matches.opt_present("d") {
        stratis_path.push_str("\\target\\debug\\");
        stratis_dest = stratis_path.clone()+"PAN_stratis.exe";
    }
    else {
        stratis_path.push_str("\\target\\release\\");
        stratis_dest = stratis_path.clone()+"\\PAN_stratis.exe";
    }

    let (tx, rx) = channel();
    let mut w = self::notify::watcher(tx,Duration::from_secs(3)).expect("unable to create filesys watcher");

    w.watch(stratis_path.clone()+"\\stratis.exe",RecursiveMode::NonRecursive).expect("unable to watch directory");

    let mut spawn_handle: Option<Child> = None;

    for n in rx.iter() {
        let mut new_spawn_handle = None;
        println!("event: {:?}",n);

        match n {
            DebouncedEvent::Write(path) => {
                if let Some(ref mut h) = spawn_handle {
                    if let Ok(_) = h.kill() {
                        println!("process-killed\n");
                        thread::sleep(Duration::from_secs(1));

                        if let Ok(r) = fs::copy(path,&stratis_dest) {
                            println!("watcher-copy:{:?}",r);
                            new_spawn_handle = spawn(&stratis_dest);
                        }
                    }
                }
                else { //no child process alive?
                    if let Ok(r) = fs::copy(path,&stratis_dest) {
                        println!("watcher-copy:{:?}",r);
                        new_spawn_handle = spawn(&stratis_dest);
                    }
                }

                spawn_handle = new_spawn_handle;
                if let Some(ref h) = spawn_handle {
                    println!("process-spawned:{:?}\n",h.id());
                }
            },
            _ => {  },
        }
    }

}

fn spawn(path: &str) -> Option<Child> {
    let r = Command::new(path).spawn();
    match r {
        Ok(h) => {
            Some(h)
        },
        Err(e) => {
            println!("spawn-err:{:?}",e);
            None
        }
    }
}
<commit_msg>update to new module location<commit_after>extern crate getopts;
extern crate notify;

use self::notify::{Watcher, RecursiveMode, DebouncedEvent};
use std::sync::mpsc::channel;
use std::time::Duration;
use std::env;
use std::fs;
use std::thread;
use std::process::{Command,Child};

/// watches the debug build, restarts server on build
pub fn watcher (matches: &getopts::Matches) {
    if !matches.opt_present("w") { return }

    let mut stratis_path = env::var("STRATIS").expect("no \'STRATIS\' path found in environment vars");
    let stratis_dest;

    if matches.opt_present("d") {
        stratis_path.push_str("\\server\\target\\debug\\");
        stratis_dest = stratis_path.clone()+"PAN_stratis.exe";
    }
    else {
        stratis_path.push_str("\\server\\target\\release\\");
        stratis_dest = stratis_path.clone()+"\\PAN_stratis.exe";
    }

    let (tx, rx) = channel();
    let mut w = self::notify::watcher(tx,Duration::from_secs(3)).expect("unable to create filesys watcher");

    w.watch(stratis_path.clone()+"\\stratis.exe",RecursiveMode::NonRecursive).expect("unable to watch directory");

    let mut spawn_handle: Option<Child> = None;

    for n in rx.iter() {
        let mut new_spawn_handle = None;
        println!("event: {:?}",n);

        match n {
            DebouncedEvent::Write(path) => {
                if let Some(ref mut h) = spawn_handle {
                    if let Ok(_) = h.kill() {
                        println!("process-killed\n");
                        thread::sleep(Duration::from_secs(1));

                        if let Ok(r) = fs::copy(path,&stratis_dest) {
                            println!("watcher-copy:{:?}",r);
                            new_spawn_handle = spawn(&stratis_dest);
                        }
                    }
                }
                else { //no child process alive?
                    if let Ok(r) = fs::copy(path,&stratis_dest) {
                        println!("watcher-copy:{:?}",r);
                        new_spawn_handle = spawn(&stratis_dest);
                    }
                }

                spawn_handle = new_spawn_handle;
                if let Some(ref h) = spawn_handle {
                    println!("process-spawned:{:?}\n",h.id());
                }
            },
            _ => {  },
        }
    }

}

fn spawn(path: &str) -> Option<Child> {
    let r = Command::new(path).spawn();
    match r {
        Ok(h) => {
            Some(h)
        },
        Err(e) => {
            println!("spawn-err:{:?}",e);
            None
        }
    }
}
<|endoftext|>


<commit_before>use crate::io::util::lines::{lines, Lines};
use crate::io::util::read_line::{read_line, ReadLine};
use crate::io::util::read_until::{read_until, ReadUntil};
use crate::io::util::split::{split, Split};
use crate::io::AsyncBufRead;

cfg_io_util! {
    /// An extension trait which adds utility methods to [`AsyncBufRead`] types.
    ///
    /// [`AsyncBufRead`]: crate::io::AsyncBufRead
    pub trait AsyncBufReadExt: AsyncBufRead {
        /// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
        ///
        /// Equivalent to:
        ///
        /// ```ignore
        /// async fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize>;
        /// ```
        ///
        /// This function will read bytes from the underlying stream until the
        /// delimiter or EOF is found. Once found, all bytes up to, and including,
        /// the delimiter (if found) will be appended to `buf`.
        ///
        /// If successful, this function will return the total number of bytes read.
        ///
        /// If this function returns `Ok(0)`, the stream has reached EOF.
        ///
        /// # Errors
        ///
        /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
        /// will otherwise return any errors returned by [`fill_buf`].
        ///
        /// If an I/O error is encountered then all bytes read so far will be
        /// present in `buf` and its length will have been adjusted appropriately.
        ///
        /// [`fill_buf`]: AsyncBufRead::poll_fill_buf
        /// [`ErrorKind::Interrupted`]: std::io::ErrorKind::Interrupted
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
        /// this example, we use [`Cursor`] to read all the bytes in a byte slice
        /// in hyphen delimited segments:
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let mut cursor = Cursor::new(b"lorem-ipsum");
        ///     let mut buf = vec![];
        ///
        ///     // cursor is at 'l'
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 6);
        ///     assert_eq!(buf, b"lorem-");
        ///     buf.clear();
        ///
        ///     // cursor is at 'i'
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 5);
        ///     assert_eq!(buf, b"ipsum");
        ///     buf.clear();
        ///
        ///     // cursor is at EOF
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///     assert_eq!(num_bytes, 0);
        ///     assert_eq!(buf, b"");
        /// }
        /// ```
        fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
        where
            Self: Unpin,
        {
            read_until(self, byte, buf)
        }

        /// Reads all bytes until a newline (the 0xA byte) is reached, and append
        /// them to the provided buffer.
        ///
        /// Equivalent to:
        ///
        /// ```ignore
        /// async fn read_line(&mut self, buf: &mut String) -> io::Result<usize>;
        /// ```
        ///
        /// This function will read bytes from the underlying stream until the
        /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes
        /// up to, and including, the delimiter (if found) will be appended to
        /// `buf`.
        ///
        /// If successful, this function will return the total number of bytes read.
        ///
        /// If this function returns `Ok(0)`, the stream has reached EOF.
        ///
        /// # Errors
        ///
        /// This function has the same error semantics as [`read_until`] and will
        /// also return an error if the read bytes are not valid UTF-8. If an I/O
        /// error is encountered then `buf` may contain some bytes already read in
        /// the event that all data read so far was valid UTF-8.
        ///
        /// [`read_until`]: AsyncBufReadExt::read_until
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements
        /// `AsyncBufRead`. In this example, we use [`Cursor`] to read all the
        /// lines in a byte slice:
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let mut cursor = Cursor::new(b"foo\nbar");
        ///     let mut buf = String::new();
        ///
        ///     // cursor is at 'f'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 4);
        ///     assert_eq!(buf, "foo\n");
        ///     buf.clear();
        ///
        ///     // cursor is at 'b'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 3);
        ///     assert_eq!(buf, "bar");
        ///     buf.clear();
        ///
        ///     // cursor is at EOF
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 0);
        ///     assert_eq!(buf, "");
        /// }
        /// ```
        fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
        where
            Self: Unpin,
        {
            read_line(self, buf)
        }

        /// Returns a stream of the contents of this reader split on the byte
        /// `byte`.
        ///
        /// This method is the asynchronous equivalent to
        /// [`BufRead::split`](std::io::BufRead::split).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
        /// the delimiter byte at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`Vec<u8>`]: std::vec::Vec
        ///
        /// # Errors
        ///
        /// Each item of the stream has the same error semantics as
        /// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until).
        ///
        /// # Examples
        ///
        /// ```
        /// # use tokio::io::AsyncBufRead;
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> {
        /// let mut segments = my_buf_read.split(b'f');
        ///
        /// while let Some(segment) = segments.next_segment().await? {
        ///     println!("length = {}", segment.len())
        /// }
        /// # Ok(())
        /// # }
        /// ```
        fn split(self, byte: u8) -> Split<Self>
        where
            Self: Sized + Unpin,
        {
            split(self, byte)
        }

        /// Returns a stream over the lines of this reader.
        /// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
        /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`String`]: String
        ///
        /// # Errors
        ///
        /// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`].
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
        /// this example, we use [`Cursor`] to iterate over all the lines in a byte
        /// slice.
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let cursor = Cursor::new(b"lorem\nipsum\r\ndolor");
        ///
        ///     let mut lines = cursor.lines();
        ///
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("lorem")));
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("ipsum")));
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("dolor")));
        ///     assert_eq!(lines.next_line().await.unwrap(), None);
        /// }
        /// ```
        ///
        /// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
        fn lines(self) -> Lines<Self>
        where
            Self: Sized,
        {
            lines(self)
        }
    }
}

impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}
<commit_msg>io: add missing Option to doc (#3999)<commit_after>use crate::io::util::lines::{lines, Lines};
use crate::io::util::read_line::{read_line, ReadLine};
use crate::io::util::read_until::{read_until, ReadUntil};
use crate::io::util::split::{split, Split};
use crate::io::AsyncBufRead;

cfg_io_util! {
    /// An extension trait which adds utility methods to [`AsyncBufRead`] types.
    ///
    /// [`AsyncBufRead`]: crate::io::AsyncBufRead
    pub trait AsyncBufReadExt: AsyncBufRead {
        /// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
        ///
        /// Equivalent to:
        ///
        /// ```ignore
        /// async fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize>;
        /// ```
        ///
        /// This function will read bytes from the underlying stream until the
        /// delimiter or EOF is found. Once found, all bytes up to, and including,
        /// the delimiter (if found) will be appended to `buf`.
        ///
        /// If successful, this function will return the total number of bytes read.
        ///
        /// If this function returns `Ok(0)`, the stream has reached EOF.
        ///
        /// # Errors
        ///
        /// This function will ignore all instances of [`ErrorKind::Interrupted`] and
        /// will otherwise return any errors returned by [`fill_buf`].
        ///
        /// If an I/O error is encountered then all bytes read so far will be
        /// present in `buf` and its length will have been adjusted appropriately.
        ///
        /// [`fill_buf`]: AsyncBufRead::poll_fill_buf
        /// [`ErrorKind::Interrupted`]: std::io::ErrorKind::Interrupted
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
        /// this example, we use [`Cursor`] to read all the bytes in a byte slice
        /// in hyphen delimited segments:
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let mut cursor = Cursor::new(b"lorem-ipsum");
        ///     let mut buf = vec![];
        ///
        ///     // cursor is at 'l'
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 6);
        ///     assert_eq!(buf, b"lorem-");
        ///     buf.clear();
        ///
        ///     // cursor is at 'i'
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 5);
        ///     assert_eq!(buf, b"ipsum");
        ///     buf.clear();
        ///
        ///     // cursor is at EOF
        ///     let num_bytes = cursor.read_until(b'-', &mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///     assert_eq!(num_bytes, 0);
        ///     assert_eq!(buf, b"");
        /// }
        /// ```
        fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
        where
            Self: Unpin,
        {
            read_until(self, byte, buf)
        }

        /// Reads all bytes until a newline (the 0xA byte) is reached, and append
        /// them to the provided buffer.
        ///
        /// Equivalent to:
        ///
        /// ```ignore
        /// async fn read_line(&mut self, buf: &mut String) -> io::Result<usize>;
        /// ```
        ///
        /// This function will read bytes from the underlying stream until the
        /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes
        /// up to, and including, the delimiter (if found) will be appended to
        /// `buf`.
        ///
        /// If successful, this function will return the total number of bytes read.
        ///
        /// If this function returns `Ok(0)`, the stream has reached EOF.
        ///
        /// # Errors
        ///
        /// This function has the same error semantics as [`read_until`] and will
        /// also return an error if the read bytes are not valid UTF-8. If an I/O
        /// error is encountered then `buf` may contain some bytes already read in
        /// the event that all data read so far was valid UTF-8.
        ///
        /// [`read_until`]: AsyncBufReadExt::read_until
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements
        /// `AsyncBufRead`. In this example, we use [`Cursor`] to read all the
        /// lines in a byte slice:
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let mut cursor = Cursor::new(b"foo\nbar");
        ///     let mut buf = String::new();
        ///
        ///     // cursor is at 'f'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 4);
        ///     assert_eq!(buf, "foo\n");
        ///     buf.clear();
        ///
        ///     // cursor is at 'b'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 3);
        ///     assert_eq!(buf, "bar");
        ///     buf.clear();
        ///
        ///     // cursor is at EOF
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 0);
        ///     assert_eq!(buf, "");
        /// }
        /// ```
        fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
        where
            Self: Unpin,
        {
            read_line(self, buf)
        }

        /// Returns a stream of the contents of this reader split on the byte
        /// `byte`.
        ///
        /// This method is the asynchronous equivalent to
        /// [`BufRead::split`](std::io::BufRead::split).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`Option`]`<`[`Vec<u8>`]`>>`. Each vector returned will *not* have
        /// the delimiter byte at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`Option`]: core::option::Option
        /// [`Vec<u8>`]: std::vec::Vec
        ///
        /// # Errors
        ///
        /// Each item of the stream has the same error semantics as
        /// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until).
        ///
        /// # Examples
        ///
        /// ```
        /// # use tokio::io::AsyncBufRead;
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> {
        /// let mut segments = my_buf_read.split(b'f');
        ///
        /// while let Some(segment) = segments.next_segment().await? {
        ///     println!("length = {}", segment.len())
        /// }
        /// # Ok(())
        /// # }
        /// ```
        fn split(self, byte: u8) -> Split<Self>
        where
            Self: Sized + Unpin,
        {
            split(self, byte)
        }

        /// Returns a stream over the lines of this reader.
        /// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`Option`]`<`[`String`]`>>`. Each string returned will *not* have a newline
        /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`Option`]: core::option::Option
        /// [`String`]: String
        ///
        /// # Errors
        ///
        /// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`].
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
        /// this example, we use [`Cursor`] to iterate over all the lines in a byte
        /// slice.
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let cursor = Cursor::new(b"lorem\nipsum\r\ndolor");
        ///
        ///     let mut lines = cursor.lines();
        ///
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("lorem")));
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("ipsum")));
        ///     assert_eq!(lines.next_line().await.unwrap(), Some(String::from("dolor")));
        ///     assert_eq!(lines.next_line().await.unwrap(), None);
        /// }
        /// ```
        ///
        /// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
        fn lines(self) -> Lines<Self>
        where
            Self: Sized,
        {
            lines(self)
        }
    }
}

impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}
<|endoftext|>


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

use LinkerFlavor;
use target::{LinkArgs, TargetOptions, RelroLevel};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Gcc, vec![
        "-Wl,-Bstatic".to_string(),
        "-Wl,--no-dynamic-linker".to_string(),
        "-Wl,--eh-frame-hdr".to_string(),
        "-Wl,--gc-sections".to_string(),
    ]);

    TargetOptions {
        executables: true,
        target_family: None,
        linker_is_gnu: true,
        pre_link_args: args,
        position_independent_executables: true,
        relro_level: RelroLevel::Full,
        exe_allocation_crate: super::maybe_jemalloc(),
        .. Default::default()
    }
}
<commit_msg>Use the right TLS model for CloudABI.<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use LinkerFlavor;
use target::{LinkArgs, TargetOptions, RelroLevel};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Gcc, vec![
        "-Wl,-Bstatic".to_string(),
        "-Wl,--no-dynamic-linker".to_string(),
        "-Wl,--eh-frame-hdr".to_string(),
        "-Wl,--gc-sections".to_string(),
    ]);

    TargetOptions {
        executables: true,
        target_family: None,
        linker_is_gnu: true,
        pre_link_args: args,
        position_independent_executables: true,
        tls_model: "local-exec".to_string(),
        relro_level: RelroLevel::Full,
        exe_allocation_crate: super::maybe_jemalloc(),
        .. Default::default()
    }
}
<|endoftext|>


<commit_before>use crate::command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::ops;
use cargo::util::ToUrl;

pub fn cli() -> App {
    subcommand("install")
        .about("Install a Rust binary. Default location is $HOME/.cargo/bin")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
        .arg(
            opt("version", "Specify a version to install")
                .alias("vers")
                .value_name("VERSION")
                .requires("crate"),
        )
        .arg(
            opt("git", "Git URL to install the specified crate from")
                .value_name("URL")
                .conflicts_with_all(&["path", "registry"]),
        )
        .arg(
            opt("branch", "Branch to use when installing from git")
                .value_name("BRANCH")
                .requires("git"),
        )
        .arg(
            opt("tag", "Tag to use when installing from git")
                .value_name("TAG")
                .requires("git"),
        )
        .arg(
            opt("rev", "Specific commit to use when installing from git")
                .value_name("SHA")
                .requires("git"),
        )
        .arg(
            opt("path", "Filesystem path to local crate to install")
                .value_name("PATH")
                .conflicts_with_all(&["git", "registry"]),
        )
        .arg(opt(
            "list",
            "list all installed packages and their versions",
        ))
        .arg_jobs()
        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
        .arg_features()
        .arg(opt("debug", "Build in debug mode instead of release mode"))
        .arg_targets_bins_examples(
            "Install only the specified binary",
            "Install all binaries",
            "Install only the specified example",
            "Install all examples",
        )
        .arg_target_triple("Build for the target triple")
        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
        .arg(
            opt("registry", "Registry to use")
                .value_name("REGISTRY")
                .requires("crate")
                .conflicts_with_all(&["git", "path"]),
        )
        .after_help(
            "\
This command manages Cargo's local set of installed binary crates. Only packages
which have [[bin]] targets can be installed, and all binaries are installed into
the installation root's `bin` folder. The installation root is determined, in
order of precedence, by `--root`, `$CARGO_INSTALL_ROOT`, the `install.root`
configuration key, and finally the home directory (which is either
`$CARGO_HOME` if set or `$HOME/.cargo` by default).

There are multiple sources from which a crate can be installed. The default
location is crates.io but the `--git`, `--path`, and `registry` flags can
change this source. If the source contains more than one package (such as
crates.io or a git repository with multiple crates) the `<crate>` argument is
required to indicate which crate should be installed.

Crates from crates.io can optionally specify the version they wish to install
via the `--version` flags, and similarly packages from git repositories can
optionally specify the branch, tag, or revision that should be installed. If a
crate has multiple binaries, the `--bin` argument can selectively install only
one of them, and if you'd rather install examples the `--example` argument can
be used as well.

By default cargo will refuse to overwrite existing binaries. The `--force` flag
enables overwriting existing binaries. Thus you can reinstall a crate with
`cargo install --force <crate>`.

Omitting the <crate> specification entirely will install the crate in the
current directory. That is, `install` is equivalent to the more explicit
`install --path .`. This behaviour is deprecated, and no longer supported as
of the Rust 2018 edition.

If the source is crates.io or `--git` then by default the crate will be built
in a temporary target directory. To avoid this, the target directory can be
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
path. In particular, this can be useful for caching build artifacts on
continuous integration systems.",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let registry = args.registry(config)?;

    if let Some(path) = args.value_of_path("path", config) {
        config.reload_rooted_at(path)?;
    } else {
        config.reload_rooted_at(config.home().clone().into_path_unlocked())?;
    }

    let workspace = args.workspace(config).ok();
    let mut compile_opts = args.compile_options(config, CompileMode::Build, workspace.as_ref())?;

    compile_opts.build_config.release = !args.is_present("debug");

    let krates = args
        .values_of("crate")
        .unwrap_or_default()
        .collect::<Vec<_>>();

    let mut from_cwd = false;

    let source = if let Some(url) = args.value_of("git") {
        let url = url.to_url()?;
        let gitref = if let Some(branch) = args.value_of("branch") {
            GitReference::Branch(branch.to_string())
        } else if let Some(tag) = args.value_of("tag") {
            GitReference::Tag(tag.to_string())
        } else if let Some(rev) = args.value_of("rev") {
            GitReference::Rev(rev.to_string())
        } else {
            GitReference::Branch("master".to_string())
        };
        SourceId::for_git(&url, gitref)?
    } else if let Some(path) = args.value_of_path("path", config) {
        SourceId::for_path(&path)?
    } else if krates.is_empty() {
        from_cwd = true;
        SourceId::for_path(config.cwd())?
    } else if let Some(registry) = registry {
        SourceId::alt_registry(config, &registry)?
    } else {
        SourceId::crates_io(config)?
    };

    let version = args.value_of("version");
    let root = args.value_of("root");

    if args.is_present("list") {
        ops::install_list(root, config)?;
    } else {
        ops::install(
            root,
            krates,
            source,
            from_cwd,
            version,
            &compile_opts,
            args.is_present("force"),
        )?;
    }
    Ok(())
}
<commit_msg>Clarify docs of install without <crate><commit_after>use crate::command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::ops;
use cargo::util::ToUrl;

pub fn cli() -> App {
    subcommand("install")
        .about("Install a Rust binary. Default location is $HOME/.cargo/bin")
        .arg(opt("quiet", "No output printed to stdout").short("q"))
        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
        .arg(
            opt("version", "Specify a version to install")
                .alias("vers")
                .value_name("VERSION")
                .requires("crate"),
        )
        .arg(
            opt("git", "Git URL to install the specified crate from")
                .value_name("URL")
                .conflicts_with_all(&["path", "registry"]),
        )
        .arg(
            opt("branch", "Branch to use when installing from git")
                .value_name("BRANCH")
                .requires("git"),
        )
        .arg(
            opt("tag", "Tag to use when installing from git")
                .value_name("TAG")
                .requires("git"),
        )
        .arg(
            opt("rev", "Specific commit to use when installing from git")
                .value_name("SHA")
                .requires("git"),
        )
        .arg(
            opt("path", "Filesystem path to local crate to install")
                .value_name("PATH")
                .conflicts_with_all(&["git", "registry"]),
        )
        .arg(opt(
            "list",
            "list all installed packages and their versions",
        ))
        .arg_jobs()
        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
        .arg_features()
        .arg(opt("debug", "Build in debug mode instead of release mode"))
        .arg_targets_bins_examples(
            "Install only the specified binary",
            "Install all binaries",
            "Install only the specified example",
            "Install all examples",
        )
        .arg_target_triple("Build for the target triple")
        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
        .arg(
            opt("registry", "Registry to use")
                .value_name("REGISTRY")
                .requires("crate")
                .conflicts_with_all(&["git", "path"]),
        )
        .after_help(
            "\
This command manages Cargo's local set of installed binary crates. Only packages
which have [[bin]] targets can be installed, and all binaries are installed into
the installation root's `bin` folder. The installation root is determined, in
order of precedence, by `--root`, `$CARGO_INSTALL_ROOT`, the `install.root`
configuration key, and finally the home directory (which is either
`$CARGO_HOME` if set or `$HOME/.cargo` by default).

There are multiple sources from which a crate can be installed. The default
location is crates.io but the `--git`, `--path`, and `registry` flags can
change this source. If the source contains more than one package (such as
crates.io or a git repository with multiple crates) the `<crate>` argument is
required to indicate which crate should be installed.

Crates from crates.io can optionally specify the version they wish to install
via the `--version` flags, and similarly packages from git repositories can
optionally specify the branch, tag, or revision that should be installed. If a
crate has multiple binaries, the `--bin` argument can selectively install only
one of them, and if you'd rather install examples the `--example` argument can
be used as well.

By default cargo will refuse to overwrite existing binaries. The `--force` flag
enables overwriting existing binaries. Thus you can reinstall a crate with
`cargo install --force <crate>`.

Omitting the <crate> specification entirely will install the crate in the
current directory. This behaviour is deprecated, and it no longer works in the
Rust 2018 edition. Use the more explicit `install --path .` instead.

If the source is crates.io or `--git` then by default the crate will be built
in a temporary target directory. To avoid this, the target directory can be
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
path. In particular, this can be useful for caching build artifacts on
continuous integration systems.",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let registry = args.registry(config)?;

    if let Some(path) = args.value_of_path("path", config) {
        config.reload_rooted_at(path)?;
    } else {
        config.reload_rooted_at(config.home().clone().into_path_unlocked())?;
    }

    let workspace = args.workspace(config).ok();
    let mut compile_opts = args.compile_options(config, CompileMode::Build, workspace.as_ref())?;

    compile_opts.build_config.release = !args.is_present("debug");

    let krates = args
        .values_of("crate")
        .unwrap_or_default()
        .collect::<Vec<_>>();

    let mut from_cwd = false;

    let source = if let Some(url) = args.value_of("git") {
        let url = url.to_url()?;
        let gitref = if let Some(branch) = args.value_of("branch") {
            GitReference::Branch(branch.to_string())
        } else if let Some(tag) = args.value_of("tag") {
            GitReference::Tag(tag.to_string())
        } else if let Some(rev) = args.value_of("rev") {
            GitReference::Rev(rev.to_string())
        } else {
            GitReference::Branch("master".to_string())
        };
        SourceId::for_git(&url, gitref)?
    } else if let Some(path) = args.value_of_path("path", config) {
        SourceId::for_path(&path)?
    } else if krates.is_empty() {
        from_cwd = true;
        SourceId::for_path(config.cwd())?
    } else if let Some(registry) = registry {
        SourceId::alt_registry(config, &registry)?
    } else {
        SourceId::crates_io(config)?
    };

    let version = args.value_of("version");
    let root = args.value_of("root");

    if args.is_present("list") {
        ops::install_list(root, config)?;
    } else {
        ops::install(
            root,
            krates,
            source,
            from_cwd,
            version,
            &compile_opts,
            args.is_present("force"),
        )?;
    }
    Ok(())
}
<|endoftext|>