<commit_before>use itertools::{multipeek,MultiPeek};
use std::str;

#[derive(Debug, PartialEq)]
pub enum Token {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,
    Comma,
    Dot,
    Minus,
    Plus,
    Semicolon,
    Slash,
    Star,
    Bang,
    BangEqual,
    Equal,
    EqualEqual,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Identifier(String),
    StringLiteral(String),
    NumberLiteral(f64),
    // Keywords
    And,
    Class,
    Else,
    False,
    Fun,
    For,
    If,
    Nil,
    Or,
    Print,
    Return,
    Super,
    This,
    True,
    Var,
    While,

    Eof,
    // The book doesn't have tokens for comments and
    // whitespaces. Introducing them the scanner can
    // deal with them uniformly and in a more
    // functional way.
    Comment,
    Whitespace,
}

#[derive(Debug)]
pub struct TokenWithContext {
    token: Token,
    // Takes a copy. Tokens can outlive the file they came from
    lexeme: String,
    line: usize,
}

struct Scanner<'a>{
    current: usize,
    current_lexeme: String,
    line: usize,
    source: MultiPeek<str::Chars<'a>>,
}

fn is_digit(c: char) -> bool {
    c >= '0' && c <= '9'
}

fn is_alpha(c: char) -> bool {
    (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
}

fn is_alphanumeric(c: char) -> bool {
    is_digit(c) || is_alpha(c)
}

fn is_whitespace(c: char) -> bool {
    match c {
        ' ' => true,
        '\r' => true,
        '\t' => true,
        '\n' => true,
        _ => false,
    }
}

impl<'a> Scanner<'a> {
    fn initialize(source: &String) -> Scanner {
        Scanner {
            current: 0,
            current_lexeme: "".into(),
            line: 1, // 1-indexed,
            source: multipeek(source.chars()),
        }
    }

    fn is_at_end(&mut self) -> bool {
        self.source.reset_peek();
        match self.source.peek(){
            Some(_) => false,
            None => true,
        }
    }

    fn peek(&mut self) -> char() {
        self.source.reset_peek();
        //TODO: this is dubious
        match self.source.peek(){
            Some(&c) => c,
            None => '\0',
        }
    }

    fn peek_next(&mut self) -> char() {
        self.source.reset_peek();
        //TODO: this is dubious
        match self.source.peek(){
            Some(&_) => match self.source.peek(){
                Some(&c) => c,
                None => '\0',
                },
            None => '\0',
        }
    }

    fn advance(&mut self) -> char {
        self.current += 1;
        //TODO: handle None!
        let c = self.source.next().unwrap();
        self.current_lexeme.push(c);
        if c == '\n' {
            self.line += 1;
        }
        c
    }

    fn is_match(&mut self, expected: char) -> bool {
        self.source.reset_peek();
        match self.source.peek(){
            Some(&c) => {
                if c == expected {
                    let _ = self.source.next();
                    self.current += 1;
                    true
                }
                else{
                    false
                }
            }
            None => false,
        }
    }

    fn add_context(&mut self, token: Token) -> TokenWithContext {
        let result = TokenWithContext {
            token: token,
            lexeme: self.current_lexeme.clone(),
            line: self.line,
        };
        self.current_lexeme = "".into();
        result
    }

    fn string(&mut self) -> Result<Token, String> {
        let initial_line = self.line;
        while self.peek() != '"' && !self.is_at_end() {
            self.advance();
        }
        if self.is_at_end() {
            return Err(format!("Unterminated string at line {}", initial_line));
        }
        self.advance();
        let literal_length = self.current_lexeme.len() - 2;
        // Trims delimiters
        let literal = self.current_lexeme.chars().skip(1).take(literal_length).collect();
        Ok(Token::StringLiteral(literal))
    }

    fn number(&mut self) -> Token {
        while is_digit(self.peek()) {
            self.advance();
        }
        if self.peek() == '.' && is_digit(self.peek_next()) {
            self.advance(); // Consume the .
            while is_digit(self.peek()) {
                self.advance();
            }
        }
        let value = self.current_lexeme.parse::<f64>().unwrap();
        Token::NumberLiteral(value)
    }

    fn identifier(&mut self) -> Token {
        while is_alphanumeric(self.peek()) {
            self.advance();
        }
        // TODO: take a ref in the first place
        match self.current_lexeme.as_ref() {
            "and" => Token::And,
            "class" => Token::Class,
            "else" => Token::Else,
            "false" => Token::False,
            "for" => Token::For,
            "fun" => Token::Fun,
            "if" => Token::If,
            "nil" => Token::Nil,
            "or" => Token::Or,
            "print" => Token::Print,
            "return" => Token::Return,
            "super" => Token::Super,
            "this" => Token::This,
            "true" => Token::True,
            "var" => Token::Var,
            "while" => Token::While,
            identifier => Token::Identifier(identifier.into()),
        }

    }

    fn scan_next(&mut self) -> Result<TokenWithContext, String> {
        let token = match self.advance() {
            '(' => Token::LeftParen,
            ')' => Token::RightParen,
            '{' => Token::LeftBrace,
            '}' => Token::RightBrace,
            ',' => Token::Comma,
            '.' => Token::Dot,
            '-' => Token::Minus,
            '+' => Token::Plus,
            ';' => Token::Semicolon,
            '*' => Token::Star,
            '!' => {
                if self.is_match('=') {
                    Token::BangEqual
                } else {
                    Token::Bang
                }
            }
            '=' => {
                if self.is_match('=') {
                    Token::EqualEqual
                } else {
                    Token::Equal
                }
            }
            '<' => {
                if self.is_match('=') {
                    Token::LessEqual
                } else {
                    Token::Less
                }
            }
            '>' => {
                if self.is_match('=') {
                    Token::GreaterEqual
                } else {
                    Token::Greater
                }
            }
            '/' => {
                if self.is_match('/') {
                    // Comments go on till the end of the line
                    while self.peek() != '\n' && !self.is_at_end() {
                        self.advance();
                    }
                    Token::Comment
                } else {
                    Token::Slash
                }
            }
            '"' => try!(self.string()),
            c if is_whitespace(c) => Token::Whitespace,
            c if is_digit(c) => self.number(),
            c if is_alpha(c) => self.identifier(),
            c => {
                return Err(format!("Unexpected character {} at line {}, pos {}",
                                   c,
                                   self.line,
                                   self.current - 1));
            }
        };
        Ok(self.add_context(token))
    }
}

pub fn scan(source: &String) -> Result<Vec<TokenWithContext>, String> {
    let mut scanner = Scanner::initialize(source);
    let mut tokens = Vec::new();
    while !scanner.is_at_end() {
        let token_with_context = try!(scanner.scan_next());
        match token_with_context.token {
            // Ignoring tokens we don't care about
            Token::Comment => {}
            Token::Whitespace => {}
            _ => tokens.push(token_with_context),
        }
    }
    tokens.push(TokenWithContext {
        token: Token::Eof,
        lexeme: "".into(),
        line: scanner.line,
    });
    Ok(tokens)
}

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

    #[test]
    fn single_token() {
        let tokens = scan(&"+".into()).unwrap();
        assert_eq!(tokens[0].token, Token::Plus);
    }

    #[test]
    fn expression() {
        let tokens = scan(&"1+2".into()).unwrap();
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
        assert_eq!(tokens[3].token, Token::Eof);
    }

    #[test]
    fn expression_with_whitespaces() {
        let tokens = scan(&"1 + 2".into()).unwrap();
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
        assert_eq!(tokens[3].token, Token::Eof);
    }

    #[test]
    fn assignement_with_comment() {
        let tokens = scan(&"var a = 1.0; // A comment".into()).unwrap();
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
        assert_eq!(tokens[5].token, Token::Eof);
    }

    #[test]
    fn multiline_statements() {
        let tokens = scan(&r#"var a = 1.0;
                              var b = "Hello";"#
                .into())
            .unwrap();
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
        assert_eq!(tokens[5].token, Token::Var);
        assert_eq!(tokens[6].token, Token::Identifier("b".into()));
        assert_eq!(tokens[7].token, Token::Equal);
        assert_eq!(tokens[8].token, Token::StringLiteral("Hello".into()));
        assert_eq!(tokens[9].token, Token::Semicolon);
        assert_eq!(tokens[10].token, Token::Eof);
        assert_eq!(tokens[1].line, 1);
        assert_eq!(tokens[9].line, 2);
    }
}
<commit_msg>Inlined double lookahead<commit_after>use itertools::{multipeek,MultiPeek};
use std::str;

#[derive(Debug, PartialEq)]
pub enum Token {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,
    Comma,
    Dot,
    Minus,
    Plus,
    Semicolon,
    Slash,
    Star,
    Bang,
    BangEqual,
    Equal,
    EqualEqual,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Identifier(String),
    StringLiteral(String),
    NumberLiteral(f64),
    // Keywords
    And,
    Class,
    Else,
    False,
    Fun,
    For,
    If,
    Nil,
    Or,
    Print,
    Return,
    Super,
    This,
    True,
    Var,
    While,

    Eof,
    // The book doesn't have tokens for comments and
    // whitespaces. Introducing them the scanner can
    // deal with them uniformly and in a more
    // functional way.
    Comment,
    Whitespace,
}

#[derive(Debug)]
pub struct TokenWithContext {
    token: Token,
    // Takes a copy. Tokens can outlive the file they came from
    lexeme: String,
    line: usize,
}

struct Scanner<'a>{
    current: usize,
    current_lexeme: String,
    line: usize,
    source: MultiPeek<str::Chars<'a>>,
}

fn is_digit(c: char) -> bool {
    c >= '0' && c <= '9'
}

fn is_alpha(c: char) -> bool {
    (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
}

fn is_alphanumeric(c: char) -> bool {
    is_digit(c) || is_alpha(c)
}

fn is_whitespace(c: char) -> bool {
    match c {
        ' ' => true,
        '\r' => true,
        '\t' => true,
        '\n' => true,
        _ => false,
    }
}

impl<'a> Scanner<'a> {
    fn initialize(source: &String) -> Scanner {
        Scanner {
            current: 0,
            current_lexeme: "".into(),
            line: 1, // 1-indexed,
            source: multipeek(source.chars()),
        }
    }

    fn is_at_end(&mut self) -> bool {
        self.source.reset_peek();
        match self.source.peek(){
            Some(_) => false,
            None => true,
        }
    }

    fn peek(&mut self) -> char() {
        self.source.reset_peek();
        //TODO: this is dubious
        match self.source.peek(){
            Some(&c) => c,
            None => '\0',
        }
    }

    fn advance(&mut self) -> char {
        self.current += 1;
        //TODO: handle None!
        let c = self.source.next().unwrap();
        self.current_lexeme.push(c);
        if c == '\n' {
            self.line += 1;
        }
        c
    }

    fn is_match(&mut self, expected: char) -> bool {
        self.source.reset_peek();
        match self.source.peek(){
            Some(&c) => {
                if c == expected {
                    let _ = self.source.next();
                    self.current += 1;
                    true
                }
                else{
                    false
                }
            }
            None => false,
        }
    }

    fn add_context(&mut self, token: Token) -> TokenWithContext {
        let result = TokenWithContext {
            token: token,
            lexeme: self.current_lexeme.clone(),
            line: self.line,
        };
        self.current_lexeme = "".into();
        result
    }

    fn string(&mut self) -> Result<Token, String> {
        let initial_line = self.line;
        while self.peek() != '"' && !self.is_at_end() {
            self.advance();
        }
        if self.is_at_end() {
            return Err(format!("Unterminated string at line {}", initial_line));
        }
        self.advance();
        let literal_length = self.current_lexeme.len() - 2;
        // Trims delimiters
        let literal = self.current_lexeme.chars().skip(1).take(literal_length).collect();
        Ok(Token::StringLiteral(literal))
    }

    fn number(&mut self) -> Token {
        while is_digit(self.peek()) {
            self.advance();
        }
        // Here we do double lookahead
        self.source.reset_peek();
        match self.source.peek(){
            Some(&p1) =>{
                match self.source.peek() {
                    Some(&p2) => if p1 == '.' && is_digit(p2){
                        self.advance(); // Consume the .
                        while is_digit(self.peek()) {
                            self.advance();
                        }
                    },
                    None => (),
                }
            }
            None => (),
        }
        let value = self.current_lexeme.parse::<f64>().unwrap();
        Token::NumberLiteral(value)
    }

    fn identifier(&mut self) -> Token {
        while is_alphanumeric(self.peek()) {
            self.advance();
        }
        // TODO: take a ref in the first place
        match self.current_lexeme.as_ref() {
            "and" => Token::And,
            "class" => Token::Class,
            "else" => Token::Else,
            "false" => Token::False,
            "for" => Token::For,
            "fun" => Token::Fun,
            "if" => Token::If,
            "nil" => Token::Nil,
            "or" => Token::Or,
            "print" => Token::Print,
            "return" => Token::Return,
            "super" => Token::Super,
            "this" => Token::This,
            "true" => Token::True,
            "var" => Token::Var,
            "while" => Token::While,
            identifier => Token::Identifier(identifier.into()),
        }

    }

    fn scan_next(&mut self) -> Result<TokenWithContext, String> {
        let token = match self.advance() {
            '(' => Token::LeftParen,
            ')' => Token::RightParen,
            '{' => Token::LeftBrace,
            '}' => Token::RightBrace,
            ',' => Token::Comma,
            '.' => Token::Dot,
            '-' => Token::Minus,
            '+' => Token::Plus,
            ';' => Token::Semicolon,
            '*' => Token::Star,
            '!' => {
                if self.is_match('=') {
                    Token::BangEqual
                } else {
                    Token::Bang
                }
            }
            '=' => {
                if self.is_match('=') {
                    Token::EqualEqual
                } else {
                    Token::Equal
                }
            }
            '<' => {
                if self.is_match('=') {
                    Token::LessEqual
                } else {
                    Token::Less
                }
            }
            '>' => {
                if self.is_match('=') {
                    Token::GreaterEqual
                } else {
                    Token::Greater
                }
            }
            '/' => {
                if self.is_match('/') {
                    // Comments go on till the end of the line
                    while self.peek() != '\n' && !self.is_at_end() {
                        self.advance();
                    }
                    Token::Comment
                } else {
                    Token::Slash
                }
            }
            '"' => try!(self.string()),
            c if is_whitespace(c) => Token::Whitespace,
            c if is_digit(c) => self.number(),
            c if is_alpha(c) => self.identifier(),
            c => {
                return Err(format!("Unexpected character {} at line {}, pos {}",
                                   c,
                                   self.line,
                                   self.current - 1));
            }
        };
        Ok(self.add_context(token))
    }
}

pub fn scan(source: &String) -> Result<Vec<TokenWithContext>, String> {
    let mut scanner = Scanner::initialize(source);
    let mut tokens = Vec::new();
    while !scanner.is_at_end() {
        let token_with_context = try!(scanner.scan_next());
        match token_with_context.token {
            // Ignoring tokens we don't care about
            Token::Comment => {}
            Token::Whitespace => {}
            _ => tokens.push(token_with_context),
        }
    }
    tokens.push(TokenWithContext {
        token: Token::Eof,
        lexeme: "".into(),
        line: scanner.line,
    });
    Ok(tokens)
}

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

    #[test]
    fn single_token() {
        let tokens = scan(&"+".into()).unwrap();
        assert_eq!(tokens[0].token, Token::Plus);
    }

    #[test]
    fn expression() {
        let tokens = scan(&"1+2".into()).unwrap();
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
        assert_eq!(tokens[3].token, Token::Eof);
    }

    #[test]
    fn expression_with_whitespaces() {
        let tokens = scan(&"1 + 2".into()).unwrap();
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
        assert_eq!(tokens[3].token, Token::Eof);
    }

    #[test]
    fn assignement_with_comment() {
        let tokens = scan(&"var a = 1.0; // A comment".into()).unwrap();
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
        assert_eq!(tokens[5].token, Token::Eof);
    }

    #[test]
    fn multiline_statements() {
        let tokens = scan(&r#"var a = 1.0;
                              var b = "Hello";"#
                .into())
            .unwrap();
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
        assert_eq!(tokens[5].token, Token::Var);
        assert_eq!(tokens[6].token, Token::Identifier("b".into()));
        assert_eq!(tokens[7].token, Token::Equal);
        assert_eq!(tokens[8].token, Token::StringLiteral("Hello".into()));
        assert_eq!(tokens[9].token, Token::Semicolon);
        assert_eq!(tokens[10].token, Token::Eof);
        assert_eq!(tokens[1].line, 1);
        assert_eq!(tokens[9].line, 2);
    }
}
<|endoftext|>


<commit_before>use glib::types::{StaticType, Type};
use glib::translate::*;
use ffi;

pub struct SecretValue {
    ptr: *mut ffi::SecretValue
}

impl SecretValue{

    /// Create a SecretValue for the secret data passed in.
    /// This method will *NOT* create the actual secret in the backing Secret Service. (see SecretService.store() for that)
    /// The secret data is copied into non-pageable 'secure' memory.
    pub fn new(secret: &str) -> Self {
        let content_type = "text/plain";
        unsafe {
            let ptr = ffi::secret_value_new(secret.to_glib_none().0, -1, content_type.to_glib_none().0);
            SecretValue::from_glib_full(ptr)
        }
    }

    /// Transfer ownership of a raw SecretValue pointer to rust.
    pub fn from_glib_full(ptr: *mut ffi::SecretValue) -> Self {
        assert!(!ptr.is_null());
        //debug_assert!(types::instance_of::<T>(ptr as *const _));
        SecretValue {
            ptr: ptr
        }
    }

    pub fn to_glib_none(&self) -> *mut ffi::SecretValue {
        self.ptr
    }

    /// Get the secret data in the SecretValue.
    /// For now, this method only supports String values.
    /// Returns None, if the content type is npt text/plain
    pub fn get(&self) -> Option<String> {
        if self.get_content_type() == "text/plain" {
            unsafe{
                let secret = ffi::secret_value_get_text(self.to_glib_none());
                Some(from_glib_none(secret))
            }
        } else {
            None
        }
    }

    /// Get the content type of the secret value, such as `text/plain`.
    pub fn get_content_type(&self) -> String {
        unsafe {
            let ptr = ffi::secret_value_get_content_type(self.to_glib_none());
            from_glib_none(ptr)
        }
    }
}

/*
impl Clone<T> for SecretValue<T> {
    fn clone(&self) -> SecretValue<T>{

    }
}*/

impl StaticType for SecretValue {
    fn static_type() -> Type{
        unsafe { from_glib(ffi::secret_value_get_type()) }
    }
}

impl Clone for SecretValue {
    fn clone(&self) -> Self {
        unsafe {
            let ptr = ffi::secret_value_ref(self.ptr);
            SecretValue::from_glib_full(ptr)
        }
    }
}

impl Drop for SecretValue {
    fn drop(&mut self){
        unsafe { ffi::secret_value_unref(self.ptr as *mut _) }
    }
}
<commit_msg>Remove old comment<commit_after>use glib::types::{StaticType, Type};
use glib::translate::*;
use ffi;

pub struct SecretValue {
    ptr: *mut ffi::SecretValue
}

impl SecretValue{

    /// Create a SecretValue for the secret data passed in.
    /// This method will *NOT* create the actual secret in the backing Secret Service. (see SecretService.store() for that)
    /// The secret data is copied into non-pageable 'secure' memory.
    pub fn new(secret: &str) -> Self {
        let content_type = "text/plain";
        unsafe {
            let ptr = ffi::secret_value_new(secret.to_glib_none().0, -1, content_type.to_glib_none().0);
            SecretValue::from_glib_full(ptr)
        }
    }

    /// Transfer ownership of a raw SecretValue pointer to rust.
    pub fn from_glib_full(ptr: *mut ffi::SecretValue) -> Self {
        assert!(!ptr.is_null());
        //debug_assert!(types::instance_of::<T>(ptr as *const _));
        SecretValue {
            ptr: ptr
        }
    }

    pub fn to_glib_none(&self) -> *mut ffi::SecretValue {
        self.ptr
    }

    /// Get the secret data in the SecretValue.
    /// For now, this method only supports String values.
    /// Returns None, if the content type is npt text/plain
    pub fn get(&self) -> Option<String> {
        if self.get_content_type() == "text/plain" {
            unsafe{
                let secret = ffi::secret_value_get_text(self.to_glib_none());
                Some(from_glib_none(secret))
            }
        } else {
            None
        }
    }

    /// Get the content type of the secret value, such as `text/plain`.
    pub fn get_content_type(&self) -> String {
        unsafe {
            let ptr = ffi::secret_value_get_content_type(self.to_glib_none());
            from_glib_none(ptr)
        }
    }
}

impl StaticType for SecretValue {
    fn static_type() -> Type{
        unsafe { from_glib(ffi::secret_value_get_type()) }
    }
}

impl Clone for SecretValue {
    fn clone(&self) -> Self {
        unsafe {
            let ptr = ffi::secret_value_ref(self.ptr);
            SecretValue::from_glib_full(ptr)
        }
    }
}

impl Drop for SecretValue {
    fn drop(&mut self){
        unsafe { ffi::secret_value_unref(self.ptr as *mut _) }
    }
}
<|endoftext|>


<commit_before>//! Low-level push primitives

use std::sync::{RwLock, Weak};
use std::collections::RingBuf;

pub trait Subject<L> {
    fn listen(&mut self, listener: Weak<RwLock<L>>);
}

pub trait Listener<A>: Send + Sync {
    fn accept(&mut self, a: A);
}

impl<A, L: Listener<A> + ?Sized> Listener<A> for Box<L> {
    fn accept(&mut self, a: A) { self.accept(a); }
}

pub struct Source<L> {
    listeners: Vec<Weak<RwLock<L>>>,
}

unsafe impl<L: Send> Send for Source<L> {}
unsafe impl<L: Sync> Sync for Source<L> {}

impl<L> Source<L> {
    pub fn new() -> Source<L> {
        Source { listeners: Vec::new() }
    }
}

impl<L> Subject<L> for Source<L> {
    fn listen(&mut self, listener: Weak<RwLock<L>>) {
        self.listeners.push(listener);
    }
}

impl<L: Send + Sync> Source<L> {
    pub fn send<A: Clone>(&mut self, a: A)
        where L: Listener<A>
    {
        let mut idx_to_remove = vec!();
        for (k, listener) in self.listeners.iter().enumerate() {
            match listener.upgrade() {
                Some(l) => l.write().unwrap().accept(a.clone()),
                None => idx_to_remove.push(k),
            }
        }
        for k in idx_to_remove.into_iter() {
            self.listeners.remove(k);
        }
    }
}

pub struct Mapper<A, B, F: Fn(A) -> B, L> {
    func: F,
    subject: Source<L>,
}

impl<A, B, F: Fn(A) -> B, L> Mapper<A, B, F, L> {
    pub fn new(func: F) -> Mapper<A, B, F, L> {
        Mapper { func: func, subject: Source::new() }
    }
}

impl<A, B, F, L> Subject<L> for Mapper<A, B, F, L> {
    fn listen(&mut self, listener: Weak<RwLock<L>>) {
        self.subject.listen(listener);
    }
}

impl<A, B, F, L> Listener<A> for Mapper<A, B, F, L>
    where L: Listener<B> + Send + Sync,
          F: Fn(A) -> B + Send + Sync,
          B: Clone,
{
    fn accept(&mut self, a: A) {
        self.subject.send((self.func)(a));
    }
}

pub struct Receiver<A> {
    buffer: RingBuf<A>,
}

impl<A> Receiver<A> {
    pub fn new() -> Receiver<A> {
        Receiver { buffer: RingBuf::new() }
    }
}

impl<A: Send + Sync> Listener<A> for Receiver<A> {
    fn accept(&mut self, a: A) {
        self.buffer.push_back(a);
    }
}

impl<A> Iterator for Receiver<A> {
    type Item = A;
    fn next(&mut self) -> Option<A> {
        self.buffer.pop_front()
    }
}

#[cfg(test)]
mod test {
    use std::sync::{Arc, RwLock};
    use super::*;

    #[test]
    fn src_recv() {
        let mut src = Source::new();
        let recv = Arc::new(RwLock::new(Receiver::new()));
        src.listen(recv.downgrade());
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(3));
    }

    #[test]
    fn map() {
        let mut src = Source::new();
        let map = Arc::new(RwLock::new(Mapper::new(|x: i32| x + 3)));
        src.listen(map.downgrade());
        let recv = Arc::new(RwLock::new(Receiver::new()));
        map.write().unwrap().listen(recv.downgrade());
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(6));
    }

}
<commit_msg>Reinvent the listener dispatch<commit_after>//! Low-level push primitives

use std::sync::{Arc, RwLock, Weak};
use std::collections::RingBuf;

pub enum ListenerError {
    Disappeared,
    Poisoned,
}

pub trait Listener<A>: Send + Sync {
    fn accept(&mut self, a: A) -> Result<(), ListenerError>;
}

pub struct ListenerWrapper<L> {
    weak: Weak<RwLock<L>>
}

impl<L> ListenerWrapper<L> {
    pub fn boxed<A>(strong: &Arc<RwLock<L>>) -> Box<Listener<A> + 'static>
        where L: Listener<A>, A: Send + Sync,
    {
        Box::new(ListenerWrapper { weak: strong.downgrade() })
    }
}

impl<A, L> Listener<A> for ListenerWrapper<L>
    where L: Listener<A> + Send + Sync, A: Send + Sync
{
    fn accept(&mut self, a: A) -> Result<(), ListenerError> {
        match self.weak.upgrade() {
            Some(listener) => match listener.write() {
                Ok(mut listener) => listener.accept(a),
                Err(_) => Err(ListenerError::Poisoned),
            },
            None => Err(ListenerError::Disappeared),
        }
    }
}

pub trait WrapListener<L> {
    fn wrap<A>(&self) -> Box<Listener<A> + 'static>
        where L: Listener<A>, A: Send + Sync;
}

impl<L> WrapListener<L> for Arc<RwLock<L>> {
    fn wrap<A>(&self) -> Box<Listener<A> + 'static>
        where L: Listener<A>, A: Send + Sync
    {
        ListenerWrapper::boxed(self)
    }
}

pub trait Subject<A>: Send + Sync {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>);
}

pub struct Source<A> {
    listeners: Vec<Box<Listener<A> + 'static>>,
}

impl<A> Source<A> {
    pub fn new() -> Source<A> {
        Source { listeners: Vec::new() }
    }
}

impl<A: Send + Sync + Clone> Source<A> {
    pub fn send(&mut self, a: A) {
        let mut idx_to_remove = vec!();
        for (k, listener) in self.listeners.iter_mut().enumerate() {
            if listener.accept(a.clone()).is_err() {
                idx_to_remove.push(k);
            }
        }
        for k in idx_to_remove.into_iter() {
            self.listeners.remove(k);
        }
    }
}

impl<A: Send + Sync> Subject<A> for Source<A> {
    fn listen(&mut self, listener: Box<Listener<A> + 'static>) {
        self.listeners.push(listener);
    }
}

pub struct Mapper<A, B, F: Fn(A) -> B> {
    func: F,
    subject: Source<B>,
}

impl<A, B, F: Fn(A) -> B> Mapper<A, B, F> {
    pub fn new(func: F) -> Mapper<A, B, F> {
        Mapper { func: func, subject: Source::new() }
    }
}

impl<A, B, F> Subject<B> for Mapper<A, B, F>
    where A: Send + Sync + Clone,
          B: Send + Sync + Clone,
          F: Fn(A) -> B + Send + Sync,
{
    fn listen(&mut self, listener: Box<Listener<B> + 'static>) {
        self.subject.listen(listener);
    }
}

impl<A, B, F> Listener<A> for Mapper<A, B, F>
    where B: Send + Sync + Clone,
          F: Fn(A) -> B + Send + Sync,
{
    fn accept(&mut self, a: A) -> Result<(), ListenerError> {
        self.subject.send((self.func)(a));
        Ok(())
    }
}

pub struct Receiver<A> {
    buffer: RingBuf<A>,
}

impl<A> Receiver<A> {
    pub fn new() -> Receiver<A> {
        Receiver { buffer: RingBuf::new() }
    }
}

impl<A> Iterator for Receiver<A> {
    type Item = A;
    fn next(&mut self) -> Option<A> {
        self.buffer.pop_front()
    }
}

impl<A: Send + Sync> Subject<()> for Receiver<A> {
    fn listen(&mut self, _: Box<Listener<()> + 'static>) {}
}

impl<A: Send + Sync> Listener<A> for Receiver<A> {
    fn accept(&mut self, a: A) -> Result<(), ListenerError> {
        self.buffer.push_back(a);
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use std::sync::{Arc, RwLock};
    use super::*;

    #[test]
    fn src_recv() {
        let mut src = Source::new();
        let recv = Arc::new(RwLock::new(Receiver::new()));
        src.listen(recv.wrap());
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(3));
    }

    #[test]
    fn map() {
        let mut src = Source::new();
        let map = Arc::new(RwLock::new(Mapper::new(|x: i32| x + 3)));
        src.listen(map.wrap());
        let recv = Arc::new(RwLock::new(Receiver::new()));
        map.write().unwrap().listen(recv.wrap());
        src.send(3);
        assert_eq!(recv.write().unwrap().next(), Some(6));
    }

    #[test]
    fn fork() {
        let mut src = Source::new();
        let map = Arc::new(RwLock::new(Mapper::new(|x: i32| x + 3)));
        src.listen(map.wrap());
        let r1 = Arc::new(RwLock::new(Receiver::new()));
        map.write().unwrap().listen(r1.wrap());
        let r2 = Arc::new(RwLock::new(Receiver::new()));
        src.listen(r2.wrap());
        src.send(4);
        assert_eq!(r1.write().unwrap().next(), Some(7));
        assert_eq!(r2.write().unwrap().next(), Some(4));
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::convert::TryFrom;
use std::ffi::{OsStr, OsString};
use std::iter;
use std::path::{Path, PathBuf};

#[cfg(unix)]
use std::os::unix::ffi::{OsStrExt, OsStringExt};
#[cfg(windows)]
use std::os::windows::ffi::{OsStrExt, OsStringExt};

use rustc::ty::layout::LayoutOf;

use crate::*;

/// Represent how path separator conversion should be done.
enum Pathconversion {
    HostToTarget,
    TargetToHost,
}

/// Perform path separator conversion if needed.
fn convert_path_separator<'a>(
    os_str: Cow<'a, OsStr>,
    target_os: &str,
    direction: Pathconversion,
) -> Cow<'a, OsStr> {
    #[cfg(windows)]
    return if target_os == "windows" {
        // Windows-on-Windows, all fine.
        os_str
    } else {
        // Unix target, Windows host.
        let (from, to) = match direction {
            Pathconversion::HostToTarget => ('\\', '/'),
            Pathconversion::TargetToHost => ('/', '\\'),
        };
        let converted = os_str
            .encode_wide()
            .map(|wchar| if wchar == from as u16 { to as u16 } else { wchar })
            .collect::<Vec<_>>();
        Cow::Owned(OsString::from_wide(&converted))
    };
    #[cfg(unix)]
    return if target_os == "windows" {
        // Windows target, Unix host.
        let (from, to) = match direction {
            Pathconversion::HostToTarget => ('/', '\\'),
            Pathconversion::TargetToHost => ('\\', '/'),
        };
        let converted = os_str
            .as_bytes()
            .iter()
            .map(|&wchar| if wchar == from as u8 { to as u8 } else { wchar })
            .collect::<Vec<_>>();
        Cow::Owned(OsString::from_vec(converted))
    } else {
        // Unix-on-Unix, all is fine.
        os_str
    };
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
    /// the Unix APIs usually handle.
    fn read_os_str_from_c_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, &'a OsStr>
    where
        'tcx: 'a,
        'mir: 'a,
    {
        #[cfg(unix)]
        fn bytes_to_os_str<'tcx, 'a>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
            Ok(OsStr::from_bytes(bytes))
        }
        #[cfg(not(unix))]
        fn bytes_to_os_str<'tcx, 'a>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
            let s = std::str::from_utf8(bytes)
                .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", bytes))?;
            Ok(OsStr::new(s))
        }

        let this = self.eval_context_ref();
        let bytes = this.memory.read_c_str(scalar)?;
        bytes_to_os_str(bytes)
    }

    /// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
    /// which is what the Windows APIs usually handle.
    fn read_os_str_from_wide_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString>
    where
        'tcx: 'a,
        'mir: 'a,
    {
        #[cfg(windows)]
        pub fn u16vec_to_osstring<'tcx, 'a>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsString> {
            Ok(OsString::from_wide(&u16_vec[..]))
        }
        #[cfg(not(windows))]
        pub fn u16vec_to_osstring<'tcx, 'a>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsString> {
            let s = String::from_utf16(&u16_vec[..])
                .map_err(|_| err_unsup_format!("{:?} is not a valid utf-16 string", u16_vec))?;
            Ok(s.into())
        }

        let u16_vec = self.eval_context_ref().memory.read_wide_str(scalar)?;
        u16vec_to_osstring(u16_vec)
    }

    /// Helper function to write an OsStr as a null-terminated sequence of bytes, which is what
    /// the Unix APIs usually handle. This function returns `Ok((false, length))` without trying
    /// to write if `size` is not large enough to fit the contents of `os_string` plus a null
    /// terminator. It returns `Ok((true, length))` if the writing process was successful. The
    /// string length returned does not include the null terminator.
    fn write_os_str_to_c_str(
        &mut self,
        os_str: &OsStr,
        scalar: Scalar<Tag>,
        size: u64,
    ) -> InterpResult<'tcx, (bool, u64)> {
        #[cfg(unix)]
        fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
            Ok(os_str.as_bytes())
        }
        #[cfg(not(unix))]
        fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
            // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
            // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
            // valid.
            os_str
                .to_str()
                .map(|s| s.as_bytes())
                .ok_or_else(|| err_unsup_format!("{:?} is not a valid utf-8 string", os_str).into())
        }

        let bytes = os_str_to_bytes(os_str)?;
        // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null
        // terminator to memory using the `ptr` pointer would cause an out-of-bounds access.
        let string_length = u64::try_from(bytes.len()).unwrap();
        if size <= string_length {
            return Ok((false, string_length));
        }
        self.eval_context_mut()
            .memory
            .write_bytes(scalar, bytes.iter().copied().chain(iter::once(0u8)))?;
        Ok((true, string_length))
    }

    /// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what
    /// the Windows APIs usually handle. This function returns `Ok((false, length))` without trying
    /// to write if `size` is not large enough to fit the contents of `os_string` plus a null
    /// terminator. It returns `Ok((true, length))` if the writing process was successful. The
    /// string length returned does not include the null terminator.
    fn write_os_str_to_wide_str(
        &mut self,
        os_str: &OsStr,
        scalar: Scalar<Tag>,
        size: u64,
    ) -> InterpResult<'tcx, (bool, u64)> {
        #[cfg(windows)]
        fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {
            Ok(os_str.encode_wide().collect())
        }
        #[cfg(not(windows))]
        fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {
            // On non-Windows platforms the best we can do to transform Vec<u16> from/to OS strings is to do the
            // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
            // valid.
            os_str
                .to_str()
                .map(|s| s.encode_utf16().collect())
                .ok_or_else(|| err_unsup_format!("{:?} is not a valid utf-8 string", os_str).into())
        }

        let u16_vec = os_str_to_u16vec(os_str)?;
        // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required
        // 0x0000 terminator to memory would cause an out-of-bounds access.
        let string_length = u64::try_from(u16_vec.len()).unwrap();
        if size <= string_length {
            return Ok((false, string_length));
        }

        // Store the UTF-16 string.
        self.eval_context_mut()
            .memory
            .write_u16s(scalar, u16_vec.into_iter().chain(iter::once(0x0000)))?;
        Ok((true, string_length))
    }

    /// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of bytes.
    fn alloc_os_str_as_c_str(
        &mut self,
        os_str: &OsStr,
        memkind: MemoryKind<MiriMemoryKind>,
    ) -> Pointer<Tag> {
        let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator.
        let this = self.eval_context_mut();

        let arg_type = this.tcx.mk_array(this.tcx.types.u8, size);
        let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind);
        assert!(self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap().0);
        arg_place.ptr.assert_ptr()
    }

    /// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of `u16`.
    fn alloc_os_str_as_wide_str(
        &mut self,
        os_str: &OsStr,
        memkind: MemoryKind<MiriMemoryKind>,
    ) -> Pointer<Tag> {
        let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator.
        let this = self.eval_context_mut();

        let arg_type = this.tcx.mk_array(this.tcx.types.u16, size);
        let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind);
        assert!(self.write_os_str_to_wide_str(os_str, arg_place.ptr, size).unwrap().0);
        arg_place.ptr.assert_ptr()
    }

    /// Read a null-terminated sequence of bytes, and perform path separator conversion if needed.
    fn read_path_from_c_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, Cow<'a, Path>>
    where
        'tcx: 'a,
        'mir: 'a,
    {
        let this = self.eval_context_ref();
        let os_str = this.read_os_str_from_c_str(scalar)?;

        Ok(match convert_path_separator(Cow::Borrowed(os_str), &this.tcx.sess.target.target.target_os, Pathconversion::TargetToHost) {
            Cow::Borrowed(x) => Cow::Borrowed(Path::new(x)),
            Cow::Owned(y) => Cow::Owned(PathBuf::from(y)),
        })
    }

    /// Read a null-terminated sequence of `u16`s, and perform path separator conversion if needed.
    fn read_path_from_wide_str(&self, scalar: Scalar<Tag>) -> InterpResult<'tcx, PathBuf> {
        let this = self.eval_context_ref();
        let os_str = this.read_os_str_from_wide_str(scalar)?;

        Ok(PathBuf::from(&convert_path_separator(Cow::Borrowed(&os_str), &this.tcx.sess.target.target.target_os, Pathconversion::TargetToHost)))
    }

    /// Write a Path to the machine memory (as a null-terminated sequence of bytes),
    /// adjusting path separators if needed.
    fn write_path_to_c_str(
        &mut self,
        path: &Path,
        scalar: Scalar<Tag>,
        size: u64,
    ) -> InterpResult<'tcx, (bool, u64)> {
        let this = self.eval_context_mut();
        let os_str = convert_path_separator(Cow::Borrowed(path.as_os_str()), &this.tcx.sess.target.target.target_os, Pathconversion::HostToTarget);
        this.write_os_str_to_c_str(&os_str, scalar, size)
    }

    /// Write a Path to the machine memory (as a null-terminated sequence of `u16`s),
    /// adjusting path separators if needed.
    fn write_path_to_wide_str(
        &mut self,
        path: &Path,
        scalar: Scalar<Tag>,
        size: u64,
    ) -> InterpResult<'tcx, (bool, u64)> {
        let this = self.eval_context_mut();
        let os_str = convert_path_separator(Cow::Borrowed(path.as_os_str()), &this.tcx.sess.target.target.target_os, Pathconversion::HostToTarget);
        this.write_os_str_to_wide_str(&os_str, scalar, size)
    }
}
<commit_msg>fix fn read_path_from_wide_str<commit_after>use std::borrow::Cow;
use std::convert::TryFrom;
use std::ffi::{OsStr, OsString};
use std::iter;
use std::path::{Path, PathBuf};

#[cfg(unix)]
use std::os::unix::ffi::{OsStrExt, OsStringExt};
#[cfg(windows)]
use std::os::windows::ffi::{OsStrExt, OsStringExt};

use rustc::ty::layout::LayoutOf;

use crate::*;

/// Represent how path separator conversion should be done.
enum Pathconversion {
    HostToTarget,
    TargetToHost,
}

/// Perform path separator conversion if needed.
fn convert_path_separator<'a>(
    os_str: Cow<'a, OsStr>,
    target_os: &str,
    direction: Pathconversion,
) -> Cow<'a, OsStr> {
    #[cfg(windows)]
    return if target_os == "windows" {
        // Windows-on-Windows, all fine.
        os_str
    } else {
        // Unix target, Windows host.
        let (from, to) = match direction {
            Pathconversion::HostToTarget => ('\\', '/'),
            Pathconversion::TargetToHost => ('/', '\\'),
        };
        let converted = os_str
            .encode_wide()
            .map(|wchar| if wchar == from as u16 { to as u16 } else { wchar })
            .collect::<Vec<_>>();
        Cow::Owned(OsString::from_wide(&converted))
    };
    #[cfg(unix)]
    return if target_os == "windows" {
        // Windows target, Unix host.
        let (from, to) = match direction {
            Pathconversion::HostToTarget => ('/', '\\'),
            Pathconversion::TargetToHost => ('\\', '/'),
        };
        let converted = os_str
            .as_bytes()
            .iter()
            .map(|&wchar| if wchar == from as u8 { to as u8 } else { wchar })
            .collect::<Vec<_>>();
        Cow::Owned(OsString::from_vec(converted))
    } else {
        // Unix-on-Unix, all is fine.
        os_str
    };
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
    /// the Unix APIs usually handle.
    fn read_os_str_from_c_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, &'a OsStr>
    where
        'tcx: 'a,
        'mir: 'a,
    {
        #[cfg(unix)]
        fn bytes_to_os_str<'tcx, 'a>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
            Ok(OsStr::from_bytes(bytes))
        }
        #[cfg(not(unix))]
        fn bytes_to_os_str<'tcx, 'a>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
            let s = std::str::from_utf8(bytes)
                .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", bytes))?;
            Ok(OsStr::new(s))
        }

        let this = self.eval_context_ref();
        let bytes = this.memory.read_c_str(scalar)?;
        bytes_to_os_str(bytes)
    }

    /// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
    /// which is what the Windows APIs usually handle.
    fn read_os_str_from_wide_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString>
    where
        'tcx: 'a,
        'mir: 'a,
    {
        #[cfg(windows)]
        pub fn u16vec_to_osstring<'tcx, 'a>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsString> {
            Ok(OsString::from_wide(&u16_vec[..]))
        }
        #[cfg(not(windows))]
        pub fn u16vec_to_osstring<'tcx, 'a>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsString> {
            let s = String::from_utf16(&u16_vec[..])
                .map_err(|_| err_unsup_format!("{:?} is not a valid utf-16 string", u16_vec))?;
            Ok(s.into())
        }

        let u16_vec = self.eval_context_ref().memory.read_wide_str(scalar)?;
        u16vec_to_osstring(u16_vec)
    }

    /// Helper function to write an OsStr as a null-terminated sequence of bytes, which is what
    /// the Unix APIs usually handle. This function returns `Ok((false, length))` without trying
    /// to write if `size` is not large enough to fit the contents of `os_string` plus a null
    /// terminator. It returns `Ok((true, length))` if the writing process was successful. The
    /// string length returned does not include the null terminator.
    fn write_os_str_to_c_str(
        &mut self,
        os_str: &OsStr,
        scalar: Scalar<Tag>,
        size: u64,
    ) -> InterpResult<'tcx, (bool, u64)> {
        #[cfg(unix)]
        fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
            Ok(os_str.as_bytes())
        }
        #[cfg(not(unix))]
        fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
            // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
            // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
            // valid.
            os_str
                .to_str()
                .map(|s| s.as_bytes())
                .ok_or_else(|| err_unsup_format!("{:?} is not a valid utf-8 string", os_str).into())
        }

        let bytes = os_str_to_bytes(os_str)?;
        // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null
        // terminator to memory using the `ptr` pointer would cause an out-of-bounds access.
        let string_length = u64::try_from(bytes.len()).unwrap();
        if size <= string_length {
            return Ok((false, string_length));
        }
        self.eval_context_mut()
            .memory
            .write_bytes(scalar, bytes.iter().copied().chain(iter::once(0u8)))?;
        Ok((true, string_length))
    }

    /// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what
    /// the Windows APIs usually handle. This function returns `Ok((false, length))` without trying
    /// to write if `size` is not large enough to fit the contents of `os_string` plus a null
    /// terminator. It returns `Ok((true, length))` if the writing process was successful. The
    /// string length returned does not include the null terminator.
    fn write_os_str_to_wide_str(
        &mut self,
        os_str: &OsStr,
        scalar: Scalar<Tag>,
        size: u64,
    ) -> InterpResult<'tcx, (bool, u64)> {
        #[cfg(windows)]
        fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {
            Ok(os_str.encode_wide().collect())
        }
        #[cfg(not(windows))]
        fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {
            // On non-Windows platforms the best we can do to transform Vec<u16> from/to OS strings is to do the
            // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
            // valid.
            os_str
                .to_str()
                .map(|s| s.encode_utf16().collect())
                .ok_or_else(|| err_unsup_format!("{:?} is not a valid utf-8 string", os_str).into())
        }

        let u16_vec = os_str_to_u16vec(os_str)?;
        // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required
        // 0x0000 terminator to memory would cause an out-of-bounds access.
        let string_length = u64::try_from(u16_vec.len()).unwrap();
        if size <= string_length {
            return Ok((false, string_length));
        }

        // Store the UTF-16 string.
        self.eval_context_mut()
            .memory
            .write_u16s(scalar, u16_vec.into_iter().chain(iter::once(0x0000)))?;
        Ok((true, string_length))
    }

    /// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of bytes.
    fn alloc_os_str_as_c_str(
        &mut self,
        os_str: &OsStr,
        memkind: MemoryKind<MiriMemoryKind>,
    ) -> Pointer<Tag> {
        let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator.
        let this = self.eval_context_mut();

        let arg_type = this.tcx.mk_array(this.tcx.types.u8, size);
        let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind);
        assert!(self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap().0);
        arg_place.ptr.assert_ptr()
    }

    /// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of `u16`.
    fn alloc_os_str_as_wide_str(
        &mut self,
        os_str: &OsStr,
        memkind: MemoryKind<MiriMemoryKind>,
    ) -> Pointer<Tag> {
        let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator.
        let this = self.eval_context_mut();

        let arg_type = this.tcx.mk_array(this.tcx.types.u16, size);
        let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind);
        assert!(self.write_os_str_to_wide_str(os_str, arg_place.ptr, size).unwrap().0);
        arg_place.ptr.assert_ptr()
    }

    /// Read a null-terminated sequence of bytes, and perform path separator conversion if needed.
    fn read_path_from_c_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, Cow<'a, Path>>
    where
        'tcx: 'a,
        'mir: 'a,
    {
        let this = self.eval_context_ref();
        let os_str = this.read_os_str_from_c_str(scalar)?;

        Ok(match convert_path_separator(Cow::Borrowed(os_str), &this.tcx.sess.target.target.target_os, Pathconversion::TargetToHost) {
            Cow::Borrowed(x) => Cow::Borrowed(Path::new(x)),
            Cow::Owned(y) => Cow::Owned(PathBuf::from(y)),
        })
    }

    /// Read a null-terminated sequence of `u16`s, and perform path separator conversion if needed.
    fn read_path_from_wide_str(&self, scalar: Scalar<Tag>) -> InterpResult<'tcx, PathBuf> {
        let this = self.eval_context_ref();
        let os_str = this.read_os_str_from_wide_str(scalar)?;

        Ok(convert_path_separator(Cow::Owned(os_str), &this.tcx.sess.target.target.target_os, Pathconversion::TargetToHost).into_owned().into())
    }

    /// Write a Path to the machine memory (as a null-terminated sequence of bytes),
    /// adjusting path separators if needed.
    fn write_path_to_c_str(
        &mut self,
        path: &Path,
        scalar: Scalar<Tag>,
        size: u64,
    ) -> InterpResult<'tcx, (bool, u64)> {
        let this = self.eval_context_mut();
        let os_str = convert_path_separator(Cow::Borrowed(path.as_os_str()), &this.tcx.sess.target.target.target_os, Pathconversion::HostToTarget);
        this.write_os_str_to_c_str(&os_str, scalar, size)
    }

    /// Write a Path to the machine memory (as a null-terminated sequence of `u16`s),
    /// adjusting path separators if needed.
    fn write_path_to_wide_str(
        &mut self,
        path: &Path,
        scalar: Scalar<Tag>,
        size: u64,
    ) -> InterpResult<'tcx, (bool, u64)> {
        let this = self.eval_context_mut();
        let os_str = convert_path_separator(Cow::Borrowed(path.as_os_str()), &this.tcx.sess.target.target.target_os, Pathconversion::HostToTarget);
        this.write_os_str_to_wide_str(&os_str, scalar, size)
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use chrono::{Duration, NaiveDate};
use gtfs::parse::*;

/// Transit trait defines methods for iterating over components of a Transit
/// system
pub trait Transit<'a, E: Error> {
    type AgencyIterator: Iterator<Item=Result<Agency, E>>;

    fn agencies(&'a self) -> Self::AgencyIterator;
}

/// Agency
#[derive(Debug, Deserialize)]
pub struct Agency {
    pub agency_id: Option<String>,
    pub agency_name: String,
    pub agency_url: String,
    pub agency_timezone: String,
    pub agency_lang: Option<String>,
    pub agency_phone: Option<String>,
    pub agency_fare_url: Option<String>,
    pub agency_email: Option<String>,
}

/// Location Type
#[derive(Debug, PartialEq)]
pub enum LocationType {
    Stop,
    Station,
}

fn default_locationtype() -> LocationType {
    LocationType::Stop
}

/// Wheelchair Boarding
#[derive(Debug, PartialEq)]
pub enum WheelchairBoarding {
    NoInformation,
    SomeAccessibility,
    NoAccessibility,
}

fn default_wheelchairboarding() -> WheelchairBoarding {
    WheelchairBoarding::NoInformation
}

/// Stop
#[derive(Debug, Deserialize, PartialEq)]
pub struct Stop {
    pub stop_id: String,
    pub stop_code: Option<String>,
    pub stop_name: String,
    pub stop_desc: Option<String>,
    pub stop_lat: f64,
    pub stop_lon: f64,
    pub zone_id: Option<String>,
    pub stop_url: Option<String>,
    #[serde(default = "default_locationtype", deserialize_with = "deserialize_locationtype")]
    pub location_type: LocationType,
    pub parent_station: Option<String>,
    pub stop_timezone: Option<String>,
    #[serde(default = "default_wheelchairboarding", deserialize_with = "deserialize_wheelchairboarding")]
    pub wheelchair_boarding: WheelchairBoarding,
}

/// RouteType
#[derive(Debug)]
pub enum RouteType {
    LightRail,
    Subway,
    Rail,
    Bus,
    Ferry,
    CableCar,
    Gondola,
    Funicular,
}

/// Route
#[derive(Debug, Deserialize)]
pub struct Route {
    pub route_id: String,
    pub agency_id: Option<String>,
    pub route_short_name: String,
    pub route_long_name: String,
    pub route_desc: Option<String>,
    #[serde(deserialize_with ="deserialize_routetype")]
    pub route_type: RouteType,
    pub route_url: Option<String>,
    pub route_color: Option<String>,
    pub route_text_color: Option<String>,
}

/// Wheelchair Accessible
// TODO: merge with WheelchairBoarding
#[derive(Debug)]
pub enum WheelchairAccessible {
    NoInformation,
    SomeAccessibility,
    NoAccessibility,
}

fn default_wheelchairaccessible() -> WheelchairAccessible {
    WheelchairAccessible::NoInformation
}

/// Bikes Allowed
#[derive(Debug)]
pub enum BikesAllowed {
    NoInformation,
    SomeBikes,
    NoBikes,
}

fn default_bikesallowed() -> BikesAllowed {
    BikesAllowed::NoInformation
}

/// Trip
#[derive(Debug, Deserialize)]
pub struct Trip {
    pub route_id: String,
    pub service_id: String,
    pub trip_id: String,
    pub trip_headsign: Option<String>,
    pub trip_short_name: Option<String>,
    pub direction_id: Option<String>,
    pub block_id: Option<String>,
    pub shape_id: Option<String>,
    #[serde(default = "default_wheelchairaccessible", deserialize_with = "deserialize_wheelchairaccessible")]
    pub wheelchair_accessible: WheelchairAccessible,
    #[serde(default = "default_bikesallowed", deserialize_with = "deserialize_bikesallowed")]
    pub bikes_allowed: BikesAllowed,
}

/// PickupType for `StopTime`
#[derive(Debug, PartialEq)]
pub enum PickupType {
    RegularlyScheduled,
    NoPickupAvailable,
    MustPhoneAgency,
    MustCoordinateWithDriver,
}

fn default_pickuptype() -> PickupType {
    PickupType::RegularlyScheduled
}

/// DropoffType for `StopTime`
#[derive(Debug, PartialEq)]
pub enum DropoffType {
    RegularlyScheduled,
    NoDropoffAvailable,
    MustPhoneAgency,
    MustCoordinateWithDriver,
}

fn default_dropofftype() -> DropoffType {
    DropoffType::RegularlyScheduled
}

/// Timepoint for `StopTime`
#[derive(Debug, PartialEq)]
pub enum Timepoint {
    Approximate,
    Exact,
}

fn default_timepoint() -> Timepoint {
    Timepoint::Exact
}

/// StopTime
#[derive(Debug, Deserialize, PartialEq)]
pub struct StopTime {
    pub trip_id: String,
    #[serde(deserialize_with = "deserialize_timeoffset")]
    pub arrival_time: TimeOffset,
    #[serde(deserialize_with = "deserialize_timeoffset")]
    pub departure_time: TimeOffset,
    pub stop_id: String,
    pub stop_sequence: u64,
    pub stop_headsign: Option<String>,
    #[serde(default = "default_pickuptype", deserialize_with = "deserialize_pickuptype")]
    pub pickup_type: PickupType,
    #[serde(default = "default_dropofftype", deserialize_with = "deserialize_dropofftype")]
    pub dropoff_type: DropoffType,
    pub shape_dist_traveled: Option<f64>,
    #[serde(default = "default_timepoint", deserialize_with = "deserialize_timepoint")]
    pub timepoint: Timepoint,
}

/// Calendar
#[derive(Debug, Deserialize)]
pub struct Calendar {
    pub service_id: String,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub monday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub tuesday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub wednesday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub thursday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub friday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub saturday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub sunday: bool,
    #[serde(deserialize_with = "deserialize_calendardate")]
    pub start_date: NaiveDate,
    #[serde(deserialize_with = "deserialize_calendardate")]
    pub end_date: NaiveDate,
}

/// ExceptionType for `CalendarDate`
#[derive(Debug)]
pub enum ExceptionType {
    ServiceAdded,
    ServiceRemoved,
}

/// CalendarDate
#[derive(Debug, Deserialize)]
pub struct CalendarDate {
    pub service_id: String,
    #[serde(deserialize_with = "deserialize_calendardate")]
    pub date: NaiveDate,
    #[serde(deserialize_with = "deserialize_exceptiontype")]
    pub exception_type: ExceptionType
}

/// PaymentMethod for `FareAttribute`
#[derive(Debug)]
pub enum PaymentMethod {
    PaidOnboard,
    PaidBefore,
}

/// Tranfers for `FareAttribute`
#[derive(Debug)]
pub enum Transfers {
    None,
    TransferOnce,
    TransferTwice,
    Unlimited,
}

/// FareAttribute
#[derive(Debug, Deserialize)]
pub struct FareAttribute {
    pub fare_id: String,
    pub price: f64,
    pub currency_type: String,
    #[serde(deserialize_with = "deserialize_paymentmethod")]
    pub payment_method: PaymentMethod,
    #[serde(deserialize_with = "deserialize_transfers")]
    pub transfers: Transfers,
    #[serde(deserialize_with = "deserialize_transferduration")]
    pub transfer_duration: Option<Duration>,
}

/// FareRule
/// origin, destination, and contains reference a zone_id from stops
#[derive(Debug, Deserialize)]
pub struct FareRule {
    pub fare_id: String,
    pub route_id: Option<String>,
    pub origin_id: Option<String>,
    pub destination_id: Option<String>,
    pub contains_id: Option<String>,
}

/// Shape
#[derive(Debug, Deserialize)]
pub struct Shape {
    pub shape_id: String,
    pub shape_pt_lat: f64,
    pub shape_pt_lon: f64,
    pub shape_pt_sequence: u64,
    pub shape_dist_traveled: Option<f64>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct TimeOffset {
    pub hours: u32,
    pub minutes: u32,
    pub seconds: u32,
}

impl TimeOffset {
    pub fn from_hms(hours: u32, minutes: u32, seconds: u32) -> TimeOffset {
        TimeOffset {
            hours: hours,
            minutes: minutes,
            seconds: seconds,
        }
    }

    pub fn duration(&self) -> Duration {
        Duration::hours(self.hours as i64)
            + Duration::minutes(self.minutes as i64)
            + Duration::seconds(self.seconds as i64)
    }
}

/// exact_times for Frequency
#[derive(Debug)]
pub enum FrequencyAccuracy {
    Approximate,
    Exact
}

fn default_frequencyaccuracy() -> FrequencyAccuracy {
    return FrequencyAccuracy::Approximate;
}

/// Frequency
#[derive(Debug, Deserialize)]
pub struct Frequency {
    pub trip_id: String,
    #[serde(deserialize_with = "deserialize_timeoffset")]
    pub start_time: TimeOffset,
    #[serde(deserialize_with = "deserialize_timeoffset")]
    pub end_time: TimeOffset,
    pub headway_secs: u64,
    #[serde(default = "default_frequencyaccuracy", deserialize_with = "deserialize_frequencyaccuracy")]
    pub exact_times: FrequencyAccuracy,
}

#[derive(Debug)]
pub enum TransferType {
    Recommended,
    Timed,
    MinimumTime,
    NotPossible
}

/// Transfer
#[derive(Debug, Deserialize)]
pub struct Transfer {
    pub from_stop_id: String,
    pub to_stop_id: String,
    #[serde(deserialize_with = "deserialize_transfertype")]
    pub transfer_type: TransferType,
    #[serde(deserialize_with = "deserialize_transferduration")]
    pub min_transfer_time: Option<Duration>
}

/// Feed Info
#[derive(Debug, Deserialize)]
pub struct FeedInfo {
    pub feed_publisher_name: String,
    pub feed_publisher_url: String,
    pub feed_lang: String,
    #[serde(default = "default_feed_date", deserialize_with = "deserialize_option_calendardate")]
    pub feed_start_date: Option<NaiveDate>,
    #[serde(default = "default_feed_date", deserialize_with = "deserialize_option_calendardate")]
    pub feed_end_date: Option<NaiveDate>,
    pub feed_version: Option<String>
}

fn default_feed_date() -> Option<NaiveDate> {
    None
}
<commit_msg>Remove experimental trait<commit_after>use chrono::{Duration, NaiveDate};
use gtfs::parse::*;

/// Agency
#[derive(Debug, Deserialize)]
pub struct Agency {
    pub agency_id: Option<String>,
    pub agency_name: String,
    pub agency_url: String,
    pub agency_timezone: String,
    pub agency_lang: Option<String>,
    pub agency_phone: Option<String>,
    pub agency_fare_url: Option<String>,
    pub agency_email: Option<String>,
}

/// Location Type
#[derive(Debug, PartialEq)]
pub enum LocationType {
    Stop,
    Station,
}

fn default_locationtype() -> LocationType {
    LocationType::Stop
}

/// Wheelchair Boarding
#[derive(Debug, PartialEq)]
pub enum WheelchairBoarding {
    NoInformation,
    SomeAccessibility,
    NoAccessibility,
}

fn default_wheelchairboarding() -> WheelchairBoarding {
    WheelchairBoarding::NoInformation
}

/// Stop
#[derive(Debug, Deserialize, PartialEq)]
pub struct Stop {
    pub stop_id: String,
    pub stop_code: Option<String>,
    pub stop_name: String,
    pub stop_desc: Option<String>,
    pub stop_lat: f64,
    pub stop_lon: f64,
    pub zone_id: Option<String>,
    pub stop_url: Option<String>,
    #[serde(default = "default_locationtype", deserialize_with = "deserialize_locationtype")]
    pub location_type: LocationType,
    pub parent_station: Option<String>,
    pub stop_timezone: Option<String>,
    #[serde(default = "default_wheelchairboarding", deserialize_with = "deserialize_wheelchairboarding")]
    pub wheelchair_boarding: WheelchairBoarding,
}

/// RouteType
#[derive(Debug)]
pub enum RouteType {
    LightRail,
    Subway,
    Rail,
    Bus,
    Ferry,
    CableCar,
    Gondola,
    Funicular,
}

/// Route
#[derive(Debug, Deserialize)]
pub struct Route {
    pub route_id: String,
    pub agency_id: Option<String>,
    pub route_short_name: String,
    pub route_long_name: String,
    pub route_desc: Option<String>,
    #[serde(deserialize_with ="deserialize_routetype")]
    pub route_type: RouteType,
    pub route_url: Option<String>,
    pub route_color: Option<String>,
    pub route_text_color: Option<String>,
}

/// Wheelchair Accessible
// TODO: merge with WheelchairBoarding
#[derive(Debug)]
pub enum WheelchairAccessible {
    NoInformation,
    SomeAccessibility,
    NoAccessibility,
}

fn default_wheelchairaccessible() -> WheelchairAccessible {
    WheelchairAccessible::NoInformation
}

/// Bikes Allowed
#[derive(Debug)]
pub enum BikesAllowed {
    NoInformation,
    SomeBikes,
    NoBikes,
}

fn default_bikesallowed() -> BikesAllowed {
    BikesAllowed::NoInformation
}

/// Trip
#[derive(Debug, Deserialize)]
pub struct Trip {
    pub route_id: String,
    pub service_id: String,
    pub trip_id: String,
    pub trip_headsign: Option<String>,
    pub trip_short_name: Option<String>,
    pub direction_id: Option<String>,
    pub block_id: Option<String>,
    pub shape_id: Option<String>,
    #[serde(default = "default_wheelchairaccessible", deserialize_with = "deserialize_wheelchairaccessible")]
    pub wheelchair_accessible: WheelchairAccessible,
    #[serde(default = "default_bikesallowed", deserialize_with = "deserialize_bikesallowed")]
    pub bikes_allowed: BikesAllowed,
}

/// PickupType for `StopTime`
#[derive(Debug, PartialEq)]
pub enum PickupType {
    RegularlyScheduled,
    NoPickupAvailable,
    MustPhoneAgency,
    MustCoordinateWithDriver,
}

fn default_pickuptype() -> PickupType {
    PickupType::RegularlyScheduled
}

/// DropoffType for `StopTime`
#[derive(Debug, PartialEq)]
pub enum DropoffType {
    RegularlyScheduled,
    NoDropoffAvailable,
    MustPhoneAgency,
    MustCoordinateWithDriver,
}

fn default_dropofftype() -> DropoffType {
    DropoffType::RegularlyScheduled
}

/// Timepoint for `StopTime`
#[derive(Debug, PartialEq)]
pub enum Timepoint {
    Approximate,
    Exact,
}

fn default_timepoint() -> Timepoint {
    Timepoint::Exact
}

/// StopTime
#[derive(Debug, Deserialize, PartialEq)]
pub struct StopTime {
    pub trip_id: String,
    #[serde(deserialize_with = "deserialize_timeoffset")]
    pub arrival_time: TimeOffset,
    #[serde(deserialize_with = "deserialize_timeoffset")]
    pub departure_time: TimeOffset,
    pub stop_id: String,
    pub stop_sequence: u64,
    pub stop_headsign: Option<String>,
    #[serde(default = "default_pickuptype", deserialize_with = "deserialize_pickuptype")]
    pub pickup_type: PickupType,
    #[serde(default = "default_dropofftype", deserialize_with = "deserialize_dropofftype")]
    pub dropoff_type: DropoffType,
    pub shape_dist_traveled: Option<f64>,
    #[serde(default = "default_timepoint", deserialize_with = "deserialize_timepoint")]
    pub timepoint: Timepoint,
}

/// Calendar
#[derive(Debug, Deserialize)]
pub struct Calendar {
    pub service_id: String,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub monday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub tuesday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub wednesday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub thursday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub friday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub saturday: bool,
    #[serde(deserialize_with = "deserialize_dow_field")]
    pub sunday: bool,
    #[serde(deserialize_with = "deserialize_calendardate")]
    pub start_date: NaiveDate,
    #[serde(deserialize_with = "deserialize_calendardate")]
    pub end_date: NaiveDate,
}

/// ExceptionType for `CalendarDate`
#[derive(Debug)]
pub enum ExceptionType {
    ServiceAdded,
    ServiceRemoved,
}

/// CalendarDate
#[derive(Debug, Deserialize)]
pub struct CalendarDate {
    pub service_id: String,
    #[serde(deserialize_with = "deserialize_calendardate")]
    pub date: NaiveDate,
    #[serde(deserialize_with = "deserialize_exceptiontype")]
    pub exception_type: ExceptionType
}

/// PaymentMethod for `FareAttribute`
#[derive(Debug)]
pub enum PaymentMethod {
    PaidOnboard,
    PaidBefore,
}

/// Tranfers for `FareAttribute`
#[derive(Debug)]
pub enum Transfers {
    None,
    TransferOnce,
    TransferTwice,
    Unlimited,
}

/// FareAttribute
#[derive(Debug, Deserialize)]
pub struct FareAttribute {
    pub fare_id: String,
    pub price: f64,
    pub currency_type: String,
    #[serde(deserialize_with = "deserialize_paymentmethod")]
    pub payment_method: PaymentMethod,
    #[serde(deserialize_with = "deserialize_transfers")]
    pub transfers: Transfers,
    #[serde(deserialize_with = "deserialize_transferduration")]
    pub transfer_duration: Option<Duration>,
}

/// FareRule
/// origin, destination, and contains reference a zone_id from stops
#[derive(Debug, Deserialize)]
pub struct FareRule {
    pub fare_id: String,
    pub route_id: Option<String>,
    pub origin_id: Option<String>,
    pub destination_id: Option<String>,
    pub contains_id: Option<String>,
}

/// Shape
#[derive(Debug, Deserialize)]
pub struct Shape {
    pub shape_id: String,
    pub shape_pt_lat: f64,
    pub shape_pt_lon: f64,
    pub shape_pt_sequence: u64,
    pub shape_dist_traveled: Option<f64>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct TimeOffset {
    pub hours: u32,
    pub minutes: u32,
    pub seconds: u32,
}

impl TimeOffset {
    pub fn from_hms(hours: u32, minutes: u32, seconds: u32) -> TimeOffset {
        TimeOffset {
            hours: hours,
            minutes: minutes,
            seconds: seconds,
        }
    }

    pub fn duration(&self) -> Duration {
        Duration::hours(self.hours as i64)
            + Duration::minutes(self.minutes as i64)
            + Duration::seconds(self.seconds as i64)
    }
}

/// exact_times for Frequency
#[derive(Debug)]
pub enum FrequencyAccuracy {
    Approximate,
    Exact
}

fn default_frequencyaccuracy() -> FrequencyAccuracy {
    return FrequencyAccuracy::Approximate;
}

/// Frequency
#[derive(Debug, Deserialize)]
pub struct Frequency {
    pub trip_id: String,
    #[serde(deserialize_with = "deserialize_timeoffset")]
    pub start_time: TimeOffset,
    #[serde(deserialize_with = "deserialize_timeoffset")]
    pub end_time: TimeOffset,
    pub headway_secs: u64,
    #[serde(default = "default_frequencyaccuracy", deserialize_with = "deserialize_frequencyaccuracy")]
    pub exact_times: FrequencyAccuracy,
}

#[derive(Debug)]
pub enum TransferType {
    Recommended,
    Timed,
    MinimumTime,
    NotPossible
}

/// Transfer
#[derive(Debug, Deserialize)]
pub struct Transfer {
    pub from_stop_id: String,
    pub to_stop_id: String,
    #[serde(deserialize_with = "deserialize_transfertype")]
    pub transfer_type: TransferType,
    #[serde(deserialize_with = "deserialize_transferduration")]
    pub min_transfer_time: Option<Duration>
}

/// Feed Info
#[derive(Debug, Deserialize)]
pub struct FeedInfo {
    pub feed_publisher_name: String,
    pub feed_publisher_url: String,
    pub feed_lang: String,
    #[serde(default = "default_feed_date", deserialize_with = "deserialize_option_calendardate")]
    pub feed_start_date: Option<NaiveDate>,
    #[serde(default = "default_feed_date", deserialize_with = "deserialize_option_calendardate")]
    pub feed_end_date: Option<NaiveDate>,
    pub feed_version: Option<String>
}

fn default_feed_date() -> Option<NaiveDate> {
    None
}
<|endoftext|>


<commit_before>//! A tremolo filter.
//!
//! Tremolo modifies the amplitude of an incoming signal (in the first channel), using
//! the output of a low frequency oscillator (in the second channel). It creates
//! a shuddering effect in the output audio.
//!
//! A intensity is set, in decibels. This controls how much gain or attenuation
//! the tremolo will apply. The LFO will then be used to oscillate this gain
//! over time.
//!
//! # Example
//!
//! To set up a tremolo, the channels must be properly configured. The following
//! will apply a tremolo to our microphone input, using a 10Hz LFO:
//!
//! ```no_run
//! use oxcable::graph::DeviceGraph;
//! use oxcable::io::audio::AudioEngine;
//! use oxcable::oscillator::*;
//! use oxcable::tremolo::Tremolo;
//!
//! let engine = AudioEngine::with_buffer_size(256).unwrap();
//! let mut graph = DeviceGraph::new();
//!
//! let lfo = graph.add_node(Oscillator::new(Sine).freq(10.0));
//! let microphone = graph.add_node(engine.default_input(1).unwrap());
//! let tremolo = graph.add_node(Tremolo::new(3.0)); // 3dB tremolo
//! let speaker = graph.add_node(engine.default_output(1).unwrap());
//!
//! graph.add_edge(microphone, 0, tremolo, 0); // first channnel is input signal
//! graph.add_edge(lfo, 0, tremolo, 1); // second channel is LFO output
//! graph.add_edge(tremolo, 0, speaker, 0);
//! ```

use num::traits::Float;
use oxcable::types::{AudioDevice, MessageReceiver, Sample, Time};

/// Defines the messages that the Tremolo supports.
#[derive(Clone, Copy, Debug)]
pub enum Message {
    /// Set the tremolo intensity, in decibels.
    SetIntensity(f32)
}
pub use self::Message::*;

/// A tremolo filter.
pub struct Tremolo {
    intensity: f32,
}

impl Tremolo {
    /// Returns a new single-channel tremolo filter.
    ///
    /// `intensity` is in decibels.
    pub fn new(intensity: f32) -> Self {
        Tremolo {
            intensity: intensity
        }
    }
}

impl MessageReceiver for Tremolo {
    type Msg = Message;
    fn handle_message(&mut self, msg: Message) {
        match msg {
            SetIntensity(intensity) => self.intensity = intensity
        }
    }
}

impl AudioDevice for Tremolo {
    fn num_inputs(&self) -> usize {
        2
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        let gain = 10.0.powf(inputs[1] * self.intensity/10.0);
        outputs[0] = gain*inputs[0];
    }
}
<commit_msg>Fixes doctest<commit_after>//! A tremolo filter.
//!
//! Tremolo modifies the amplitude of an incoming signal (in the first channel), using
//! the output of a low frequency oscillator (in the second channel). It creates
//! a shuddering effect in the output audio.
//!
//! A intensity is set, in decibels. This controls how much gain or attenuation
//! the tremolo will apply. The LFO will then be used to oscillate this gain
//! over time.
//!
//! # Example
//!
//! To set up a tremolo, the channels must be properly configured. The following
//! will apply a tremolo to our microphone input, using a 10Hz LFO:
//!
//! ```no_run
//! # extern crate oxcable;
//! # extern crate oxcable_basic_devices;
//! # fn main() {
//! use oxcable::graph::DeviceGraph;
//! use oxcable::io::audio::AudioEngine;
//! use oxcable::oscillator::*;
//!
//! use oxcable_basic_devices::tremolo::Tremolo;
//!
//! let engine = AudioEngine::with_buffer_size(256).unwrap();
//! let mut graph = DeviceGraph::new();
//!
//! let lfo = graph.add_node(Oscillator::new(Sine).freq(10.0));
//! let microphone = graph.add_node(engine.default_input(1).unwrap());
//! let tremolo = graph.add_node(Tremolo::new(3.0)); // 3dB tremolo
//! let speaker = graph.add_node(engine.default_output(1).unwrap());
//!
//! graph.add_edge(microphone, 0, tremolo, 0); // first channnel is input signal
//! graph.add_edge(lfo, 0, tremolo, 1); // second channel is LFO output
//! graph.add_edge(tremolo, 0, speaker, 0);
//! # }
//! ```

use num::traits::Float;
use oxcable::types::{AudioDevice, MessageReceiver, Sample, Time};

/// Defines the messages that the Tremolo supports.
#[derive(Clone, Copy, Debug)]
pub enum Message {
    /// Set the tremolo intensity, in decibels.
    SetIntensity(f32)
}
pub use self::Message::*;

/// A tremolo filter.
pub struct Tremolo {
    intensity: f32,
}

impl Tremolo {
    /// Returns a new single-channel tremolo filter.
    ///
    /// `intensity` is in decibels.
    pub fn new(intensity: f32) -> Self {
        Tremolo {
            intensity: intensity
        }
    }
}

impl MessageReceiver for Tremolo {
    type Msg = Message;
    fn handle_message(&mut self, msg: Message) {
        match msg {
            SetIntensity(intensity) => self.intensity = intensity
        }
    }
}

impl AudioDevice for Tremolo {
    fn num_inputs(&self) -> usize {
        2
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        let gain = 10.0.powf(inputs[1] * self.intensity/10.0);
        outputs[0] = gain*inputs[0];
    }
}
<|endoftext|>


<commit_before>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! #[macro_use]
//! extern crate enum_map;
//! #[macro_use]
//! extern crate enum_map_derive;
//!
//! use enum_map::EnumMap;
//!
//! #[derive(Debug, EnumMap)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

mod enummap_impls;
mod implementations;
mod iter;
mod serde;

pub use iter::{Iter, IterMut};

/// Internal enum mapping type
///
/// This trait is internally used by `#[derive(EnumMap)]`. Despite it being
/// a public trait, it's not intended to be public. `Internal<T>` is
/// implemented by any enum type where V is a generic type representing a
/// value. The purpose of this generic type is to allow providing a value
/// type for arrays, as Rust currently does not support higher kinded types.
/// Users aren't expected to use this trait directly, but rather to use
/// `EnumMap<K, V>` which uses this internally.
///
/// This trait is also implemented by `bool` and `u8` type. While `u8` is
/// strictly speaking not an actual enum, there are good reasons to consider
/// it like one, as array of `u8` keys is a relatively common pattern.
pub trait Internal<V>: Sized {
    #[doc(hidden)]
    type Array;
    #[doc(hidden)]
    fn slice(&Self::Array) -> &[V];
    #[doc(hidden)]
    fn slice_mut(&mut Self::Array) -> &mut [V];
    #[doc(hidden)]
    fn from_usize(usize) -> Self;
    #[doc(hidden)]
    fn to_usize(self) -> usize;
    #[doc(hidden)]
    fn from_function<F: FnMut(Self) -> V>(F) -> Self::Array;
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// Additionally, `bool` and `u8` automatically derives from `EnumMap`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
    where K::Array: Default
{
    /// Creates an enum map with default values.
    ///
    /// ```
    /// extern crate enum_map;
    /// #[macro_use]
    /// extern crate enum_map_derive;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        K::slice(&self.array).len()
    }

    /// Returns whether the enum variant set is empty.
    ///
    /// This isn't particularly useful, as there is no real reason to use
    /// enum map for enums without variants. However, it is provided for
    /// consistency with data structures providing len method (and I will
    /// admit, to avoid clippy warnings).
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate enum_map;
    /// #[macro_use]
    /// extern crate enum_map_derive;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Void {}
    ///
    /// #[derive(EnumMap)]
    /// enum SingleVariant {
    ///     Variant,
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(EnumMap::<Void, ()>::new().is_empty(), true);
    ///     assert_eq!(EnumMap::<SingleVariant, ()>::new().is_empty(), false);
    /// }
    pub fn is_empty(&self) -> bool {
        K::slice(&self.array).is_empty()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { false => 0, true => 1 };
    ///     map.swap(false, true);
    ///     assert_eq!(map[false], 1);
    ///     assert_eq!(map[true], 0);
    /// }
    /// ```
    pub fn swap(&mut self, a: K, b: K) {
        K::slice_mut(&mut self.array).swap(a.to_usize(), b.to_usize())
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        ::enum_map::EnumMap::from(|k| match k { $($t)* })
    };
}
<commit_msg>Use $crate meta-variable in enum map macro<commit_after>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! #[macro_use]
//! extern crate enum_map;
//! #[macro_use]
//! extern crate enum_map_derive;
//!
//! use enum_map::EnumMap;
//!
//! #[derive(Debug, EnumMap)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

mod enummap_impls;
mod implementations;
mod iter;
mod serde;

pub use iter::{Iter, IterMut};

/// Internal enum mapping type
///
/// This trait is internally used by `#[derive(EnumMap)]`. Despite it being
/// a public trait, it's not intended to be public. `Internal<T>` is
/// implemented by any enum type where V is a generic type representing a
/// value. The purpose of this generic type is to allow providing a value
/// type for arrays, as Rust currently does not support higher kinded types.
/// Users aren't expected to use this trait directly, but rather to use
/// `EnumMap<K, V>` which uses this internally.
///
/// This trait is also implemented by `bool` and `u8` type. While `u8` is
/// strictly speaking not an actual enum, there are good reasons to consider
/// it like one, as array of `u8` keys is a relatively common pattern.
pub trait Internal<V>: Sized {
    #[doc(hidden)]
    type Array;
    #[doc(hidden)]
    fn slice(&Self::Array) -> &[V];
    #[doc(hidden)]
    fn slice_mut(&mut Self::Array) -> &mut [V];
    #[doc(hidden)]
    fn from_usize(usize) -> Self;
    #[doc(hidden)]
    fn to_usize(self) -> usize;
    #[doc(hidden)]
    fn from_function<F: FnMut(Self) -> V>(F) -> Self::Array;
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// Additionally, `bool` and `u8` automatically derives from `EnumMap`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
    where K::Array: Default
{
    /// Creates an enum map with default values.
    ///
    /// ```
    /// extern crate enum_map;
    /// #[macro_use]
    /// extern crate enum_map_derive;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        K::slice(&self.array).len()
    }

    /// Returns whether the enum variant set is empty.
    ///
    /// This isn't particularly useful, as there is no real reason to use
    /// enum map for enums without variants. However, it is provided for
    /// consistency with data structures providing len method (and I will
    /// admit, to avoid clippy warnings).
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate enum_map;
    /// #[macro_use]
    /// extern crate enum_map_derive;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Void {}
    ///
    /// #[derive(EnumMap)]
    /// enum SingleVariant {
    ///     Variant,
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(EnumMap::<Void, ()>::new().is_empty(), true);
    ///     assert_eq!(EnumMap::<SingleVariant, ()>::new().is_empty(), false);
    /// }
    pub fn is_empty(&self) -> bool {
        K::slice(&self.array).is_empty()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { false => 0, true => 1 };
    ///     map.swap(false, true);
    ///     assert_eq!(map[false], 1);
    ///     assert_eq!(map[true], 0);
    /// }
    /// ```
    pub fn swap(&mut self, a: K, b: K) {
        K::slice_mut(&mut self.array).swap(a.to_usize(), b.to_usize())
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
/// #[macro_use]
/// extern crate enum_map_derive;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        $crate::EnumMap::from(|k| match k { $($t)* })
    };
}
<|endoftext|>