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

use applescript::{run as run_applescript};

use plist::Plist;

use tera::{Context, Tera};

use urls;

// http://stackoverflow.com/a/27590832/1558022
macro_rules! error(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
        process::exit(1);
    } }
);

/// Returns true/false if Safari is running.
pub fn is_safari_running() -> bool {
  let cmd_result = Command::new("ps")
    .arg("-eaf")
    .output()
    .expect("Unable to test if Safari is running.");
  for line in String::from_utf8(cmd_result.stdout).unwrap().lines() {
    if line.ends_with("Safari.app/Contents/MacOS/Safari") {
      return true
    }
  }
  false
}

/// Exits the program if Safari isn't running.
pub fn assert_safari_is_running() {
  if !is_safari_running() {
    error!("Safari is not running.");
  }
}

/// Return a URL from a Safari window.
///
/// Given a (window, tab) pair, this function looks up the URL of the tab.
/// Note that it doesn't do any error handling, so will throw an execution
/// error if it fails.
///
/// * `window` - Window index.  1 is frontmost.  If None, assumes the
///              frontmost window.
/// * `tab` - Tab index.  1 is leftmost.  If None, assumes the frontmost tab.
///
pub fn get_url(window: Option<i32>, tab: Option<i32>) -> String {
  // If a tab isn't specified, assume the user wants the frontmost tab.
  let command = match window {
    Some(w_idx) => {
      match tab {
        Some(t_idx) => format!("tell application \"Safari\" to get tab {} of window {}", t_idx, w_idx),
        None => format!("tell application \"Safari\" to get URL of document {}", w_idx),
      }
    },
    None => "tell application \"Safari\" to get URL of document 1".to_string(),
  };
  let output = run_applescript(&command);

  if output.status.success() {
    urls::tidy_url(output.stdout.trim())
  } else {
    if output.stderr.contains("Invalid index") {
      error!("Invalid index: no such window or tab.");
    } else {
      error!("Unexpected error from osascript: {:?}", output.stderr);
    }
  }
}

/// Return a list of URLs from Safari.
///
/// This returns a list of URLs, one for every tab in Safari.  Iteration
/// order depends on AppleScript, which I don't think is guaranteed to be
/// stable (in particular, I think it depends on which window is frontmost).
///
pub fn get_all_urls() -> Vec<String> {
  let script = include_str!("scripts/list-open-tabs.scpt");
  let output = run_applescript(&script);
  if output.status.success() {
    output.stdout.trim()
                 .split(", ")
                 .map(|url| urls::tidy_url(url))
                 .filter(|url| url != "favorites://")
                 .collect()
  } else {
    error!("Unexpected error from osascript: {:?}", output.stderr);
  }
}

/// Convert URL patterns into AppleScript conditions.
///
/// These conditions can be used in an `if` statement in AppleScript to
/// decide whether a tab should be closed.  Three patterns are supported,
/// a limited regex syntax:
///
///     example.com             matches anywhere in the URL
///     ^http://examples.com    matches at the start of the URL
///     example.com/$           matches at the end of the URL
///
fn parse_conditions(url_patterns: Vec<&str>) -> Vec<String> {
  url_patterns.iter().map(|p|
    if p.starts_with("^") {
      format!("starts with \"{}\"", p.replace("^", ""))
    } else if p.ends_with("$") {
      format!("ends with \"{}\"", p.replace("$", ""))
    } else {
      format!("contains \"{}\"", p)
    }
  ).collect()
}

/// Tests for parse_conditions().
#[cfg(test)]
mod tests {
  use safari::parse_conditions;

  #[test]
  fn test_parse_conditions() {
    let patterns = vec!["github.com", "^facebook.com", "twitter.com$"];
    let expected = vec!["contains \"github.com\"", "starts with \"facebook.com\"", "ends with \"twitter.com\""];
    let actual = parse_conditions(patterns);
    assert_eq!(actual, expected);
  }
}

/// Close tabs in Safari that match URL patterns.
///
/// Takes a list of URL patterns, and tries to close any matching Safari tabs.
/// Bugginess in AppleScript means this isn't always perfect, but we can
/// have a go.  In general it will fail to close tabs, rather than close
/// the wrong tabs.
///
pub fn close_tabs(url_patterns: Vec<&str>) {
  let conditions = parse_conditions(url_patterns);

  let clean_tabs_template = include_str!("scripts/clean-tabs.scpt");
  let mut context = Context::new();
  context.add("conditions", &conditions);
  let script = Tera::one_off(&clean_tabs_template, context, false).unwrap();

  // Run it twice to get around weird AppleScript bugs.
  run_applescript(&script);
  run_applescript(&script);
}

/// Get the Bookmarks.plist dict for a given title
fn read_bookmarks_plist(title: &str) -> Plist {

  // All Safari data lives at ~/Library/Safari/Bookmarks.plist
  // TODO: There's probably a more idiomatic Rust-like way to write this.
  let mut plist_path = match env::home_dir() {
    Some(v) => v,
    None => error!("Unable to get path to Bookmarks.plist?"),
  };
  plist_path.push("Library/Safari/Bookmarks.plist");

  let file = match File::open(plist_path) {
    Ok(v) => v,
    Err(e) => error!("Unable to open ~/Library/Safari/Bookmarks.plist: {:?}", e),
  };

  let plist = match Plist::read(file) {
    Ok(v) => v,
    Err(e) => error!("Unable to read ~/Library/Safari/Bookmarks.plist: {:?}", e),
  };

  let data = match plist.as_dictionary() {
    Some(v) => v,
    None => error!("Unable to parse ~/Library/Safari/Bookmarks.plist as dictionary?"),
  };

  // The structure of Bookmarks.plist is as follows:
  //
  //     <dict>
  //       <key>Children</key>
  //       <array>
  //         <dict>
  //           <key>Title</key><string>History</string>
  //           ... dict data ...
  //         </dict>
  //         <dict>
  //           <key>Title</key><string>com.apple.ReadingList</string>
  //           ... dict data ...
  //         </dict>
  //         ... other array items ...
  //       </array>
  //     </dict>
  //
  let children = match data.get("Children") {
    Some(child_key) => match child_key.as_array() {
      Some(v) => v,
      None => error!("Top-level children key in ~/Library/Safari/Bookmarks.plist isn't an array?"),
    },
    None => error!("Unable to find top-level Children key in ~/Library/Safari/Bookmarks.plist"),
  };

  let mut matching_children = children.iter().filter(|d|
    match d.as_dictionary() {
      Some(dict) => match dict.get("Title") {
        Some(title_elem) => match title_elem.as_string() {
          Some(v) => (v == title),
          None => false,
        },
        None => false,
      },
      None => false,
    }
  );

  // Check we got one, and only one result.
  let result = match matching_children.next() {
    Some(v) => v,
    None => error!("Unable to find key {} in Bookmarks.plist", title),
  };

  match matching_children.next() {
    Some(_) => error!("Got more than one result for {} in Bookmarks.plist", title),
    None => {},
  };

  result.to_owned()
}

/// Return a list of URLs from Reading List.
///
/// Iteration order depends on the order in which they're stored in
/// Bookmarks.plist, which is usually (but not guaranteed to be) newest first.
///
pub fn get_reading_list_urls() -> Vec<String> {
  let plist = read_bookmarks_plist("com.apple.ReadingList");

  // TODO: All these unwrap() calls should probably be handled better
  let children = plist
    .as_dictionary().unwrap()
    .get("Children").unwrap()
    .as_array().unwrap();

  children
    .iter()
    .map(|child|
      child
        .as_dictionary().unwrap()
        .get("URLString").unwrap()
        .as_string().unwrap()
    )
    .map(|url| urls::tidy_url(url))
    .collect()
}
<commit_msg>Oopsie fix<commit_after>use std::env;
use std::fs::File;
use std::io::Write;
use std::process;

use applescript::{run as run_applescript};

use plist::Plist;

use tera::{Context, Tera};

use urls;

// http://stackoverflow.com/a/27590832/1558022
macro_rules! error(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
        process::exit(1);
    } }
);

/// Returns true/false if Safari is running.
pub fn is_safari_running() -> bool {
  let cmd_result = process::Command::new("ps")
    .arg("-eaf")
    .output()
    .expect("Unable to test if Safari is running.");
  for line in String::from_utf8(cmd_result.stdout).unwrap().lines() {
    if line.ends_with("Safari.app/Contents/MacOS/Safari") {
      return true
    }
  }
  false
}

/// Exits the program if Safari isn't running.
pub fn assert_safari_is_running() {
  if !is_safari_running() {
    error!("Safari is not running.");
  }
}

/// Return a URL from a Safari window.
///
/// Given a (window, tab) pair, this function looks up the URL of the tab.
/// Note that it doesn't do any error handling, so will throw an execution
/// error if it fails.
///
/// * `window` - Window index.  1 is frontmost.  If None, assumes the
///              frontmost window.
/// * `tab` - Tab index.  1 is leftmost.  If None, assumes the frontmost tab.
///
pub fn get_url(window: Option<i32>, tab: Option<i32>) -> String {
  // If a tab isn't specified, assume the user wants the frontmost tab.
  let command = match window {
    Some(w_idx) => {
      match tab {
        Some(t_idx) => format!("tell application \"Safari\" to get tab {} of window {}", t_idx, w_idx),
        None => format!("tell application \"Safari\" to get URL of document {}", w_idx),
      }
    },
    None => "tell application \"Safari\" to get URL of document 1".to_string(),
  };
  let output = run_applescript(&command);

  if output.status.success() {
    urls::tidy_url(output.stdout.trim())
  } else {
    if output.stderr.contains("Invalid index") {
      error!("Invalid index: no such window or tab.");
    } else {
      error!("Unexpected error from osascript: {:?}", output.stderr);
    }
  }
}

/// Return a list of URLs from Safari.
///
/// This returns a list of URLs, one for every tab in Safari.  Iteration
/// order depends on AppleScript, which I don't think is guaranteed to be
/// stable (in particular, I think it depends on which window is frontmost).
///
pub fn get_all_urls() -> Vec<String> {
  let script = include_str!("scripts/list-open-tabs.scpt");
  let output = run_applescript(&script);
  if output.status.success() {
    output.stdout.trim()
                 .split(", ")
                 .map(|url| urls::tidy_url(url))
                 .filter(|url| url != "favorites://")
                 .collect()
  } else {
    error!("Unexpected error from osascript: {:?}", output.stderr);
  }
}

/// Convert URL patterns into AppleScript conditions.
///
/// These conditions can be used in an `if` statement in AppleScript to
/// decide whether a tab should be closed.  Three patterns are supported,
/// a limited regex syntax:
///
///     example.com             matches anywhere in the URL
///     ^http://examples.com    matches at the start of the URL
///     example.com/$           matches at the end of the URL
///
fn parse_conditions(url_patterns: Vec<&str>) -> Vec<String> {
  url_patterns.iter().map(|p|
    if p.starts_with("^") {
      format!("starts with \"{}\"", p.replace("^", ""))
    } else if p.ends_with("$") {
      format!("ends with \"{}\"", p.replace("$", ""))
    } else {
      format!("contains \"{}\"", p)
    }
  ).collect()
}

/// Tests for parse_conditions().
#[cfg(test)]
mod tests {
  use safari::parse_conditions;

  #[test]
  fn test_parse_conditions() {
    let patterns = vec!["github.com", "^facebook.com", "twitter.com$"];
    let expected = vec!["contains \"github.com\"", "starts with \"facebook.com\"", "ends with \"twitter.com\""];
    let actual = parse_conditions(patterns);
    assert_eq!(actual, expected);
  }
}

/// Close tabs in Safari that match URL patterns.
///
/// Takes a list of URL patterns, and tries to close any matching Safari tabs.
/// Bugginess in AppleScript means this isn't always perfect, but we can
/// have a go.  In general it will fail to close tabs, rather than close
/// the wrong tabs.
///
pub fn close_tabs(url_patterns: Vec<&str>) {
  let conditions = parse_conditions(url_patterns);

  let clean_tabs_template = include_str!("scripts/clean-tabs.scpt");
  let mut context = Context::new();
  context.add("conditions", &conditions);
  let script = Tera::one_off(&clean_tabs_template, context, false).unwrap();

  // Run it twice to get around weird AppleScript bugs.
  run_applescript(&script);
  run_applescript(&script);
}

/// Get the Bookmarks.plist dict for a given title
fn read_bookmarks_plist(title: &str) -> Plist {

  // All Safari data lives at ~/Library/Safari/Bookmarks.plist
  // TODO: There's probably a more idiomatic Rust-like way to write this.
  let mut plist_path = match env::home_dir() {
    Some(v) => v,
    None => error!("Unable to get path to Bookmarks.plist?"),
  };
  plist_path.push("Library/Safari/Bookmarks.plist");

  let file = match File::open(plist_path) {
    Ok(v) => v,
    Err(e) => error!("Unable to open ~/Library/Safari/Bookmarks.plist: {:?}", e),
  };

  let plist = match Plist::read(file) {
    Ok(v) => v,
    Err(e) => error!("Unable to read ~/Library/Safari/Bookmarks.plist: {:?}", e),
  };

  let data = match plist.as_dictionary() {
    Some(v) => v,
    None => error!("Unable to parse ~/Library/Safari/Bookmarks.plist as dictionary?"),
  };

  // The structure of Bookmarks.plist is as follows:
  //
  //     <dict>
  //       <key>Children</key>
  //       <array>
  //         <dict>
  //           <key>Title</key><string>History</string>
  //           ... dict data ...
  //         </dict>
  //         <dict>
  //           <key>Title</key><string>com.apple.ReadingList</string>
  //           ... dict data ...
  //         </dict>
  //         ... other array items ...
  //       </array>
  //     </dict>
  //
  let children = match data.get("Children") {
    Some(child_key) => match child_key.as_array() {
      Some(v) => v,
      None => error!("Top-level children key in ~/Library/Safari/Bookmarks.plist isn't an array?"),
    },
    None => error!("Unable to find top-level Children key in ~/Library/Safari/Bookmarks.plist"),
  };

  let mut matching_children = children.iter().filter(|d|
    match d.as_dictionary() {
      Some(dict) => match dict.get("Title") {
        Some(title_elem) => match title_elem.as_string() {
          Some(v) => (v == title),
          None => false,
        },
        None => false,
      },
      None => false,
    }
  );

  // Check we got one, and only one result.
  let result = match matching_children.next() {
    Some(v) => v,
    None => error!("Unable to find key {} in Bookmarks.plist", title),
  };

  match matching_children.next() {
    Some(_) => error!("Got more than one result for {} in Bookmarks.plist", title),
    None => {},
  };

  result.to_owned()
}

/// Return a list of URLs from Reading List.
///
/// Iteration order depends on the order in which they're stored in
/// Bookmarks.plist, which is usually (but not guaranteed to be) newest first.
///
pub fn get_reading_list_urls() -> Vec<String> {
  let plist = read_bookmarks_plist("com.apple.ReadingList");

  // TODO: All these unwrap() calls should probably be handled better
  let children = plist
    .as_dictionary().unwrap()
    .get("Children").unwrap()
    .as_array().unwrap();

  children
    .iter()
    .map(|child|
      child
        .as_dictionary().unwrap()
        .get("URLString").unwrap()
        .as_string().unwrap()
    )
    .map(|url| urls::tidy_url(url))
    .collect()
}
<|endoftext|>


<commit_before>use params::*;

use rustc_serialize::json::{ToJson, Json};

use std::collections::BTreeMap;

/// Struct for containing the search results and the
/// parameters given inside the query string.
pub struct SearchResult {
  pub results: Vec<u32>,
  pub params:  Map
}

impl ToJson for SearchResult {
  /// Results are returned as Json<Vec<u32>>, while params
  /// are casted to `Vec<String>`, `u32` and `String`, fallbacking
  /// one to another the conversion doesn't succeed.
  fn to_json(&self) -> Json {
    let mut values: BTreeMap<String, Json> = BTreeMap::new();

    for (key_, value) in &self.params.0 {
      let key = key_.clone();

      match Vec::<String>::from_value(value) {
        Some(value) => { values.insert(key, value.to_json()); },
        None        => {
          match u32::from_value(value) {
            Some(value) => { values.insert(key, value.to_json()); },
            None        => {
              match String::from_value(value) {
                Some(value) => { values.insert(key, value.to_json()); },
                None        => {}
              }
            }
          }
        }
      }
    }

    let mut map = BTreeMap::new();
    map.insert("results".to_string(), self.results.to_json());
    map.insert("params".to_string(),  values.to_json());

    Json::Object(map)
  }
}

#[cfg(test)]
mod tests {
  use params::*;
  use search::SearchResult;
  use rustc_serialize::json::{self, ToJson};

  #[test]
  fn test_search_result_to_json() {
    {
      let mut params = Map::new();
      params.assign("work_roles[]", Value::String("Fullstack".into())).unwrap();
      params.assign("work_roles[]", Value::String("DevOps".into())).unwrap();
      params.assign("page",         Value::I64(42)).unwrap();
      params.assign("vbb",          Value::String("vbb".into())).unwrap();

      let response = SearchResult {
        results: vec![],
        params:  params.clone()
      };

      let json_response = json::encode(&response.to_json()).unwrap();
      assert_eq!(json_response,
        "{\"params\":{\"page\":42,\"vbb\":\"vbb\",\"work_roles\":[\"Fullstack\",\"DevOps\"]},\"results\":[]}");
    }

    {
      let response = SearchResult {
        results: vec![],
        params:  Map::new()
      };

      let json_response = json::encode(&response.to_json()).unwrap();
      assert_eq!(json_response, "{\"params\":{},\"results\":[]}");
    }
  }
}
<commit_msg>search: prefer () to {} for empty statements in match blocks<commit_after>use params::*;

use rustc_serialize::json::{ToJson, Json};

use std::collections::BTreeMap;

/// Struct for containing the search results and the
/// parameters given inside the query string.
pub struct SearchResult {
  pub results: Vec<u32>,
  pub params:  Map
}

impl ToJson for SearchResult {
  /// Results are returned as Json<Vec<u32>>, while params
  /// are casted to `Vec<String>`, `u32` and `String`, fallbacking
  /// one to another the conversion doesn't succeed.
  fn to_json(&self) -> Json {
    let mut values: BTreeMap<String, Json> = BTreeMap::new();

    for (key_, value) in &self.params.0 {
      let key = key_.clone();

      match Vec::<String>::from_value(value) {
        Some(value) => { values.insert(key, value.to_json()); },
        None        => {
          match u32::from_value(value) {
            Some(value) => { values.insert(key, value.to_json()); },
            None        => {
              match String::from_value(value) {
                Some(value) => { values.insert(key, value.to_json()); },
                None        => ()
              }
            }
          }
        }
      }
    }

    let mut map = BTreeMap::new();
    map.insert("results".to_string(), self.results.to_json());
    map.insert("params".to_string(),  values.to_json());

    Json::Object(map)
  }
}

#[cfg(test)]
mod tests {
  use params::*;
  use search::SearchResult;
  use rustc_serialize::json::{self, ToJson};

  #[test]
  fn test_search_result_to_json() {
    {
      let mut params = Map::new();
      params.assign("work_roles[]", Value::String("Fullstack".into())).unwrap();
      params.assign("work_roles[]", Value::String("DevOps".into())).unwrap();
      params.assign("page",         Value::I64(42)).unwrap();
      params.assign("vbb",          Value::String("vbb".into())).unwrap();

      let response = SearchResult {
        results: vec![],
        params:  params.clone()
      };

      let json_response = json::encode(&response.to_json()).unwrap();
      assert_eq!(json_response,
        "{\"params\":{\"page\":42,\"vbb\":\"vbb\",\"work_roles\":[\"Fullstack\",\"DevOps\"]},\"results\":[]}");
    }

    {
      let response = SearchResult {
        results: vec![],
        params:  Map::new()
      };

      let json_response = json::encode(&response.to_json()).unwrap();
      assert_eq!(json_response, "{\"params\":{},\"results\":[]}");
    }
  }
}
<|endoftext|>


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

use std::io::Error;
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use std::{mem, thread};
use std::net::{TcpStream, TcpListener};
use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd};

use libc;
use libc::{c_int, c_void};
use slab::Slab;
use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use errno::errno;
use threadpool::ThreadPool;
use openssl::ssl::{SslStream, SslContext};
use ss::nonblocking::plain::Plain;
use ss::nonblocking::secure::Secure;
use ss::{Socket, Stream, SRecv, SSend, TcpOptions, SocketOptions};

use stats;
use types::*;
use config::Config;

// We need to be able to access our resource pool from several methods
static mut thread_pool: *mut ThreadPool = 0 as *mut ThreadPool;

// Global SslContext
static mut ssl_context: *mut SslContext = 0 as *mut SslContext;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLET  - Fd is in EdgeTriggered mode (notification on state changes)
// EPOLLIN  - Data is available in kerndl buffer
const EVENTS: u32 = event_type::EPOLLET | event_type::EPOLLIN;

/// Starts the epoll wait and incoming connection listener threads.
pub fn begin(config: Config, handler: Box<EventHandler>) {
    // Master socket list
    let sockets = Arc::new(Mutex::new(Slab::<Stream, usize>::new(100000)));

    // Resource pool
    let mut tp = ThreadPool::new(config.workers);
    unsafe {
        thread_pool = &mut tp;
    }

    // Wrap our event handler into something that can be safely shared
    // between threads.
    let e_handler = Handler(Box::into_raw(handler));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        return;
    }
    let epfd = result.unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    let streams2 = sockets.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            event_loop(epfd2, streams2, e_handler);
        })
        .unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let streams3 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
           listen(config, epfd3, streams3);
        })
        .unwrap();

    // Stay alive forever, or at least we hope
    let _ = prox.join();
}

/// Incoming connection listening thread
fn listen(config: Config, epfd: RawFd, streams: StreamList) {
    // Setup server and listening port
    let listener_result = try_setup_tcp_listener(&config);
    if listener_result.is_err() {
        error!("Setting up server: {}", listener_result.unwrap_err());
        return;
    }

    // If we're using SSL, setup our context reference
    if config.ssl.is_some() {
        setup_ssl_context(&config);
    }

    // Begin listening for new connections
    let listener = listener_result.unwrap();
    for accept_result in listener.incoming() {
        match accept_result {
            Ok(tcp_stream) => handle_new_connection(tcp_stream, &config, epfd, streams.clone()),
            Err(e) => error!("Accepting connection: {}", e)
        }
    }

    drop(listener);
}

fn try_setup_tcp_listener(config: &Config) -> Result<TcpListener, Error> {
    let create_result = TcpListener::bind((&config.addr[..], config.port));
    if create_result.is_err() {
        return create_result;
    }

    let listener = create_result.unwrap();
    let server_fd = listener.as_raw_fd();

    // Set the SO_REUSEADDR so that restarts after crashes do not take 5min to unbind
    // the initial port
    unsafe {
        let optval: c_int = 1;
        let opt_result = libc::setsockopt(server_fd,
                                          libc::SOL_SOCKET,
                                          libc::SO_REUSEADDR,
                                          &optval as *const _ as *const c_void,
                                          mem::size_of::<c_int>() as u32);
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }
    }

    Ok(listener)
}

fn setup_ssl_context(config: &Config) {
    unsafe {
        ssl_context = Box::into_raw(Box::new(config.ssl.clone().unwrap()));
    }
}

fn handle_new_connection(tcp_stream: TcpStream, config: &Config, epfd: RawFd, streams: StreamList) {
    // Update our total opened file descriptors
    stats::fd_opened();

    // Create new socket
    let socket = Socket::new(tcp_stream.into_raw_fd());

    // Socket's fd for option setting after connection has been established
    let fd = socket.as_raw_fd();

    // Setup our stream
    let stream = match config.ssl {
        Some(_) => {
            let ssl_result = unsafe { SslStream::accept(&(*ssl_context), socket) };
            match ssl_result {
                Ok(ssl_stream) => {
                    let secure_stream = Secure::new(ssl_stream);
                    Stream::new(Box::new(secure_stream))
                }
                Err(ssl_error) => {
                    error!("Creating SslStream: {}", ssl_error);
                    close_fd(fd);
                    return;
                }
            }
        }
        None => {
            let plain_text = Plain::new(socket);
            Stream::new(Box::new(plain_text))
        }
    };

    // Setup various socket options
    let mut opt_socket = Socket::new(fd);
    let result = setup_new_socket(&mut opt_socket);
    if result.is_err() {
        close_fd(fd);
        return;
    }

    // Add stream to our server
    let fd = stream.as_raw_fd();
    add_stream_to_master_list(stream, streams.clone());
    add_fd_to_epoll(epfd, fd, streams.clone());
}

/// Sets up various socket options
fn setup_new_socket(socket: &mut Socket) -> Result<(), ()> {
    let result = socket.set_nonblocking();
    if result.is_err() {
        error!("Setting fd to nonblocking: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_tcp_nodelay(true);
    if result.is_err() {
        error!("Setting tcp_nodelay: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_keepalive(true);
    if result.is_err() {
        error!("Setting tcp_keepalive: {}", result.unwrap_err());
        return Err(());
    }

    Ok(())
}

/// Event loop for handling all epoll events
fn event_loop(epfd: RawFd, streams: StreamList, handler: Handler) {
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe {
        events.set_len(100);
    }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    handle_epoll_event(epfd, &events[x], streams.clone(), handler.clone());
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        };
    }
}

/// Finds the stream the epoll event is associated with and parses the event type
/// to hand off to specific handlers
fn handle_epoll_event(epfd: RawFd, event: &EpollEvent, streams: StreamList, handler: Handler) {
    const READ_EVENT: u32 = event_type::EPOLLIN;

    let fd = event.data as RawFd;
    let find_result = try_find_stream_from_fd(streams.clone(), fd);
    if find_result.is_err() {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);
    }

    let stream = find_result.unwrap();
    let read_event = if (event.events & READ_EVENT) > 0 {
        true
    } else {
        false
    };

    if read_event {
        handle_read_event(epfd, stream, streams, handler);
    } else {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        unsafe {
            (*thread_pool).execute(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(fd);
            });
        }
    }
}

fn try_find_stream_from_fd(streams: StreamList, fd: RawFd) -> Result<Stream, ()> {
    let mut guard = match streams.lock() {
        Ok(g) => g,
        Err(p) => p.into_inner()
    };
    let list = guard.deref_mut();

    let mut found = false;
    let mut index = 0;
    for x in 0..list.count() {
        match list.get(x) {
            Some(stream) => {
                if stream.as_raw_fd() == fd {
                    found = true;
                    index = x;
                    break;
                }
            }
            None => { }
        };
    }

    if found {
        Ok(list.remove(index).unwrap())
    } else {
        Err(())
    }
}

/// Reads all available data on the stream.
///
/// If a complete message(s) is available, each message will be routed through the
/// resource pool.
///
/// If an error occurs during the read, the stream is dropped from the server.
fn handle_read_event(epfd: RawFd, stream: Stream, streams: StreamList, handler: Handler) {
    let fd = stream.as_raw_fd();

    let mut stream = stream;
    let recv_result = stream.recv();
    if recv_result.is_err() {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        unsafe {
            (*thread_pool).execute(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(fd);
            });
        }
        return;
    }

    let mut msg_queue = stream.drain_rx_queue();
    for msg in msg_queue.drain(..) {
        let s = stream.clone();
        let sl = streams.clone();
        let h = handler.clone();

        if msg_is_stats_request(&msg) {
            handle_stats_request(&msg, epfd, s, sl);
        } else {
            unsafe {
                (*thread_pool).execute(move || {
                    let Handler(ptr) = h;
                    (*ptr).on_data_received(s, msg);
                });
            }
        }
    }

    add_stream_to_master_list(stream, streams);
}

#[inline]
fn msg_is_stats_request(msg: &[u8]) -> bool {
    if msg.len() == 6 && msg[0] == 0x04 && msg[1] == 0x04 {
        true
    } else {
        false
    }
}

fn handle_stats_request(buf: &[u8], epfd: RawFd, stream: Stream, streams: StreamList) {
    trace!("handle_stats_request");
    let stream_clone = stream.clone();
    let u8ptr: *const u8 = &buf[2] as *const _;
    let f32ptr: *const f32 = u8ptr as *const _;
    unsafe {
        let sec = *f32ptr;
        (*thread_pool).execute(move || {
            let stats_result = stats::as_serialized_buffer(sec);
            if stats_result.is_err() {
                error!("Retrieving stats");
                return;
            }

            let stats_buffer = stats_result.unwrap();

            let mut stream = stream;
            let send_result = stream.send(&stats_buffer[..]);
            if send_result.is_err() {
                error!("Writing to stream: {}", send_result.unwrap_err());
                let fd = stream.as_raw_fd();
                remove_fd_from_epoll(epfd, fd);
                close_fd(fd);
            }
        });
    }

    add_stream_to_master_list(stream_clone, streams);
}

/// Inserts the stream back into the master list of streams
fn add_stream_to_master_list(stream: Stream, streams: StreamList) {
    { // Mutex lock
        let mut guard = match streams.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner()
        };

        let list = guard.deref_mut();

        // Allocate if we need more slab space
        if !list.has_remaining() {
            let extra_capacity = list.count();
            list.grow(extra_capacity);
        }

        let _ = list.insert(stream);
    } // Mutex unlock

    stats::conn_recv();
}

/// Adds a new fd to the epoll instance
fn add_fd_to_epoll(epfd: RawFd, fd: RawFd, streams: StreamList) {
    let result = epoll::ctl(epfd,
                            ctl_op::ADD,
                            fd,
                            &mut EpollEvent {
                                data: fd as u64,
                                events: EVENTS,
                            });

    if result.is_err() {
        error!("epoll::CtrlError during add: {}", result.unwrap_err());

        remove_fd_from_list(fd, streams.clone());
        close_fd(fd);
    }
}

/// Removes a fd from the epoll instance
fn remove_fd_from_epoll(epfd: RawFd, fd: RawFd) {
    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL. We'll be as backwards compatible as possible.
    let _ = epoll::ctl(epfd,
                       ctl_op::DEL,
                       fd,
                       &mut EpollEvent {
                           data: 0 as u64,
                           events: 0 as u32,
                       })
                .map_err(|e| warn!("Epoll CtrlError during del: {}", e));
}

/// Removes stream with fd from master list
fn remove_fd_from_list(fd: RawFd, streams: StreamList) {
    { // Mutex lock
        let mut guard = match streams.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner()
        };
        let list = guard.deref_mut();

        let mut found = false;
        let mut index = 0;
        for x in 0..list.count() {
            match list.get(x) {
                Some(stream) => {
                    if stream.as_raw_fd() == fd {
                        found = true;
                        index = x;
                        break;
                    }
                }
                None => { }
            };
        }

        if !found {
            return;
        }

        list.remove(index);
    } // Mutex unlock

    stats::conn_lost();
}

/// Closes a fd with the kernel
fn close_fd(fd: RawFd) {
    unsafe {
        let result = libc::close(fd);
        if result < 0 {
            error!("Error closing fd: {}",
                   Error::from_raw_os_error(result as i32));
            return;
        }
    }
    stats::fd_closed();
}
<commit_msg>Adding logs<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::io::Error;
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use std::{mem, thread};
use std::net::{TcpStream, TcpListener};
use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd};

use libc;
use libc::{c_int, c_void};
use slab::Slab;
use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use errno::errno;
use threadpool::ThreadPool;
use openssl::ssl::{SslStream, SslContext};
use ss::nonblocking::plain::Plain;
use ss::nonblocking::secure::Secure;
use ss::{Socket, Stream, SRecv, SSend, TcpOptions, SocketOptions};

use stats;
use types::*;
use config::Config;

// We need to be able to access our resource pool from several methods
static mut thread_pool: *mut ThreadPool = 0 as *mut ThreadPool;

// Global SslContext
static mut ssl_context: *mut SslContext = 0 as *mut SslContext;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLET  - Fd is in EdgeTriggered mode (notification on state changes)
// EPOLLIN  - Data is available in kerndl buffer
const EVENTS: u32 = event_type::EPOLLET | event_type::EPOLLIN;

/// Starts the epoll wait and incoming connection listener threads.
pub fn begin(config: Config, handler: Box<EventHandler>) {
    // Master socket list
    let sockets = Arc::new(Mutex::new(Slab::<Stream, usize>::new(100000)));

    // Resource pool
    let mut tp = ThreadPool::new(config.workers);
    unsafe {
        thread_pool = &mut tp;
    }

    // Wrap our event handler into something that can be safely shared
    // between threads.
    let e_handler = Handler(Box::into_raw(handler));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        return;
    }
    let epfd = result.unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    let streams2 = sockets.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            event_loop(epfd2, streams2, e_handler);
        })
        .unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let streams3 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
           listen(config, epfd3, streams3);
        })
        .unwrap();

    // Stay alive forever, or at least we hope
    let _ = prox.join();
}

/// Incoming connection listening thread
fn listen(config: Config, epfd: RawFd, streams: StreamList) {
    // Setup server and listening port
    let listener_result = try_setup_tcp_listener(&config);
    if listener_result.is_err() {
        error!("Setting up server: {}", listener_result.unwrap_err());
        return;
    }

    // If we're using SSL, setup our context reference
    if config.ssl.is_some() {
        setup_ssl_context(&config);
    }

    // Begin listening for new connections
    let listener = listener_result.unwrap();
    for accept_result in listener.incoming() {
        match accept_result {
            Ok(tcp_stream) => handle_new_connection(tcp_stream, &config, epfd, streams.clone()),
            Err(e) => error!("Accepting connection: {}", e)
        }
    }

    drop(listener);
}

fn try_setup_tcp_listener(config: &Config) -> Result<TcpListener, Error> {
    let create_result = TcpListener::bind((&config.addr[..], config.port));
    if create_result.is_err() {
        return create_result;
    }

    let listener = create_result.unwrap();
    let server_fd = listener.as_raw_fd();

    // Set the SO_REUSEADDR so that restarts after crashes do not take 5min to unbind
    // the initial port
    unsafe {
        let optval: c_int = 1;
        let opt_result = libc::setsockopt(server_fd,
                                          libc::SOL_SOCKET,
                                          libc::SO_REUSEADDR,
                                          &optval as *const _ as *const c_void,
                                          mem::size_of::<c_int>() as u32);
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }
    }

    Ok(listener)
}

fn setup_ssl_context(config: &Config) {
    unsafe {
        ssl_context = Box::into_raw(Box::new(config.ssl.clone().unwrap()));
    }
}

fn handle_new_connection(tcp_stream: TcpStream, config: &Config, epfd: RawFd, streams: StreamList) {
    // Update our total opened file descriptors
    stats::fd_opened();

    // Create new socket
    let socket = Socket::new(tcp_stream.into_raw_fd());

    // Socket's fd for option setting after connection has been established
    let fd = socket.as_raw_fd();

    // Setup our stream
    let stream = match config.ssl {
        Some(_) => {
            let ssl_result = unsafe { SslStream::accept(&(*ssl_context), socket) };
            match ssl_result {
                Ok(ssl_stream) => {
                    let secure_stream = Secure::new(ssl_stream);
                    Stream::new(Box::new(secure_stream))
                }
                Err(ssl_error) => {
                    error!("Creating SslStream: {}", ssl_error);
                    close_fd(fd);
                    return;
                }
            }
        }
        None => {
            let plain_text = Plain::new(socket);
            Stream::new(Box::new(plain_text))
        }
    };

    // Setup various socket options
    let mut opt_socket = Socket::new(fd);
    let opt_set_result = setup_new_socket(&mut opt_socket);
    if opt_set_result.is_err() {
        close_fd(fd);
        return;
    }

    // Add stream to our server
    let fd = stream.as_raw_fd();
    add_stream_to_master_list(stream, streams.clone());
    add_fd_to_epoll(epfd, fd, streams.clone());

    stats::conn_recv();
}

/// Sets up various socket options
fn setup_new_socket(socket: &mut Socket) -> Result<(), ()> {
    let result = socket.set_nonblocking();
    if result.is_err() {
        error!("Setting fd to nonblocking: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_tcp_nodelay(true);
    if result.is_err() {
        error!("Setting tcp_nodelay: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_keepalive(true);
    if result.is_err() {
        error!("Setting tcp_keepalive: {}", result.unwrap_err());
        return Err(());
    }

    Ok(())
}

/// Event loop for handling all epoll events
fn event_loop(epfd: RawFd, streams: StreamList, handler: Handler) {
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe {
        events.set_len(100);
    }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    handle_epoll_event(epfd, &events[x], streams.clone(), handler.clone());
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        };
    }
}

/// Finds the stream the epoll event is associated with and parses the event type
/// to hand off to specific handlers
fn handle_epoll_event(epfd: RawFd, event: &EpollEvent, streams: StreamList, handler: Handler) {
    const READ_EVENT: u32 = event_type::EPOLLIN;

    let fd = event.data as RawFd;
    let find_result = try_find_stream_from_fd(streams.clone(), fd);
    if find_result.is_err() {
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);
    }

    let stream = find_result.unwrap();
    let read_event = if (event.events & READ_EVENT) > 0 {
        true
    } else {
        false
    };

    if read_event {
        handle_read_event(epfd, stream, streams, handler);
    } else {
        trace!("Epoll reported non-read event for fd: {}", fd);

        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        unsafe {
            (*thread_pool).execute(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(fd);
            });
        }
    }
}

fn try_find_stream_from_fd(streams: StreamList, fd: RawFd) -> Result<Stream, ()> {
    let mut guard = match streams.lock() {
        Ok(g) => g,
        Err(p) => p.into_inner()
    };
    let list = guard.deref_mut();

    let mut found = false;
    let mut index = 0;
    for x in 0..list.count() {
        match list.get(x) {
            Some(stream) => {
                if stream.as_raw_fd() == fd {
                    found = true;
                    index = x;
                    break;
                }
            }
            None => { }
        };
    }

    if found {
        Ok(list.remove(index).unwrap())
    } else {
        warn!("Unable to locate fd: {} in StreamList", fd);
        Err(())
    }
}

/// Reads all available data on the stream.
///
/// If a complete message(s) is available, each message will be routed through the
/// resource pool.
///
/// If an error occurs during the read, the stream is dropped from the server.
fn handle_read_event(epfd: RawFd, stream: Stream, streams: StreamList, handler: Handler) {
    let fd = stream.as_raw_fd();

    trace!("Read event for fd: {}", fd);

    let mut stream = stream;
    let recv_result = stream.recv();
    if recv_result.is_err() {
        trace!("Error during recv (disconnect/eof/etc... not real error), closing fd");

        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        unsafe {
            (*thread_pool).execute(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(fd);
            });
        }
        return;
    }

    let mut msg_queue = stream.drain_rx_queue();
    for msg in msg_queue.drain(..) {
        let s = stream.clone();
        let sl = streams.clone();
        let h = handler.clone();

        if msg_is_stats_request(&msg) {
            handle_stats_request(&msg, epfd, s, sl);
        } else {
            unsafe {
                (*thread_pool).execute(move || {
                    let Handler(ptr) = h;
                    (*ptr).on_data_received(s, msg);
                });
            }
        }
    }

    add_stream_to_master_list(stream, streams);
}

#[inline]
fn msg_is_stats_request(msg: &[u8]) -> bool {
    if msg.len() == 6 && msg[0] == 0x04 && msg[1] == 0x04 {
        true
    } else {
        false
    }
}

fn handle_stats_request(buf: &[u8], epfd: RawFd, stream: Stream, streams: StreamList) {
    trace!("handle_stats_request");

    let stream_clone = stream.clone();
    let u8ptr: *const u8 = &buf[2] as *const _;
    let f32ptr: *const f32 = u8ptr as *const _;
    unsafe {
        let sec = *f32ptr;
        (*thread_pool).execute(move || {
            let stats_result = stats::as_serialized_buffer(sec);
            if stats_result.is_err() {
                error!("Retrieving stats");
                return;
            }

            let stats_buffer = stats_result.unwrap();

            let mut stream = stream;
            let send_result = stream.send(&stats_buffer[..]);
            if send_result.is_err() {
                error!("Writing to stream: {}", send_result.unwrap_err());

                let fd = stream.as_raw_fd();
                remove_fd_from_epoll(epfd, fd);
                close_fd(fd);
            }
        });
    }

    add_stream_to_master_list(stream_clone, streams);
}

/// Inserts the stream back into the master list of streams
fn add_stream_to_master_list(stream: Stream, streams: StreamList) {
    { // Mutex lock
        let mut guard = match streams.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner()
        };

        let list = guard.deref_mut();

        // Allocate if we need more slab space
        if !list.has_remaining() {
            let extra_capacity = list.count();

            warn!("Slab filled, allocating {} extra slots", extra_capacity);

            list.grow(extra_capacity);
        }

        let _ = list.insert(stream);
    } // Mutex unlock
}

/// Adds a new fd to the epoll instance
fn add_fd_to_epoll(epfd: RawFd, fd: RawFd, streams: StreamList) {
    let result = epoll::ctl(epfd,
                            ctl_op::ADD,
                            fd,
                            &mut EpollEvent {
                                data: fd as u64,
                                events: EVENTS,
                            });

    if result.is_err() {
        error!("epoll::CtrlError during add: {}", result.unwrap_err());

        remove_fd_from_list(fd, streams.clone());
        close_fd(fd);
    }
}

/// Removes a fd from the epoll instance
fn remove_fd_from_epoll(epfd: RawFd, fd: RawFd) {
    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL. We'll be as backwards compatible as possible.
    let _ = epoll::ctl(epfd,
                       ctl_op::DEL,
                       fd,
                       &mut EpollEvent {
                           data: 0 as u64,
                           events: 0 as u32,
                       })
                .map_err(|e| warn!("Epoll CtrlError during del: {}", e));
}

/// Removes stream with fd from master list
fn remove_fd_from_list(fd: RawFd, streams: StreamList) {
    trace!("Attempting reoval of fd: {}", fd);

    { // Mutex lock
        let mut guard = match streams.lock() {
            Ok(g) => g,
            Err(p) => p.into_inner()
        };
        let list = guard.deref_mut();

        let mut found = false;
        let mut index = 0;
        for x in 0..list.count() {
            match list.get(x) {
                Some(stream) => {
                    if stream.as_raw_fd() == fd {
                        found = true;
                        index = x;
                        break;
                    }
                }
                None => { }
            };
        }

        if !found {
            warn!("fd: {} not found in list when attempting removal", fd);
            return;
        }

        list.remove(index);
    } // Mutex unlock

    trace!("Removal of fd: {} successful", fd);

    stats::conn_lost();
}

/// Closes a fd with the kernel
fn close_fd(fd: RawFd) {
    trace!("Attempting close for fd: {}", fd);

    unsafe {
        let result = libc::close(fd);
        if result < 0 {
            error!("Error closing fd: {}",
                   Error::from_raw_os_error(result as i32));
            return;
        }
    }

    trace!("fd: {} closed successfully", fd);

    stats::fd_closed();
}
<|endoftext|>


<commit_before>extern crate rustc;
use rustc::util::sha2::{Sha256, Digest};

#[cfg(not(test))]
fn main() {
    println!("{}", sha_256("Rosetta code"));
}

fn sha_256(input: &str) -> String {
    let mut sh = box Sha256::new();
    sh.input_str(input);
    sh.result_str()
}

#[test]
fn test_rosetta() {
    assert_eq!(sha_256("Rosetta code"),
    "764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf"
    .to_string());
}<commit_msg>added header and safety note from Sha256 docs<commit_after>// Implements http://rosettacode.org/wiki/SHA-256

// note that for now the rustc::util::sha2::Sha256 docs state:
// This implementation is not intended for external use or for any use where security is
// important.
extern crate rustc;
use rustc::util::sha2::{Sha256, Digest};

#[cfg(not(test))]
fn main() {
    println!("{}", sha_256("Rosetta code"));
}

fn sha_256(input: &str) -> String {
    let mut sh = box Sha256::new();
    sh.input_str(input);
    sh.result_str()
}

#[test]
fn test_rosetta() {
    assert_eq!(sha_256("Rosetta code"),
    "764faf5c61ac315f1497f9dfa542713965b785e5cc2f707d6468d7d1124cdfcf"
    .to_string());
}<|endoftext|>


<commit_before>//! Continuous time signals

use std::sync::{ Arc, Mutex };
use std::ops::Deref;
use source::{ Source, with_weak, CallbackError };
use stream::{ self, BoxClone, Stream };
use transaction::{ commit, register_callback };
use pending::Pending;

enum SignalFn {
    Const(A),
    Func(Box<Fn() -> A + Send + Sync + 'static>),
}

impl SignalFn {
    pub fn from_fn<F: Fn() -> A + Send + Sync + 'static>(f: F) -> SignalFn {
        SignalFn::Func(Box::new(f))
    }
}

impl SignalFn {
    pub fn call(&self) -> A {
        match *self {
            SignalFn::Const(ref a) => a.clone(),
            SignalFn::Func(ref f) => f(),
        }
    }
}

/// A continuous signal.
pub struct Signal {
    current: Arc<Mutex<Pending<SignalFn>>>,
    source: Arc<Mutex<Source<()>>>,
    #[allow(dead_code)]
    keep_alive: Box<BoxClone>,
}

impl Clone for Signal {
    fn clone(&self) -> Signal {
        Signal {
            current: self.current.clone(),
            source: self.source.clone(),
            keep_alive: self.keep_alive.box_clone(),
        }
    }
}

impl Signal {
    /// Create a constant signal.
    pub fn new(a: A) -> Signal {
        Signal {
            current: Arc::new(Mutex::new(Pending::new(SignalFn::Const(a)))),
            source: Arc::new(Mutex::new(Source::new())),
            keep_alive: Box::new(()),
        }
    }

    /// Sample the current value of a signal.
    pub fn sample(&self) -> A {
        commit((), |_| self.current.lock().unwrap().call())
    }
}

impl Signal {
    /// stub
    pub fn snapshot(&self, stream: &Stream) -> Stream<(A, B)>
        where B: Clone + Send + Sync + 'static,
    {
        stream::snapshot(self, stream)
    }
}

impl Signal<Signal> {
    /// stub
    pub fn switch(&self) -> Signal {
        fn make_callback(parent: &Signal<Signal>) -> SignalFn
            where A: Send + Clone + Sync + 'static,
        {
            // TODO: use information on inner value
            let current_signal = parent.current.clone();
            SignalFn::from_fn(move ||
                current_signal.lock().unwrap().call().sample()
            )
        }
        commit((), |_| {
            let current = Arc::new(Mutex::new(Pending::new(make_callback(self))));
            let source = Arc::new(Mutex::new(Source::new()));
            let weak_source = source.downgrade();
            let weak_current = current.downgrade();
            let parent = self.clone();
            self.source.lock().unwrap().register(move |()|
                weak_current.upgrade().map(|cur| register_callback(
                    move || { let _ = cur.lock().map(|mut cur| cur.update()); }))
                    .ok_or(CallbackError::Disappeared)
                .and(with_weak(&weak_current, |cur| cur.queue(make_callback(&parent))))
                .and(with_weak(&weak_source, |src| src.send(())))
            );
            Signal {
                source: source,
                current: current,
                keep_alive: Box::new(()),
            }
        })
    }
}

/// stub
pub struct SignalCycle {
    signal: Signal,
}

impl SignalCycle {
    /// stub
    pub fn new() -> SignalCycle {
        SignalCycle { signal: Signal {
            current: Arc::new(Mutex::new(Pending::new(SignalFn::from_fn(
                || panic!("sampled on forward-declaration of signal")
            )))),
            source: Arc::new(Mutex::new(Source::new())),
            keep_alive: Box::new(()),
        } }
    }

    /// stub
    pub fn define(self, definition: Signal) -> Signal {
        /// Generate a callback from the signal definition's current value.
        fn make_callback(current_def: &Arc<Mutex<Pending<SignalFn>>>) -> SignalFn
            where A: Send + Sync + Clone + 'static
        {
            match *current_def.lock().unwrap().future() {
                SignalFn::Const(ref a) => SignalFn::Const(a.clone()),
                SignalFn::Func(_) => SignalFn::from_fn({
                    let sig = current_def.downgrade();
                    move || {
                        let strong = sig.upgrade().unwrap();
                        let ret = strong.lock().unwrap().call();
                        ret
                    }
                }),
            }
        }
        commit((), move |_| {
            *self.signal.current.lock().unwrap() = Pending::new(make_callback(&definition.current));
            let sig = definition.current.downgrade();
            let weak_source = self.signal.source.downgrade();
            let weak_current = self.signal.current.downgrade();
            definition.source.lock().unwrap().register(move |()|
                weak_current.upgrade().map(|cur| register_callback(
                    move || { let _ = cur.lock().map(|mut cur| cur.update()); }))
                    .ok_or(CallbackError::Disappeared)
                .and(with_weak(&weak_current, |cur| cur.queue(make_callback(&sig.upgrade().unwrap()))))
                .and(with_weak(&weak_source, |src| src.send(())))
            );
            Signal {
                keep_alive: Box::new(definition),
                ..self.signal
            }
        })
    }
}

impl Deref for SignalCycle {
    type Target = Signal;
    fn deref(&self) -> &Signal { &self.signal }
}

/// Hold a stream as a signal.
pub fn hold(initial: A, stream: &Stream) -> Signal
    where A: Send + Sync + 'static,
{
    commit((), |_| {
        let source = Arc::new(Mutex::new(Source::new()));
        let current = Arc::new(Mutex::new(Pending::new(SignalFn::Const(initial))));
        let weak_source = source.downgrade();
        let weak_current = current.downgrade();
        stream::source(&stream).lock().unwrap().register(move |a| {
            weak_current.upgrade().map(|cur| register_callback(
                move || { let _ = cur.lock().map(|mut cur| cur.update()); }))
                .ok_or(CallbackError::Disappeared)
            .and(with_weak(&weak_current, |cur| cur.queue(SignalFn::Const(a))))
            .and(with_weak(&weak_source, |src| src.send(())))
        });
        Signal {
            current: current,
            source: source,
            keep_alive: Box::new(stream.clone()),
        }
    })
}

/// Lift a 0-ary function to a signal.
pub fn lift0(f: F) -> Signal
    where F: Fn() -> A + Send + Sync + 'static
{
    Signal {
        current: Arc::new(Mutex::new(Pending::new(SignalFn::from_fn(f)))),
        source: Arc::new(Mutex::new(Source::new())),
        keep_alive: Box::new(()),
    }
}

/// Unary lift
pub fn lift1(f: F, sa: &Signal) -> Signal
    where A: Send + Sync + Clone + 'static,
          B: Send + Sync + Clone + 'static,
          F: Fn(A) -> B + Send + Sync + 'static,
{
    fn make_callback(f: &Arc<F>, parent: &Signal) -> SignalFn
        where A: Send + Sync + Clone + 'static,
              B: Send + Sync + Clone + 'static,
              F: Fn(A) -> B + Send + Sync + 'static,
    {
        let pclone = parent.clone();
        let f = f.clone();
        match *parent.current.lock().unwrap().future() {
            SignalFn::Const(ref a) => SignalFn::Const(f(a.clone())),
            SignalFn::Func(_) => SignalFn::from_fn(move || f(pclone.sample())),
        }
    }

    let f = Arc::new(f);
    let source = Arc::new(Mutex::new(Source::new()));
    let current = Arc::new(Mutex::new(Pending::new(make_callback(&f, &sa))));
    let weak_source = source.downgrade();
    let weak_current = current.downgrade();
    let sa_2 = sa.clone();
    sa.source.lock().unwrap().register(move |()| {
        weak_current.upgrade().map(|cur| register_callback(
            move || { let _ = cur.lock().map(|mut cur| cur.update()); }))
            .ok_or(CallbackError::Disappeared)
        .and(with_weak(&weak_current, |cur| cur.queue(make_callback(&f, &sa_2))))
        .and(with_weak(&weak_source, |src| src.send(())))
    });
    Signal {
        source: source,
        current: current,
        keep_alive: Box::new(()),
    }
}

#[cfg(test)]
mod test {
    use ::stream::Sink;
    use ::signal::{ self, Signal, SignalCycle };

    #[test]
    fn clone() {
        let b = Signal::new(3);
        assert_eq!(b.clone().sample(), 3);
    }

    #[test]
    fn lift0() {
        let signal = signal::lift0(|| 3);
        assert_eq!(signal.sample(), 3);
    }

    #[test]
    fn lift1() {
        let sig2 = signal::lift1(|n| n + 2, &Signal::new(3));
        assert_eq!(sig2.sample(), 5);
    }

    #[test]
    fn hold() {
        let sink = Sink::new();
        let signal = sink.stream().hold(3);
        assert_eq!(signal.sample(), 3);
        sink.send(4);
        assert_eq!(signal.sample(), 4);
    }

    #[test]
    fn hold_implicit_stream() {
        let sink = Sink::new();
        let signal = signal::hold(0, &sink.stream().map(|n| 2 * n));
        assert_eq!(signal.sample(), 0);
        sink.send(4);
        assert_eq!(signal.sample(), 8);
    }

    #[test]
    fn snapshot() {
        let sink1: Sink<i32> = Sink::new();
        let sink2: Sink<f64> = Sink::new();
        let mut snap_events = sink1.stream().hold(1).snapshot(&sink2.stream().map(|x| x + 3.0)).events();
        sink2.send(4.0);
        assert_eq!(snap_events.next(), Some((1, 7.0)));
    }

    #[test]
    fn snapshot_2() {
        let ev1 = Sink::new();
        let beh1 = ev1.stream().hold(5);
        let ev2 = Sink::new();
        let snap = beh1.snapshot(&ev2.stream());
        let mut events = snap.events();
        ev2.send(4);
        assert_eq!(events.next(), Some((5, 4)));
        ev1.send(-2);
        ev2.send(6);
        assert_eq!(events.next(), Some((-2, 6)));
    }

    #[test]
    fn switch() {
        let stream1 = Sink::<Option<i32>>::new();
        let stream2 = Sink::<Option<i32>>::new();
        let button1 = Sink::<()>::new();
        let button2 = Sink::<()>::new();
        let output = {
            let stream1 = stream1.stream().hold(Some(-1));
            let stream2 = stream2.stream().hold(Some(-2));
            button1.stream()
                .map(move |_| stream1.clone())
                .merge(&button2.stream()
                    .map(move |_| stream2.clone())
                )
                .hold(Sink::new().stream().hold(Some(-3)))
                .switch()
        };
        let fn_output = signal::lift1(|x| x.map_or(0, |x| 2*x), &output);
        assert_eq!(output.sample(), Some(-3));
        assert_eq!(fn_output.sample(), -6);
        button1.send(());
        assert_eq!(output.sample(), Some(-1));
        button2.send(());
        assert_eq!(output.sample(), Some(-2));
        button1.send(());
        stream1.send(Some(6));
        assert_eq!(output.sample(), Some(6));
        assert_eq!(fn_output.sample(), 12);
        stream1.send(Some(12));
        assert_eq!(output.sample(), Some(12));
        assert_eq!(fn_output.sample(), 24);
    }

    #[test]
    fn cyclic_snapshot_accum() {
        let sink = Sink::new();
        let stream = sink.stream();
        let accum = SignalCycle::new();
        let def = accum.snapshot(&stream).map(|(a, s)| a + s).hold(0);
        let accum = accum.define(def);
        assert_eq!(accum.sample(), 0);
        sink.send(3);
        assert_eq!(accum.sample(), 3);
        sink.send(7);
        assert_eq!(accum.sample(), 10);
        sink.send(-21);
        assert_eq!(accum.sample(), -11);
    }

    #[test]
    fn snapshot_order_standard() {
        let sink = Sink::new();
        let cell = sink.stream().hold(0);
        let mut events = cell.snapshot(&sink.stream()).events();
        sink.send(1);
        assert_eq!(events.next(), Some((0, 1)));
    }

    #[test]
    fn snapshot_lift_order_standard() {
        let sink = Sink::new();
        let cell = sink.stream().hold(0);
        let mut events = signal::lift1(|x| x, &cell)
            .snapshot(&sink.stream())
            .events();
        sink.send(1);
        assert_eq!(events.next(), Some((0, 1)));
    }

    #[test]
    fn snapshot_order_alternative() {
        let sink = Sink::new();
        // Invert the "natural" order of the registry by declaring the stream before
        // the cell, which are both used by the snapshot.
        let first = sink.stream().map(|x| x);
        let cell = sink.stream().hold(0);
        let mut events = cell.snapshot(&first).events();
        sink.send(1);
        assert_eq!(events.next(), Some((0, 1)));
    }
}
<commit_msg>Factor out signal callback registration<commit_after>//! Continuous time signals

use std::sync::{ Arc, Mutex };
use std::ops::Deref;
use source::{ Source, with_weak, CallbackError };
use stream::{ self, BoxClone, Stream };
use transaction::{ commit, register_callback };
use pending::Pending;

enum SignalFn {
    Const(A),
    Func(Box<Fn() -> A + Send + Sync + 'static>),
}

impl SignalFn {
    pub fn from_fn<F: Fn() -> A + Send + Sync + 'static>(f: F) -> SignalFn {
        SignalFn::Func(Box::new(f))
    }
}

impl SignalFn {
    pub fn call(&self) -> A {
        match *self {
            SignalFn::Const(ref a) => a.clone(),
            SignalFn::Func(ref f) => f(),
        }
    }
}

/// Helper function to register callback handlers related to signal construction.
fn reg_signal(parent_source: &mut Source, signal: &Signal, handler: F)
    where A: Send + Sync + 'static,
          B: Send + Sync + 'static,
          F: Fn(A) -> SignalFn + Send + Sync + 'static,
{
    let weak_source = signal.source.downgrade();
    let weak_current = signal.current.downgrade();
    parent_source.register(move |a|
        weak_current.upgrade().map(|cur| register_callback(
            move || { let _ = cur.lock().map(|mut cur| cur.update()); }))
            .ok_or(CallbackError::Disappeared)
        .and(with_weak(&weak_current, |cur| cur.queue(handler(a))))
        .and(with_weak(&weak_source, |src| src.send(())))
    );
}

/// A continuous signal.
pub struct Signal {
    current: Arc<Mutex<Pending<SignalFn>>>,
    source: Arc<Mutex<Source<()>>>,
    #[allow(dead_code)]
    keep_alive: Box<BoxClone>,
}

impl Clone for Signal {
    fn clone(&self) -> Signal {
        Signal {
            current: self.current.clone(),
            source: self.source.clone(),
            keep_alive: self.keep_alive.box_clone(),
        }
    }
}

impl Signal {
    /// Create a constant signal.
    pub fn new(a: A) -> Signal {
        Signal {
            current: Arc::new(Mutex::new(Pending::new(SignalFn::Const(a)))),
            source: Arc::new(Mutex::new(Source::new())),
            keep_alive: Box::new(()),
        }
    }

    /// Sample the current value of a signal.
    pub fn sample(&self) -> A {
        commit((), |_| self.current.lock().unwrap().call())
    }
}

impl Signal {
    /// stub
    pub fn snapshot(&self, stream: &Stream) -> Stream<(A, B)>
        where B: Clone + Send + Sync + 'static,
    {
        stream::snapshot(self, stream)
    }
}

impl Signal<Signal> {
    /// stub
    pub fn switch(&self) -> Signal {
        fn make_callback(parent: &Signal<Signal>) -> SignalFn
            where A: Send + Clone + Sync + 'static,
        {
            // TODO: use information on inner value
            let current_signal = parent.current.clone();
            SignalFn::from_fn(move ||
                current_signal.lock().unwrap().call().sample()
            )
        }
        commit((), |_| {
            let signal = Signal {
                current: Arc::new(Mutex::new(Pending::new(make_callback(self)))),
                source: Arc::new(Mutex::new(Source::new())),
                keep_alive: Box::new(()),
            };
            let parent = self.clone();
            reg_signal(&mut self.source.lock().unwrap(), &signal,
                move |_| make_callback(&parent));
            signal
        })
    }
}

/// stub
pub struct SignalCycle {
    signal: Signal,
}

impl SignalCycle {
    /// stub
    pub fn new() -> SignalCycle {
        SignalCycle { signal: Signal {
            current: Arc::new(Mutex::new(Pending::new(SignalFn::from_fn(
                || panic!("sampled on forward-declaration of signal")
            )))),
            source: Arc::new(Mutex::new(Source::new())),
            keep_alive: Box::new(()),
        } }
    }

    /// stub
    pub fn define(self, definition: Signal) -> Signal {
        /// Generate a callback from the signal definition's current value.
        fn make_callback(current_def: &Arc<Mutex<Pending<SignalFn>>>) -> SignalFn
            where A: Send + Sync + Clone + 'static
        {
            match *current_def.lock().unwrap().future() {
                SignalFn::Const(ref a) => SignalFn::Const(a.clone()),
                SignalFn::Func(_) => SignalFn::from_fn({
                    let sig = current_def.downgrade();
                    move || {
                        let strong = sig.upgrade().unwrap();
                        let ret = strong.lock().unwrap().call();
                        ret
                    }
                }),
            }
        }
        commit((), move |_| {
            *self.signal.current.lock().unwrap() = Pending::new(make_callback(&definition.current));
            let weak_parent = definition.current.downgrade();
            reg_signal(&mut definition.source.lock().unwrap(), &self.signal,
                move |_| make_callback(&weak_parent.upgrade().unwrap()));
            Signal { keep_alive: Box::new(definition), ..self.signal }
        })
    }
}

impl Deref for SignalCycle {
    type Target = Signal;
    fn deref(&self) -> &Signal { &self.signal }
}

/// Hold a stream as a signal.
pub fn hold(initial: A, stream: &Stream) -> Signal
    where A: Send + Sync + 'static,
{
    commit((), |_| {
        let signal = Signal {
            source: Arc::new(Mutex::new(Source::new())),
            current: Arc::new(Mutex::new(Pending::new(SignalFn::Const(initial)))),
            keep_alive: Box::new(stream.clone()),
        };
        reg_signal(&mut stream::source(&stream).lock().unwrap(), &signal, SignalFn::Const);
        signal
    })
}

/// Lift a 0-ary function to a signal.
pub fn lift0(f: F) -> Signal
    where F: Fn() -> A + Send + Sync + 'static
{
    Signal {
        current: Arc::new(Mutex::new(Pending::new(SignalFn::from_fn(f)))),
        source: Arc::new(Mutex::new(Source::new())),
        keep_alive: Box::new(()),
    }
}

/// Unary lift
pub fn lift1(f: F, sa: &Signal) -> Signal
    where A: Send + Sync + Clone + 'static,
          B: Send + Sync + Clone + 'static,
          F: Fn(A) -> B + Send + Sync + 'static,
{
    fn make_callback(f: &Arc<F>, parent: &Signal) -> SignalFn
        where A: Send + Sync + Clone + 'static,
              B: Send + Sync + Clone + 'static,
              F: Fn(A) -> B + Send + Sync + 'static,
    {
        let pclone = parent.clone();
        let f = f.clone();
        match *parent.current.lock().unwrap().future() {
            SignalFn::Const(ref a) => SignalFn::Const(f(a.clone())),
            SignalFn::Func(_) => SignalFn::from_fn(move || f(pclone.sample())),
        }
    }

    let f = Arc::new(f);
    let source = Arc::new(Mutex::new(Source::new()));
    let current = Arc::new(Mutex::new(Pending::new(make_callback(&f, &sa))));
    let weak_source = source.downgrade();
    let weak_current = current.downgrade();
    let sa_2 = sa.clone();
    sa.source.lock().unwrap().register(move |()| {
        weak_current.upgrade().map(|cur| register_callback(
            move || { let _ = cur.lock().map(|mut cur| cur.update()); }))
            .ok_or(CallbackError::Disappeared)
        .and(with_weak(&weak_current, |cur| cur.queue(make_callback(&f, &sa_2))))
        .and(with_weak(&weak_source, |src| src.send(())))
    });
    Signal {
        source: source,
        current: current,
        keep_alive: Box::new(()),
    }
}

#[cfg(test)]
mod test {
    use ::stream::Sink;
    use ::signal::{ self, Signal, SignalCycle };

    #[test]
    fn clone() {
        let b = Signal::new(3);
        assert_eq!(b.clone().sample(), 3);
    }

    #[test]
    fn lift0() {
        let signal = signal::lift0(|| 3);
        assert_eq!(signal.sample(), 3);
    }

    #[test]
    fn lift1() {
        let sig2 = signal::lift1(|n| n + 2, &Signal::new(3));
        assert_eq!(sig2.sample(), 5);
    }

    #[test]
    fn hold() {
        let sink = Sink::new();
        let signal = sink.stream().hold(3);
        assert_eq!(signal.sample(), 3);
        sink.send(4);
        assert_eq!(signal.sample(), 4);
    }

    #[test]
    fn hold_implicit_stream() {
        let sink = Sink::new();
        let signal = signal::hold(0, &sink.stream().map(|n| 2 * n));
        assert_eq!(signal.sample(), 0);
        sink.send(4);
        assert_eq!(signal.sample(), 8);
    }

    #[test]
    fn snapshot() {
        let sink1: Sink<i32> = Sink::new();
        let sink2: Sink<f64> = Sink::new();
        let mut snap_events = sink1.stream().hold(1).snapshot(&sink2.stream().map(|x| x + 3.0)).events();
        sink2.send(4.0);
        assert_eq!(snap_events.next(), Some((1, 7.0)));
    }

    #[test]
    fn snapshot_2() {
        let ev1 = Sink::new();
        let beh1 = ev1.stream().hold(5);
        let ev2 = Sink::new();
        let snap = beh1.snapshot(&ev2.stream());
        let mut events = snap.events();
        ev2.send(4);
        assert_eq!(events.next(), Some((5, 4)));
        ev1.send(-2);
        ev2.send(6);
        assert_eq!(events.next(), Some((-2, 6)));
    }

    #[test]
    fn switch() {
        let stream1 = Sink::<Option<i32>>::new();
        let stream2 = Sink::<Option<i32>>::new();
        let button1 = Sink::<()>::new();
        let button2 = Sink::<()>::new();
        let output = {
            let stream1 = stream1.stream().hold(Some(-1));
            let stream2 = stream2.stream().hold(Some(-2));
            button1.stream()
                .map(move |_| stream1.clone())
                .merge(&button2.stream()
                    .map(move |_| stream2.clone())
                )
                .hold(Sink::new().stream().hold(Some(-3)))
                .switch()
        };
        let fn_output = signal::lift1(|x| x.map_or(0, |x| 2*x), &output);
        assert_eq!(output.sample(), Some(-3));
        assert_eq!(fn_output.sample(), -6);
        button1.send(());
        assert_eq!(output.sample(), Some(-1));
        button2.send(());
        assert_eq!(output.sample(), Some(-2));
        button1.send(());
        stream1.send(Some(6));
        assert_eq!(output.sample(), Some(6));
        assert_eq!(fn_output.sample(), 12);
        stream1.send(Some(12));
        assert_eq!(output.sample(), Some(12));
        assert_eq!(fn_output.sample(), 24);
    }

    #[test]
    fn cyclic_snapshot_accum() {
        let sink = Sink::new();
        let stream = sink.stream();
        let accum = SignalCycle::new();
        let def = accum.snapshot(&stream).map(|(a, s)| a + s).hold(0);
        let accum = accum.define(def);
        assert_eq!(accum.sample(), 0);
        sink.send(3);
        assert_eq!(accum.sample(), 3);
        sink.send(7);
        assert_eq!(accum.sample(), 10);
        sink.send(-21);
        assert_eq!(accum.sample(), -11);
    }

    #[test]
    fn snapshot_order_standard() {
        let sink = Sink::new();
        let cell = sink.stream().hold(0);
        let mut events = cell.snapshot(&sink.stream()).events();
        sink.send(1);
        assert_eq!(events.next(), Some((0, 1)));
    }

    #[test]
    fn snapshot_lift_order_standard() {
        let sink = Sink::new();
        let cell = sink.stream().hold(0);
        let mut events = signal::lift1(|x| x, &cell)
            .snapshot(&sink.stream())
            .events();
        sink.send(1);
        assert_eq!(events.next(), Some((0, 1)));
    }

    #[test]
    fn snapshot_order_alternative() {
        let sink = Sink::new();
        // Invert the "natural" order of the registry by declaring the stream before
        // the cell, which are both used by the snapshot.
        let first = sink.stream().map(|x| x);
        let cell = sink.stream().hold(0);
        let mut events = cell.snapshot(&first).events();
        sink.send(1);
        assert_eq!(events.next(), Some((0, 1)));
    }
}
<|endoftext|>


<commit_before>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, Sample, SampleSize, StreamProducer,
  many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> Result<StreamReader<R>, ErrorKind> {
    let producer = ReadStream::new(reader);

    Stream::from_stream_producer(producer)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::IO(io::ErrorKind::NotFound)` is returned when the given
  ///   filename isn't found.
  /// * `ErrorKind::IO(io::ErrorKind::InvalidData)` is returned when the data
  ///   within the file isn't valid FLAC data.
  /// * Several different parser specific errors that are structured as
  ///   `ErrorKind::<parser_name>Parser`.
  /// * Several different invalidation specific errors that are
  ///   structured as `ErrorKind::Invalid<invalidation_name>`.
  #[inline]
  pub fn from_file(filename: &str) -> Result<StreamReader<File>, ErrorKind> {
    File::open(filename).map_err(|e| ErrorKind::IO(e.kind()))
                        .and_then(|file| {
      let producer = ReadStream::new(file);

      Stream::from_stream_producer(producer)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::IO(io::ErrorKind::InvalidData)` is returned when the data
  ///   within the file isn't valid FLAC data.
  /// * Several different parser specific errors that are structured as
  ///   `ErrorKind::<parser_name>Parser`.
  /// * Several different invalidation specific errors that are
  ///   structured as `ErrorKind::Invalid<invalidation_name>`.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> Result<StreamBuffer, ErrorKind> {
    let producer = ByteStream::new(buffer);

    Stream::from_stream_producer(producer)
  }

  fn from_stream_producer(mut producer: P) -> Result<Self, ErrorKind> {
    let mut stream_info = Default::default();
    let mut metadata    = Vec::new();

    many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    }).map(|_| {
      Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
      }
    })
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter<S: SampleSize>(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;
    let channels     = self.info.channels as usize;
    let block_size   = self.info.max_block_size as usize;
    let buffer_size  = block_size * channels;

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
      buffer: vec![S::Extended::from_i8(0); buffer_size]
    }
  }

  fn next_frame<S>(&mut self, buffer: &mut [S]) -> Option<usize>
   where S: Sample {
    let stream_info = &self.info;

    loop {
      match self.producer.parse(|i| frame_parser(i, stream_info, buffer)) {
        Ok(frame)                => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut buffer[start..end];

            subframe::decode(&subframe, block_size, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, buffer);

          return Some(block_size);
        }
        Err(ErrorKind::Continue) => continue,
        Err(_)                   => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P, S>
 where P: 'a + StreamProducer,
       S: Sample{
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
  buffer: Vec<S>,
}

impl<'a, P, S> Iterator for Iter<'a, P, S>
 where P: StreamProducer,
       S: Sample {
  type Item = S::Normal;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      let buffer = &mut self.buffer;

      if let Some(block_size) = self.stream.next_frame(buffer) {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.buffer[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    S::to_normal(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

//impl<'a, P, S> IntoIterator for &'a mut Stream

// where P: StreamProducer,
//       S: Sample {
//  type Item     = S::Normal;
//  type IntoIter = Iter<'a, P, S>;
//
//  #[inline]
//  fn into_iter(self) -> Self::IntoIter {
//    self.iter()
//  }
//}
<commit_msg>Add unchecked array for the decode iterator<commit_after>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, Sample, SampleSize, StreamProducer,
  many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> Result<StreamReader<R>, ErrorKind> {
    let producer = ReadStream::new(reader);

    Stream::from_stream_producer(producer)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::IO(io::ErrorKind::NotFound)` is returned when the given
  ///   filename isn't found.
  /// * `ErrorKind::IO(io::ErrorKind::InvalidData)` is returned when the data
  ///   within the file isn't valid FLAC data.
  /// * Several different parser specific errors that are structured as
  ///   `ErrorKind::<parser_name>Parser`.
  /// * Several different invalidation specific errors that are
  ///   structured as `ErrorKind::Invalid<invalidation_name>`.
  #[inline]
  pub fn from_file(filename: &str) -> Result<StreamReader<File>, ErrorKind> {
    File::open(filename).map_err(|e| ErrorKind::IO(e.kind()))
                        .and_then(|file| {
      let producer = ReadStream::new(file);

      Stream::from_stream_producer(producer)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::IO(io::ErrorKind::InvalidData)` is returned when the data
  ///   within the file isn't valid FLAC data.
  /// * Several different parser specific errors that are structured as
  ///   `ErrorKind::<parser_name>Parser`.
  /// * Several different invalidation specific errors that are
  ///   structured as `ErrorKind::Invalid<invalidation_name>`.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> Result<StreamBuffer, ErrorKind> {
    let producer = ByteStream::new(buffer);

    Stream::from_stream_producer(producer)
  }

  fn from_stream_producer(mut producer: P) -> Result<Self, ErrorKind> {
    let mut stream_info = Default::default();
    let mut metadata    = Vec::new();

    many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    }).map(|_| {
      Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
      }
    })
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter<S: SampleSize>(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;
    let channels     = self.info.channels as usize;
    let block_size   = self.info.max_block_size as usize;
    let buffer_size  = block_size * channels;

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
      buffer: vec![S::Extended::from_i8(0); buffer_size]
    }
  }

  fn next_frame<S>(&mut self, buffer: &mut [S]) -> Option<usize>
   where S: Sample {
    let stream_info = &self.info;

    loop {
      match self.producer.parse(|i| frame_parser(i, stream_info, buffer)) {
        Ok(frame)                => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut buffer[start..end];

            subframe::decode(&subframe, block_size, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, buffer);

          return Some(block_size);
        }
        Err(ErrorKind::Continue) => continue,
        Err(_)                   => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P, S>
 where P: 'a + StreamProducer,
       S: Sample{
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
  buffer: Vec<S>,
}

impl<'a, P, S> Iterator for Iter<'a, P, S>
 where P: StreamProducer,
       S: Sample {
  type Item = S::Normal;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      let buffer = &mut self.buffer;

      if let Some(block_size) = self.stream.next_frame(buffer) {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = unsafe { *self.buffer.get_unchecked(index) };

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    S::to_normal(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

//impl<'a, P, S> IntoIterator for &'a mut Stream

// where P: StreamProducer,
//       S: Sample {
//  type Item     = S::Normal;
//  type IntoIter = Iter<'a, P, S>;
//
//  #[inline]
//  fn into_iter(self) -> Self::IntoIter {
//    self.iter()
//  }
//}
<|endoftext|>