<commit_before>#[macro_use]
extern crate cnx;
extern crate env_logger;
#[macro_use]
extern crate error_chain;
extern crate log;

use std::env;

use env_logger::Builder;
use log::LevelFilter;

use cnx::text::*;
use cnx::widgets::*;
use cnx::*;

mod errors {
    error_chain! {
        links {
            Cnx(::cnx::errors::Error, ::cnx::errors::ErrorKind);
        }
        foreign_links {
            SetLogger(::log::SetLoggerError);
        }
    }
}

fn init_log() -> errors::Result<()> {
    let mut builder = Builder::new();
    builder.filter(Some("cnx"), LevelFilter::Trace);
    if let Ok(rust_log) = env::var("RUST_LOG") {
        builder.parse(&rust_log);
    }
    builder.try_init()?;
    Ok(())
}

fn main() -> errors::Result<()> {
    init_log()?;

    let attr = Attributes {
        font: Font::new("SourceCodePro 21"),
        fg_color: Color::white(),
        bg_color: None,
        padding: Padding::new(8.0, 8.0, 0.0, 0.0),
    };
    let mut active_attr = attr.clone();
    active_attr.bg_color = Some(Color::blue());

    let mut cnx = Cnx::new(Position::Bottom)?;

    cnx_add_widget!(cnx, Pager::new(&cnx, active_attr, attr.clone()));
    cnx_add_widget!(cnx, ActiveWindowTitle::new(&cnx, attr.clone()));
    cnx_add_widget!(
        cnx,
        Sensors::new(&cnx, attr.clone(), vec!["Core 0", "Core 1"])
    );
    #[cfg(feature = "volume-widget")]
    cnx_add_widget!(cnx, Volume::new(&cnx, attr.clone()));
    cnx_add_widget!(cnx, Battery::new(&cnx, attr.clone(), Color::red()));
    cnx_add_widget!(cnx, Clock::new(&cnx, attr.clone()));

    cnx.run()?;

    Ok(())
}
<commit_msg>Default bar to top, for easy debugging.<commit_after>#[macro_use]
extern crate cnx;
extern crate env_logger;
#[macro_use]
extern crate error_chain;
extern crate log;

use std::env;

use env_logger::Builder;
use log::LevelFilter;

use cnx::text::*;
use cnx::widgets::*;
use cnx::*;

mod errors {
    error_chain! {
        links {
            Cnx(::cnx::errors::Error, ::cnx::errors::ErrorKind);
        }
        foreign_links {
            SetLogger(::log::SetLoggerError);
        }
    }
}

fn init_log() -> errors::Result<()> {
    let mut builder = Builder::new();
    builder.filter(Some("cnx"), LevelFilter::Trace);
    if let Ok(rust_log) = env::var("RUST_LOG") {
        builder.parse(&rust_log);
    }
    builder.try_init()?;
    Ok(())
}

fn main() -> errors::Result<()> {
    init_log()?;

    let attr = Attributes {
        font: Font::new("SourceCodePro 21"),
        fg_color: Color::white(),
        bg_color: None,
        padding: Padding::new(8.0, 8.0, 0.0, 0.0),
    };
    let mut active_attr = attr.clone();
    active_attr.bg_color = Some(Color::blue());

    let mut cnx = Cnx::new(Position::Top)?;

    cnx_add_widget!(cnx, Pager::new(&cnx, active_attr, attr.clone()));
    cnx_add_widget!(cnx, ActiveWindowTitle::new(&cnx, attr.clone()));
    cnx_add_widget!(
        cnx,
        Sensors::new(&cnx, attr.clone(), vec!["Core 0", "Core 1"])
    );
    #[cfg(feature = "volume-widget")]
    cnx_add_widget!(cnx, Volume::new(&cnx, attr.clone()));
    cnx_add_widget!(cnx, Battery::new(&cnx, attr.clone(), Color::red()));
    cnx_add_widget!(cnx, Clock::new(&cnx, attr.clone()));

    cnx.run()?;

    Ok(())
}
<|endoftext|>


<commit_before>//! History API

#[cfg(unix)]
use libc;
use std::collections::vec_deque;
use std::collections::VecDeque;
use std::fs::File;
use std::iter::DoubleEndedIterator;
use std::ops::Index;
use std::path::Path;

use super::Result;
use crate::config::{Config, HistoryDuplicates};

/// Search direction
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {
    Forward,
    Reverse,
}

/// Current state of the history.
#[derive(Default)]
pub struct History {
    entries: VecDeque<String>,
    max_len: usize,
    pub(crate) ignore_space: bool,
    pub(crate) ignore_dups: bool,
}

impl History {
    pub fn new() -> Self {
        Self::with_config(Config::default())
    }

    pub fn with_config(config: Config) -> Self {
        Self {
            entries: VecDeque::new(),
            max_len: config.max_history_size(),
            ignore_space: config.history_ignore_space(),
            ignore_dups: config.history_duplicates() == HistoryDuplicates::IgnoreConsecutive,
        }
    }

    /// Return the history entry at position `index`, starting from 0.
    pub fn get(&self, index: usize) -> Option<&String> {
        self.entries.get(index)
    }

    /// Return the last history entry (i.e. previous command)
    pub fn last(&self) -> Option<&String> {
        self.entries.back()
    }

    /// Add a new entry in the history.
    pub fn add<S: AsRef<str> + Into<String>>(&mut self, line: S) -> bool {
        if self.max_len == 0 {
            return false;
        }
        if line.as_ref().is_empty()
            || (self.ignore_space
                && line
                    .as_ref()
                    .chars()
                    .next()
                    .map_or(true, char::is_whitespace))
        {
            return false;
        }
        if self.ignore_dups {
            if let Some(s) = self.entries.back() {
                if s == line.as_ref() {
                    return false;
                }
            }
        }
        if self.entries.len() == self.max_len {
            self.entries.pop_front();
        }
        self.entries.push_back(line.into());
        true
    }

    /// Return the number of entries in the history.
    pub fn len(&self) -> usize {
        self.entries.len()
    }

    /// Return true if the history has no entry.
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    /// Set the maximum length for the history. This function can be called even
    /// if there is already some history, the function will make sure to retain
    /// just the latest `len` elements if the new history length value is
    /// smaller than the amount of items already inside the history.
    ///
    /// Like [stifle_history](http://cnswww.cns.cwru.
    /// edu/php/chet/readline/history.html#IDX11).
    pub fn set_max_len(&mut self, len: usize) {
        self.max_len = len;
        if len == 0 {
            self.entries.clear();
            return;
        }
        loop {
            if self.entries.len() <= len {
                break;
            }
            self.entries.pop_front();
        }
    }

    /// Save the history in the specified file.
    // TODO append_history
    // http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX30
    // TODO history_truncate_file
    // http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX31
    pub fn save<P: AsRef<Path> + ?Sized>(&self, path: &P) -> Result<()> {
        use std::io::{BufWriter, Write};

        if self.is_empty() {
            return Ok(());
        }
        let old_umask = umask();
        let f = File::create(path);
        restore_umask(old_umask);
        let file = f?;
        fix_perm(&file);
        let mut wtr = BufWriter::new(file);
        for entry in &self.entries {
            wtr.write_all(entry.as_bytes())?;
            wtr.write_all(b"\n")?;
        }
        // https://github.com/rust-lang/rust/issues/32677#issuecomment-204833485
        wtr.flush()?;
        Ok(())
    }

    /// Load the history from the specified file.
    ///
    /// # Errors
    /// Will return `Err` if path does not already exist or could not be read.
    pub fn load<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
        use std::io::{BufRead, BufReader};

        let file = File::open(&path)?;
        let rdr = BufReader::new(file);
        for line in rdr.lines() {
            self.add(line?); // TODO truncate to MAX_LINE
        }
        Ok(())
    }

    /// Clear history
    pub fn clear(&mut self) {
        self.entries.clear()
    }

    /// Search history (start position inclusive [0, len-1]).
    ///
    /// Return the absolute index of the nearest history entry that matches
    /// `term`.
    ///
    /// Return None if no entry contains `term` between [start, len -1] for
    /// forward search
    /// or between [0, start] for reverse search.
    pub fn search(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        let test = |entry: &String| entry.contains(term);
        self.search_match(term, start, dir, test)
    }

    /// Anchored search
    pub fn starts_with(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        let test = |entry: &String| entry.starts_with(term);
        self.search_match(term, start, dir, test)
    }

    fn search_match<F>(&self, term: &str, start: usize, dir: Direction, test: F) -> Option<usize>
    where
        F: Fn(&String) -> bool,
    {
        if term.is_empty() || start >= self.len() {
            return None;
        }
        match dir {
            Direction::Reverse => {
                let index = self
                    .entries
                    .iter()
                    .rev()
                    .skip(self.entries.len() - 1 - start)
                    .position(test);
                index.and_then(|index| Some(start - index))
            }
            Direction::Forward => {
                let index = self.entries.iter().skip(start).position(test);
                index.and_then(|index| Some(index + start))
            }
        }
    }

    /// Return a forward iterator.
    pub fn iter(&self) -> Iter<'_> {
        Iter(self.entries.iter())
    }
}

impl Index<usize> for History {
    type Output = String;

    fn index(&self, index: usize) -> &String {
        &self.entries[index]
    }
}

impl<'a> IntoIterator for &'a History {
    type IntoIter = Iter<'a>;
    type Item = &'a String;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// History iterator.
pub struct Iter<'a>(vec_deque::Iter<'a, String>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<&'a String> {
        self.0.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<&'a String> {
        self.0.next_back()
    }
}

#[cfg(windows)]
fn umask() -> u16 {
    0
}
#[cfg(unix)]
fn umask() -> libc::mode_t {
    unsafe { libc::umask(libc::S_IXUSR | libc::S_IRWXG | libc::S_IRWXO) }
}
#[cfg(windows)]
fn restore_umask(_: u16) {}
#[cfg(unix)]
fn restore_umask(old_umask: libc::mode_t) {
    unsafe {
        libc::umask(old_umask);
    }
}

#[cfg(windows)]
fn fix_perm(_: &File) {}
#[cfg(unix)]
fn fix_perm(file: &File) {
    use std::os::unix::io::AsRawFd;
    unsafe {
        libc::fchmod(file.as_raw_fd(), libc::S_IRUSR | libc::S_IWUSR);
    }
}

#[cfg(test)]
mod tests {
    use super::{Direction, History};
    use crate::config::Config;
    use std::path::Path;
    use tempdir;

    fn init() -> History {
        let mut history = History::new();
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(history.add("line3"));
        history
    }

    #[test]
    fn new() {
        let history = History::new();
        assert_eq!(0, history.entries.len());
    }

    #[test]
    fn add() {
        let config = Config::builder().history_ignore_space(true).build();
        let mut history = History::with_config(config);
        assert_eq!(config.max_history_size(), history.max_len);
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(!history.add("line2"));
        assert!(!history.add(""));
        assert!(!history.add(" line3"));
    }

    #[test]
    fn set_max_len() {
        let mut history = init();
        history.set_max_len(1);
        assert_eq!(1, history.entries.len());
        assert_eq!(Some(&"line3".to_owned()), history.last());
    }

    #[test]
    fn save() {
        let mut history = init();
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history");

        history.save(&history_path).unwrap();
        history.load(&history_path).unwrap();
        td.close().unwrap();
    }

    #[test]
    fn search() {
        let history = init();
        assert_eq!(None, history.search("", 0, Direction::Forward));
        assert_eq!(None, history.search("none", 0, Direction::Forward));
        assert_eq!(None, history.search("line", 3, Direction::Forward));

        assert_eq!(Some(0), history.search("line", 0, Direction::Forward));
        assert_eq!(Some(1), history.search("line", 1, Direction::Forward));
        assert_eq!(Some(2), history.search("line3", 1, Direction::Forward));
    }

    #[test]
    fn reverse_search() {
        let history = init();
        assert_eq!(None, history.search("", 2, Direction::Reverse));
        assert_eq!(None, history.search("none", 2, Direction::Reverse));
        assert_eq!(None, history.search("line", 3, Direction::Reverse));

        assert_eq!(Some(2), history.search("line", 2, Direction::Reverse));
        assert_eq!(Some(1), history.search("line", 1, Direction::Reverse));
        assert_eq!(Some(0), history.search("line1", 1, Direction::Reverse));
    }
}
<commit_msg>Fix clippy warnings<commit_after>//! History API

#[cfg(unix)]
use libc;
use std::collections::vec_deque;
use std::collections::VecDeque;
use std::fs::File;
use std::iter::DoubleEndedIterator;
use std::ops::Index;
use std::path::Path;

use super::Result;
use crate::config::{Config, HistoryDuplicates};

/// Search direction
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {
    Forward,
    Reverse,
}

/// Current state of the history.
#[derive(Default)]
pub struct History {
    entries: VecDeque<String>,
    max_len: usize,
    pub(crate) ignore_space: bool,
    pub(crate) ignore_dups: bool,
}

impl History {
    pub fn new() -> Self {
        Self::with_config(Config::default())
    }

    pub fn with_config(config: Config) -> Self {
        Self {
            entries: VecDeque::new(),
            max_len: config.max_history_size(),
            ignore_space: config.history_ignore_space(),
            ignore_dups: config.history_duplicates() == HistoryDuplicates::IgnoreConsecutive,
        }
    }

    /// Return the history entry at position `index`, starting from 0.
    pub fn get(&self, index: usize) -> Option<&String> {
        self.entries.get(index)
    }

    /// Return the last history entry (i.e. previous command)
    pub fn last(&self) -> Option<&String> {
        self.entries.back()
    }

    /// Add a new entry in the history.
    pub fn add<S: AsRef<str> + Into<String>>(&mut self, line: S) -> bool {
        if self.max_len == 0 {
            return false;
        }
        if line.as_ref().is_empty()
            || (self.ignore_space
                && line
                    .as_ref()
                    .chars()
                    .next()
                    .map_or(true, char::is_whitespace))
        {
            return false;
        }
        if self.ignore_dups {
            if let Some(s) = self.entries.back() {
                if s == line.as_ref() {
                    return false;
                }
            }
        }
        if self.entries.len() == self.max_len {
            self.entries.pop_front();
        }
        self.entries.push_back(line.into());
        true
    }

    /// Return the number of entries in the history.
    pub fn len(&self) -> usize {
        self.entries.len()
    }

    /// Return true if the history has no entry.
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    /// Set the maximum length for the history. This function can be called even
    /// if there is already some history, the function will make sure to retain
    /// just the latest `len` elements if the new history length value is
    /// smaller than the amount of items already inside the history.
    ///
    /// Like [stifle_history](http://cnswww.cns.cwru.
    /// edu/php/chet/readline/history.html#IDX11).
    pub fn set_max_len(&mut self, len: usize) {
        self.max_len = len;
        if len == 0 {
            self.entries.clear();
            return;
        }
        loop {
            if self.entries.len() <= len {
                break;
            }
            self.entries.pop_front();
        }
    }

    /// Save the history in the specified file.
    // TODO append_history
    // http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX30
    // TODO history_truncate_file
    // http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX31
    pub fn save<P: AsRef<Path> + ?Sized>(&self, path: &P) -> Result<()> {
        use std::io::{BufWriter, Write};

        if self.is_empty() {
            return Ok(());
        }
        let old_umask = umask();
        let f = File::create(path);
        restore_umask(old_umask);
        let file = f?;
        fix_perm(&file);
        let mut wtr = BufWriter::new(file);
        for entry in &self.entries {
            wtr.write_all(entry.as_bytes())?;
            wtr.write_all(b"\n")?;
        }
        // https://github.com/rust-lang/rust/issues/32677#issuecomment-204833485
        wtr.flush()?;
        Ok(())
    }

    /// Load the history from the specified file.
    ///
    /// # Errors
    /// Will return `Err` if path does not already exist or could not be read.
    pub fn load<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
        use std::io::{BufRead, BufReader};

        let file = File::open(&path)?;
        let rdr = BufReader::new(file);
        for line in rdr.lines() {
            self.add(line?); // TODO truncate to MAX_LINE
        }
        Ok(())
    }

    /// Clear history
    pub fn clear(&mut self) {
        self.entries.clear()
    }

    /// Search history (start position inclusive [0, len-1]).
    ///
    /// Return the absolute index of the nearest history entry that matches
    /// `term`.
    ///
    /// Return None if no entry contains `term` between [start, len -1] for
    /// forward search
    /// or between [0, start] for reverse search.
    pub fn search(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        let test = |entry: &String| entry.contains(term);
        self.search_match(term, start, dir, test)
    }

    /// Anchored search
    pub fn starts_with(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        let test = |entry: &String| entry.starts_with(term);
        self.search_match(term, start, dir, test)
    }

    fn search_match<F>(&self, term: &str, start: usize, dir: Direction, test: F) -> Option<usize>
    where
        F: Fn(&String) -> bool,
    {
        if term.is_empty() || start >= self.len() {
            return None;
        }
        match dir {
            Direction::Reverse => {
                let index = self
                    .entries
                    .iter()
                    .rev()
                    .skip(self.entries.len() - 1 - start)
                    .position(test);
                index.map(|index| start - index)
            }
            Direction::Forward => {
                let index = self.entries.iter().skip(start).position(test);
                index.map(|index| index + start)
            }
        }
    }

    /// Return a forward iterator.
    pub fn iter(&self) -> Iter<'_> {
        Iter(self.entries.iter())
    }
}

impl Index<usize> for History {
    type Output = String;

    fn index(&self, index: usize) -> &String {
        &self.entries[index]
    }
}

impl<'a> IntoIterator for &'a History {
    type IntoIter = Iter<'a>;
    type Item = &'a String;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// History iterator.
pub struct Iter<'a>(vec_deque::Iter<'a, String>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<&'a String> {
        self.0.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<&'a String> {
        self.0.next_back()
    }
}

#[cfg(windows)]
fn umask() -> u16 {
    0
}
#[cfg(unix)]
fn umask() -> libc::mode_t {
    unsafe { libc::umask(libc::S_IXUSR | libc::S_IRWXG | libc::S_IRWXO) }
}
#[cfg(windows)]
fn restore_umask(_: u16) {}
#[cfg(unix)]
fn restore_umask(old_umask: libc::mode_t) {
    unsafe {
        libc::umask(old_umask);
    }
}

#[cfg(windows)]
fn fix_perm(_: &File) {}
#[cfg(unix)]
fn fix_perm(file: &File) {
    use std::os::unix::io::AsRawFd;
    unsafe {
        libc::fchmod(file.as_raw_fd(), libc::S_IRUSR | libc::S_IWUSR);
    }
}

#[cfg(test)]
mod tests {
    use super::{Direction, History};
    use crate::config::Config;
    use std::path::Path;
    use tempdir;

    fn init() -> History {
        let mut history = History::new();
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(history.add("line3"));
        history
    }

    #[test]
    fn new() {
        let history = History::new();
        assert_eq!(0, history.entries.len());
    }

    #[test]
    fn add() {
        let config = Config::builder().history_ignore_space(true).build();
        let mut history = History::with_config(config);
        assert_eq!(config.max_history_size(), history.max_len);
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(!history.add("line2"));
        assert!(!history.add(""));
        assert!(!history.add(" line3"));
    }

    #[test]
    fn set_max_len() {
        let mut history = init();
        history.set_max_len(1);
        assert_eq!(1, history.entries.len());
        assert_eq!(Some(&"line3".to_owned()), history.last());
    }

    #[test]
    fn save() {
        let mut history = init();
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history");

        history.save(&history_path).unwrap();
        history.load(&history_path).unwrap();
        td.close().unwrap();
    }

    #[test]
    fn search() {
        let history = init();
        assert_eq!(None, history.search("", 0, Direction::Forward));
        assert_eq!(None, history.search("none", 0, Direction::Forward));
        assert_eq!(None, history.search("line", 3, Direction::Forward));

        assert_eq!(Some(0), history.search("line", 0, Direction::Forward));
        assert_eq!(Some(1), history.search("line", 1, Direction::Forward));
        assert_eq!(Some(2), history.search("line3", 1, Direction::Forward));
    }

    #[test]
    fn reverse_search() {
        let history = init();
        assert_eq!(None, history.search("", 2, Direction::Reverse));
        assert_eq!(None, history.search("none", 2, Direction::Reverse));
        assert_eq!(None, history.search("line", 3, Direction::Reverse));

        assert_eq!(Some(2), history.search("line", 2, Direction::Reverse));
        assert_eq!(Some(1), history.search("line", 1, Direction::Reverse));
        assert_eq!(Some(0), history.search("line1", 1, Direction::Reverse));
    }
}
<|endoftext|>


<commit_before><commit_msg>:shirt: Comment out unused functions<commit_after><|endoftext|>


<commit_before><commit_msg>src/addressbook: cargo fmt expects documentation<commit_after><|endoftext|>


<commit_before><commit_msg>Implement apple_music client<commit_after>use scraping::{Html, Selector};
use scraping::element_ref::ElementRef;
use hyper::Client;
use hyper::header::Connection;
use hyper::header::ConnectionOption;
use std::io::Read;
use std::error;
use std::fmt;
use regex::Regex;

static BASE_URL:  &'static str = "http://tools.applemusic.com/embed/v1/";
static MUSIC_URL: &'static str = r#"musicUrl = "([\x00-\x21\x23-\x7F]+)""#; // except \x22(")

#[derive(Debug)]
pub struct Song {
    pub id:          String,
    pub country:     String,
    pub title:       String,
    pub artwork_url: String,
    pub artist:      String,
    pub audio_url:   String,
    pub music_url:   String,
}

#[derive(Debug)]
pub struct Album {
    pub id:           String,
    pub country:      String,
    pub title:        String,
    pub artwork_url:  String,
    pub album_artist: String,
    pub music_url:    String,
    pub genre:        String,
}

#[derive(Debug)]
pub struct Playlist {
    pub id:          String,
    pub country:     String,
    pub title:       String,
    pub curator:     String,
    pub description: String,
    pub artwork_url: String,
    pub music_url:   String,
    pub count:       String,
}

#[derive(Debug)]
pub struct Track {
    pub title:       String,
    pub artwork_url: String,
    pub artist:      String,
    pub audio_url:   String,
}

#[derive(Debug)]
pub struct ScrapeError {
    reason: String,
}

impl fmt::Display for ScrapeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.reason)
    }
}

type ScrapeResult<T> = Result<T, ScrapeError>;

impl error::Error for ScrapeError {
    fn description(&self) -> &str {
        &self.reason
    }
}

pub fn fetch_song(id: &str, country: &str) -> ScrapeResult<Song> {
    let client = Client::new();
    let url = format!("{}/song/{}?country={}", BASE_URL, id, country);
    let mut res = client.get(&url)
        .header(Connection(vec![ConnectionOption::Close]))
        .send()
        .unwrap();
    if !res.status.is_success() {
        return Err(ScrapeError { reason: "network error".to_string() })
    }
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    let fragment = Html::parse_fragment(&body);

    let artwork_url = try!(extract_artwork_url(fragment.clone()));
    let title       = try!(extract_song_title(fragment.clone()));
    let artist      = try!(extract_song_artist(fragment.clone()));
    let audio_url   = try!(extract_audio_url(fragment.clone()));
    let music_url   = try!(extract_music_url(fragment.clone()));
    Ok(Song {
        id:          id.to_string(),
        country:     country.to_string(),
        title:       title,
        artist:      artist,
        artwork_url: artwork_url,
        audio_url:   audio_url,
        music_url:   music_url,
    })
}

pub fn fetch_album(id: &str, country: &str) -> ScrapeResult<Album> {
    let client = Client::new();
    let url = format!("{}/album/{}?country={}", BASE_URL, id, country);
    let mut res = client.get(&url)
        .header(Connection(vec![ConnectionOption::Close]))
        .send()
        .unwrap();
    if !res.status.is_success() {
        return Err(ScrapeError { reason: "network error".to_string() })
    }
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    let fragment = Html::parse_fragment(&body);

    let artwork_url  = try!(extract_artwork_url(fragment.clone()));
    let title        = try!(extract_title(fragment.clone()));
    let album_artist = try!(extract_album_artist(fragment.clone()));
    let count        = try!(extract_count(fragment.clone()));
    let music_url    = try!(extract_music_url(fragment.clone()));
    let mut tracks   = Vec::new();
    let tracks_selector = Selector::parse(".track").unwrap();
    for node in fragment.select(&tracks_selector) {
        tracks.push(extract_track(node));
    }
    Ok(Album {
        id:           id.to_string(),
        country:      country.to_string(),
        title:        title,
        album_artist: album_artist,
        artwork_url:  artwork_url,
        music_url:    music_url,
        genre:        count,
    })
}

pub fn fetch_playlist(id: &str, country: &str) -> ScrapeResult<Playlist> {
    let client = Client::new();
    let url = format!("{}/playlist/{}?country={}", BASE_URL, id, country);
    let mut res = client.get(&url)
        .header(Connection(vec![ConnectionOption::Close]))
        .send()
        .unwrap();
    if !res.status.is_success() {
        return Err(ScrapeError { reason: "network error".to_string() })
    }
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    let fragment = Html::parse_fragment(&body);

    let artwork_url = try!(extract_artwork_url(fragment.clone()));
    let title       = try!(extract_title(fragment.clone()));
    let description = try!(extract_description(fragment.clone()));
    let curator     = try!(extract_curator(fragment.clone()));
    let count       = try!(extract_count(fragment.clone()));
    let music_url   = try!(extract_music_url(fragment.clone()));
    let mut tracks  = Vec::new();
    let tracks_selector = Selector::parse(".track").unwrap();
    for node in fragment.select(&tracks_selector) {
        let track = extract_track(node);
        tracks.push(track);
    }
    Ok(Playlist {
        id:          id.to_string(),
        country:     country.to_string(),
        title:       title,
        curator:     curator,
        description: description,
        artwork_url: artwork_url,
        music_url:   music_url,
        count:       count,
    })
}

fn extract_music_url(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse("script").unwrap();
    html.select(&selector)
        .last()
        .and_then(|img| img.text().next())
        .and_then(|script| match Regex::new(MUSIC_URL) {
            Ok(re) => match re.captures(script) {
                Some(cap) => Some(cap[1].to_string()),
                None => None
            },
            Err(_) => None
        })
        .ok_or(ScrapeError { reason: "music url is not found".to_string() })
}

fn extract_artwork_url(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse("#heroArtImage > img").unwrap();
    html.select(&selector)
        .next()
        .and_then(|img| img.value().attr("src"))
        .map(|url| url.trim().to_string())
        .ok_or(ScrapeError { reason: "artwork url is not found".to_string() })
}

fn extract_audio_url(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse("#heroArtImage > .song-audio").unwrap();
    html.select(&selector)
        .next()
        .and_then(|img| img.value().attr("data-url"))
        .map(|url| url.trim().to_string())
        .ok_or(ScrapeError { reason: "audio url is not found".to_string() })
}

fn extract_description(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse("#description").unwrap();
    html.select(&selector)
        .next()
        .and_then(|div| div.text().next())
        .map(|text| text.trim().to_string())
        .ok_or(ScrapeError { reason: "description is not found".to_string() })
}

fn extract_title(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse(".heroMeta > .title > a").unwrap();
    html.select(&selector)
        .next()
        .and_then(|a| a.text().next())
        .map(|text| text.trim().to_string())
        .ok_or(ScrapeError { reason: "title is not found".to_string() })
}

fn extract_song_title(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse(".heroMeta > .details > .title-explicit > .title > a").unwrap();
    html.select(&selector)
        .next()
        .and_then(|a| a.text().next())
        .map(|text| text.trim().to_string())
        .ok_or(ScrapeError { reason: "title is not found".to_string() })
}

fn extract_curator(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse(".heroMeta > .curator > a").unwrap();
    html.select(&selector)
        .next()
        .and_then(|a| a.text().next())
        .map(|text| text.trim().to_string())
        .ok_or(ScrapeError { reason: "curator is not found".to_string() })
}

fn extract_album_artist(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse(".heroMeta > .album-artist > a").unwrap();
    html.select(&selector)
        .next()
        .and_then(|a| a.text().next())
        .map(|text| text.trim().to_string())
        .ok_or(ScrapeError { reason: "album artist is not found".to_string() })
}

fn extract_song_artist(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse(".heroMeta > .details > .song-artist > a").unwrap();
    html.select(&selector)
        .next()
        .and_then(|a| a.text().next())
        .map(|text| text.trim().to_string())
        .ok_or(ScrapeError { reason: "song artist is not found".to_string() })
}

fn extract_count(html: Html) -> ScrapeResult<String> {
    let selector = Selector::parse(".heroMeta > .count").unwrap();
    html.select(&selector)
        .next()
        .and_then(|a| a.text().next())
        .map(|text| text.trim().to_string())
        .ok_or(ScrapeError { reason: "count is not found".to_string() })
}

fn extract_track(node: ElementRef) -> Track {
    let img_selector    = Selector::parse(".artworkImage > img").unwrap();
    let title_selector  = Selector::parse(".title").unwrap();
    let artist_selector = Selector::parse(".artist").unwrap();
    let audio_selector  = Selector::parse(".playlist-audio").unwrap();

    let mut title:       String = "".to_string();
    let mut artwork_url: String = "".to_string();
    let mut artist:      String = "".to_string();
    let mut audio_url:   String = "".to_string();
    if let Some(n) = node.select(&title_selector).next() {
        if let Some(text) = n.text().next() {
            title = text.trim().to_string();
        }
    }

    if let Some(n) = node.select(&artist_selector).next() {
        if let Some(text) = n.text().next() {
            artist = text.trim().to_string();
        }
    }

    if let Some(n) = node.select(&img_selector).next() {
        if let Some(url) = n.value().attr("src") {
            artwork_url = url.trim().to_string();
        }
    }

    if let Some(n) = node.select(&audio_selector).next() {
        if let Some(url) = n.value().attr("data-url") {
            audio_url = url.trim().to_string();
        }
    }

    Track {
        title:       title,
        artwork_url: artwork_url,
        artist:      artist,
        audio_url:   audio_url,
    }
}

#[cfg(test)]
mod test {
    use super::fetch_playlist;
    use super::fetch_album;
    use super::fetch_song;
    #[test]
    fn test_fetch_playlist() {
        let playlist = fetch_playlist("pl.2ff0e502db0c44a598a7cb2261a5e6b2", "jp").unwrap();
        assert_eq!(playlist.id, "pl.2ff0e502db0c44a598a7cb2261a5e6b2");
        assert_eq!(playlist.music_url, "https://itunes.apple.com/jp/playlist/lili-limit-ga-xuanbu-maipureirisuto/idpl.2ff0e502db0c44a598a7cb2261a5e6b2?app=music");
    }
    #[test]
    fn test_fetch_album() {
        let album = fetch_album("1160715126", "jp").unwrap();
        assert_eq!(album.id, "1160715126");
    }
    #[test]
    fn test_fetch_song() {
        let song = fetch_song("1160715431", "jp").unwrap();
        assert_eq!(song.id, "1160715431");
    }
}
<|endoftext|>


<commit_before><commit_msg>added tracechain tests<commit_after>extern crate rustyprefetch;
use rustyprefetch::librp::tracechain;
use rustyprefetch::librp::utils;

#[test]
fn tracechain_v17_test() {
    let v17_tracechain_buffer: &[u8] = &[
        0x01,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0xFA,0xFF,0x07,0x00
    ];

    let v17_tracechain_entry = match tracechain::TraceChainEntryV17::new(v17_tracechain_buffer){
        Ok(v17_tracechain_entry) => v17_tracechain_entry,
        Err(error) => panic!(error)
    };

    assert_eq!(v17_tracechain_entry.next_index, 1);
    assert_eq!(v17_tracechain_entry.block_load_count, 1024);
    assert_eq!(v17_tracechain_entry.unknown1, 250);
    assert_eq!(v17_tracechain_entry.unknown2, 255);
    assert_eq!(v17_tracechain_entry.unknown3, 7);
}

#[test]
fn tracechain_v26_test() {
    let v26_tracechain_buffer: &[u8] = &[
        0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x16,0x00
    ];

    let v26_tracechain_entry = match tracechain::TraceChainEntryV26::new(v26_tracechain_buffer){
        Ok(v26_tracechain_entry) => v26_tracechain_entry,
        Err(error) => panic!(error)
    };

    assert_eq!(v26_tracechain_entry.next_index, 1);
    assert_eq!(v26_tracechain_entry.block_load_count, 0);
    assert_eq!(v26_tracechain_entry.unknown1, 3);
    assert_eq!(v26_tracechain_entry.unknown2, 1);
    assert_eq!(v26_tracechain_entry.unknown3, 22);
}

#[test]
fn tracechain_v30_test() {
    let v30_tracechain_buffer: &[u8] = &[
        0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00
    ];

    let v30_tracechain_entry = match tracechain::TraceChainEntryV30::new(v30_tracechain_buffer){
        Ok(v30_tracechain_entry) => v30_tracechain_entry,
        Err(error) => panic!(error)
    };

    assert_eq!(v30_tracechain_entry.block_load_count, 0);
    assert_eq!(v30_tracechain_entry.unknown1,6);
    assert_eq!(v30_tracechain_entry.unknown2, 0);
    assert_eq!(v30_tracechain_entry.unknown3, 0);
}
<|endoftext|>


<commit_before><commit_msg>Add a TUI benchmark program<commit_after>// A program that initializes the TUI and adds lines in the file (given as first argument) to it,
// with a draw() call after every line added.
//
// After adding all lines the program just quits.
//
// Useful for benchmarking TUI::draw().

use libtiny_tui::{Colors, TUI};
use libtiny_ui::*;
use std::fs::File;
use std::io::{BufRead, BufReader};
use tokio::runtime::current_thread::Runtime;

fn main() {
    let args = std::env::args().collect::<Vec<_>>();
    let file_path = &args[1];
    let file = File::open(file_path).unwrap();
    let file_buffered = BufReader::new(file);
    let lines = file_buffered.lines().map(Result::unwrap).collect();

    let mut executor = Runtime::new().unwrap();
    let (tui, _) = TUI::run(Colors::default(), &mut executor);

    tui.new_server_tab("test");
    tui.draw();

    executor.block_on(bench_task(tui, lines));

    // executor.run();
}

async fn bench_task(tui: TUI, lines: Vec<String>) {
    let msg_target = MsgTarget::Server { serv: "test" };
    let time = time::now();

    for line in &lines {
        tui.add_privmsg("server", line, time, &msg_target, false, false);
        tui.draw();
    }
}
<|endoftext|>


<commit_before>use core::clone::Clone;
use core::mem::size_of;
use core::option::Option;

use alloc::boxed::*;

use common::debug::*;
use common::memory::*;
use common::random::*;
use common::string::*;
use common::vec::*;

use network::common::*;

#[derive(Copy, Clone)]
pub struct TCPHeader {
    pub src: n16,
    pub dst: n16,
    pub sequence: n32,
    pub ack_num: n32,
    pub flags: n16,
    pub window_size: n16,
    pub checksum: Checksum,
    pub urgent_pointer: n16
}

pub struct TCP {
    header: TCPHeader,
    options: Vec<u8>,
    data: Vec<u8>,
    src_ip: IPv4Addr,
    dst_ip: IPv4Addr
}

impl ToBytes for TCP {
    fn to_bytes(&self) -> Vec<u8> {
        unsafe{
            let header_ptr: *const TCPHeader = &self.header;
            let mut ret = Vec::from_raw_buf(header_ptr as *const u8, size_of::<TCPHeader>());
            ret.push_all(&self.options);
            ret.push_all(&self.data);
            return ret;
        }
    }
}

const TCP_FIN: u16 = 1;
const TCP_SYN: u16 = 1 << 1;
const TCP_RST: u16 = 1 << 2;
const TCP_PSH: u16 = 1 << 3;
const TCP_ACK: u16 = 1 << 4;

#[allow(trivial_casts)]
impl Response for TCP {
    fn respond(&self, callback: Box<FnBox(Vec<Vec<u8>>)>){
        if cfg!(debug_network){
            d("            ");
            self.d();
            dl();
        }

        let allow;
        match self.header.dst.get() {
            80 => allow = true,
            _ => allow = false
        }

        if allow {
            if self.header.flags.get() & TCP_SYN != 0 {
                if cfg!(debug_network){
                    d("            TCP SYN\n");
                }
                let mut response = TCP {
                    header: self.header,
                    options: self.options.clone(),
                    data: Vec::new(),
                    src_ip: IP_ADDR,
                    dst_ip: self.src_ip
                };

                response.header.src = self.header.dst;
                response.header.dst = self.header.src;
                response.header.flags.set(self.header.flags.get() | TCP_ACK);
                response.header.ack_num.set(self.header.sequence.get() + 1);
                response.header.sequence.set(rand() as u32);

                unsafe{
                    response.header.checksum.data = 0;

                    let proto = n16::new(0x06);
                    let segment_len = n16::new((size_of::<TCPHeader>() + response.options.len() + response.data.len()) as u16);
                    response.header.checksum.data = Checksum::compile(
                        Checksum::sum((&response.src_ip as *const IPv4Addr) as usize, size_of::<IPv4Addr>()) +
                        Checksum::sum((&response.dst_ip as *const IPv4Addr) as usize, size_of::<IPv4Addr>()) +
                        Checksum::sum((&proto as *const n16) as usize, size_of::<n16>()) +
                        Checksum::sum((&segment_len as *const n16) as usize, size_of::<n16>()) +
                        Checksum::sum((&response.header as *const TCPHeader) as usize, size_of::<TCPHeader>()) +
                        Checksum::sum(response.options.as_ptr() as usize, response.options.len()) +
                        Checksum::sum(response.data.as_ptr() as usize, response.data.len())
                    );
                }

                let mut ret: Vec<Vec<u8>> = Vec::new();
                ret.push(response.to_bytes());
                callback(ret);
            }else if self.header.flags.get() & TCP_PSH != 0{
                if cfg!(debug_network){
                    d("            TCP PSH\n");
                }
                //Send TCP_ACK_PSH_FIN in one statement
                {
                    let tcp_header = self.header;
                    let tcp_options = self.options.clone();
                    let tcp_dst_ip = self.src_ip;
                    let tcp_data = self.data.clone();
                    let tcp_callback = box move |data: String|{
                        let mut response = TCP {
                            header: tcp_header,
                            options: tcp_options.clone(),
                            data: Vec::new(),
                            src_ip: IP_ADDR,
                            dst_ip: tcp_dst_ip
                        };

                        response.header.src = tcp_header.dst;
                        response.header.dst = tcp_header.src;
                        response.header.flags.set(tcp_header.flags.get() | TCP_FIN);
                        response.header.ack_num.set(tcp_header.sequence.get() + tcp_data.len() as u32);
                        response.header.sequence.set(tcp_header.ack_num.get());

                        unsafe{
                            let data_ptr = data.to_c_str();
                            response.data = Vec::from_raw_buf(data_ptr, data.len());
                            unalloc(data_ptr as usize);
                        }

                        response.header.checksum.data = 0;

                        let proto = n16::new(0x06);
                        let segment_len = n16::new((size_of::<TCPHeader>() + response.options.len() + response.data.len()) as u16);
                        unsafe{
                            response.header.checksum.data = Checksum::compile(
                                Checksum::sum((&response.src_ip as *const IPv4Addr) as usize, size_of::<IPv4Addr>()) +
                                Checksum::sum((&response.dst_ip as *const IPv4Addr) as usize, size_of::<IPv4Addr>()) +
                                Checksum::sum((&proto as *const n16) as usize, size_of::<n16>()) +
                                Checksum::sum((&segment_len as *const n16) as usize, size_of::<n16>()) +
                                Checksum::sum((&response.header as *const TCPHeader) as usize, size_of::<TCPHeader>()) +
                                Checksum::sum(response.options.as_ptr() as usize, response.options.len()) +
                                Checksum::sum(response.data.as_ptr() as usize, response.data.len())
                            );
                        }

                        let mut ret: Vec<Vec<u8>> = Vec::new();
                        ret.push(response.to_bytes());
                        callback(ret);
                    };

                    match self.header.dst.get() {
                        80 => {
                            let request = String::from_c_slice(self.data.as_slice());

                            let mut path = "/".to_string();

                            for row in request.split("\r\n".to_string()) {
                                let mut i = 0;
                                for col in row.split(" ".to_string()) {
                                    match i {
                                        1 => path = col,
                                        _ => ()
                                    }
                                    i += 1;
                                }
                                break;
                            }

                            //session.request(&URL::from_string("http://".to_string() + path), tcp_callback);
                        },
                        _ => ()
                    }
                }
            }
        }else{
            d("            TCP RST TODO\n");
        }
    }
}

impl TCP {
    pub fn from_bytes_ipv4(bytes: Vec<u8>, src_ip: IPv4Addr, dst_ip: IPv4Addr) -> Option<TCP> {
        if bytes.len() >= size_of::<TCPHeader>() {
            unsafe {
                let header = *(bytes.as_ptr() as *const TCPHeader);
                let header_len = ((header.flags.get() & 0xF000) >> 10) as usize;

                return Option::Some(TCP {
                    header: header,
                    options: bytes.sub(size_of::<TCPHeader>(), header_len - size_of::<TCPHeader>()),
                    data: bytes.sub(header_len, bytes.len() - header_len),
                    src_ip: src_ip,
                    dst_ip: dst_ip
                });
            }
        }
        return Option::None;
    }

    pub fn d(&self){
        d("TCP from ");
        dd(self.header.src.get() as usize);
        d(" to ");
        dd(self.header.dst.get() as usize);
        d(" options ");
        dd(self.options.len());
        d(" data ");
        dd(self.data.len());
    }
}
<commit_msg>Allow HTTP response<commit_after>use core::clone::Clone;
use core::mem::size_of;
use core::option::Option;

use alloc::boxed::*;

use common::debug::*;
use common::memory::*;
use common::random::*;
use common::resource::*;
use common::string::*;
use common::vec::*;

use network::common::*;

#[derive(Copy, Clone)]
pub struct TCPHeader {
    pub src: n16,
    pub dst: n16,
    pub sequence: n32,
    pub ack_num: n32,
    pub flags: n16,
    pub window_size: n16,
    pub checksum: Checksum,
    pub urgent_pointer: n16
}

pub struct TCP {
    header: TCPHeader,
    options: Vec<u8>,
    data: Vec<u8>,
    src_ip: IPv4Addr,
    dst_ip: IPv4Addr
}

impl ToBytes for TCP {
    fn to_bytes(&self) -> Vec<u8> {
        unsafe{
            let header_ptr: *const TCPHeader = &self.header;
            let mut ret = Vec::from_raw_buf(header_ptr as *const u8, size_of::<TCPHeader>());
            ret.push_all(&self.options);
            ret.push_all(&self.data);
            return ret;
        }
    }
}

const TCP_FIN: u16 = 1;
const TCP_SYN: u16 = 1 << 1;
const TCP_RST: u16 = 1 << 2;
const TCP_PSH: u16 = 1 << 3;
const TCP_ACK: u16 = 1 << 4;

#[allow(trivial_casts)]
impl Response for TCP {
    fn respond(&self, callback: Box<FnBox(Vec<Vec<u8>>)>){
        if cfg!(debug_network){
            d("            ");
            self.d();
            dl();
        }

        let allow;
        match self.header.dst.get() {
            80 => allow = true,
            _ => allow = false
        }

        if allow {
            if self.header.flags.get() & TCP_SYN != 0 {
                if cfg!(debug_network){
                    d("            TCP SYN\n");
                }
                let mut response = TCP {
                    header: self.header,
                    options: self.options.clone(),
                    data: Vec::new(),
                    src_ip: IP_ADDR,
                    dst_ip: self.src_ip
                };

                response.header.src = self.header.dst;
                response.header.dst = self.header.src;
                response.header.flags.set(self.header.flags.get() | TCP_ACK);
                response.header.ack_num.set(self.header.sequence.get() + 1);
                response.header.sequence.set(rand() as u32);

                unsafe{
                    response.header.checksum.data = 0;

                    let proto = n16::new(0x06);
                    let segment_len = n16::new((size_of::<TCPHeader>() + response.options.len() + response.data.len()) as u16);
                    response.header.checksum.data = Checksum::compile(
                        Checksum::sum((&response.src_ip as *const IPv4Addr) as usize, size_of::<IPv4Addr>()) +
                        Checksum::sum((&response.dst_ip as *const IPv4Addr) as usize, size_of::<IPv4Addr>()) +
                        Checksum::sum((&proto as *const n16) as usize, size_of::<n16>()) +
                        Checksum::sum((&segment_len as *const n16) as usize, size_of::<n16>()) +
                        Checksum::sum((&response.header as *const TCPHeader) as usize, size_of::<TCPHeader>()) +
                        Checksum::sum(response.options.as_ptr() as usize, response.options.len()) +
                        Checksum::sum(response.data.as_ptr() as usize, response.data.len())
                    );
                }

                let mut ret: Vec<Vec<u8>> = Vec::new();
                ret.push(response.to_bytes());
                callback(ret);
            }else if self.header.flags.get() & TCP_PSH != 0{
                if cfg!(debug_network){
                    d("            TCP PSH\n");
                }
                //Send TCP_ACK_PSH_FIN in one statement
                {
                    match self.header.dst.get() {
                        80 => {
                            let request = String::from_c_slice(self.data.as_slice());

                            let mut path = "/".to_string();

                            for row in request.split("\r\n".to_string()) {
                                let mut i = 0;
                                for col in row.split(" ".to_string()) {
                                    match i {
                                        1 => path = col,
                                        _ => ()
                                    }
                                    i += 1;
                                }
                                break;
                            }

                            let tcp_header = self.header;
                            let tcp_options = self.options.clone();
                            let tcp_dst_ip = self.src_ip;
                            let tcp_data = self.data.clone();
                            URL::from_string("http://".to_string() + path).open_async(box move |mut resource: Box<Resource>|{
                                let mut vec: Vec<u8> = Vec::new();

                                match resource.read_to_end(&mut vec) {
                                    Option::Some(len) => (),
                                    Option::None => ()
                                }

                                let mut response = TCP {
                                    header: tcp_header,
                                    options: tcp_options.clone(),
                                    data: Vec::new(),
                                    src_ip: IP_ADDR,
                                    dst_ip: tcp_dst_ip
                                };

                                response.header.src = tcp_header.dst;
                                response.header.dst = tcp_header.src;
                                response.header.flags.set(tcp_header.flags.get() | TCP_FIN);
                                response.header.ack_num.set(tcp_header.sequence.get() + tcp_data.len() as u32);
                                response.header.sequence.set(tcp_header.ack_num.get());

                                response.data = vec;

                                response.header.checksum.data = 0;

                                let proto = n16::new(0x06);
                                let segment_len = n16::new((size_of::<TCPHeader>() + response.options.len() + response.data.len()) as u16);
                                unsafe{
                                    response.header.checksum.data = Checksum::compile(
                                        Checksum::sum((&response.src_ip as *const IPv4Addr) as usize, size_of::<IPv4Addr>()) +
                                        Checksum::sum((&response.dst_ip as *const IPv4Addr) as usize, size_of::<IPv4Addr>()) +
                                        Checksum::sum((&proto as *const n16) as usize, size_of::<n16>()) +
                                        Checksum::sum((&segment_len as *const n16) as usize, size_of::<n16>()) +
                                        Checksum::sum((&response.header as *const TCPHeader) as usize, size_of::<TCPHeader>()) +
                                        Checksum::sum(response.options.as_ptr() as usize, response.options.len()) +
                                        Checksum::sum(response.data.as_ptr() as usize, response.data.len())
                                    );
                                }

                                let mut ret: Vec<Vec<u8>> = Vec::new();
                                ret.push(response.to_bytes());
                                callback(ret);
                            });
                        },
                        _ => ()
                    }
                }
            }
        }else{
            d("            TCP RST TODO\n");
        }
    }
}

impl TCP {
    pub fn from_bytes_ipv4(bytes: Vec<u8>, src_ip: IPv4Addr, dst_ip: IPv4Addr) -> Option<TCP> {
        if bytes.len() >= size_of::<TCPHeader>() {
            unsafe {
                let header = *(bytes.as_ptr() as *const TCPHeader);
                let header_len = ((header.flags.get() & 0xF000) >> 10) as usize;

                return Option::Some(TCP {
                    header: header,
                    options: bytes.sub(size_of::<TCPHeader>(), header_len - size_of::<TCPHeader>()),
                    data: bytes.sub(header_len, bytes.len() - header_len),
                    src_ip: src_ip,
                    dst_ip: dst_ip
                });
            }
        }
        return Option::None;
    }

    pub fn d(&self){
        d("TCP from ");
        dd(self.header.src.get() as usize);
        d(" to ");
        dd(self.header.dst.get() as usize);
        d(" options ");
        dd(self.options.len());
        d(" data ");
        dd(self.data.len());
    }
}
<|endoftext|>


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

//! Command Buffer device interface

use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::collections::hash_set::{self, HashSet};
use {Backend, Resources, IndexType, InstanceCount, VertexCount,
     SubmissionResult, SubmissionError};
use {state, target, pso, shade, texture, handle};

/// A universal clear color supporting integet formats
/// as well as the standard floating-point.
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum ClearColor {
    /// Standard floating-point vec4 color
    Float([f32; 4]),
    /// Integer vector to clear ivec4 targets.
    Int([i32; 4]),
    /// Unsigned int vector to clear uvec4 targets.
    Uint([u32; 4]),
}

/// Optional instance parameters: (instance count, buffer offset)
pub type InstanceParams = (InstanceCount, VertexCount);

/// Thread-safe finished command buffer for submission.
pub struct Submit<B: Backend>(B::SubmitInfo);
impl<B: Backend> Submit<B> {
    #[doc(hidden)]
    pub unsafe fn get_info(&self) -> &B::SubmitInfo {
        &self.0
    }
}

/// Encoder for a command buffer.
///
/// Pools will always return an Encoder on `acquire_command_buffer` to provide a safe interface.
#[derive(Debug)]
pub struct Encoder<B: Backend, C: CommandBuffer<B>>(C, PhantomData<B>);

impl<B, C> Deref for Encoder<B, C>
    where B: Backend, C: CommandBuffer<B>
{
    type Target = C;
    fn deref(&self) -> &C {
        &self.0
    }
}

impl<B, C> DerefMut for Encoder<B, C>
    where B: Backend, C: CommandBuffer<B>
{
    fn deref_mut(&mut self) -> &mut C {
        &mut self.0
    }
}

impl<B, C> Encoder<B, C>
    where B: Backend, C: CommandBuffer<B>
{
    #[doc(hidden)]
    pub unsafe fn new(buffer: C) -> Self {
        Encoder(buffer, PhantomData)
    }

    /// Finish recording commands to the command buffers.
    ///
    /// The command buffer will be consumed and can't be modified further.
    /// The command pool must be reset to re-record the command buffer.
    pub fn finish(mut self) -> Submit<B> {
        Submit(unsafe { self.0.end() })
    }
}

/// Base trait for all CommandBuffers
pub trait CommandBuffer<B: Backend> {
    #[doc(hidden)]
    unsafe fn end(&mut self) -> B::SubmitInfo;
}

/// Command buffer with graphics, compute and transfer functionality.
pub struct GeneralCommandBuffer<'a, B: Backend>(pub(crate) &'a mut B::RawCommandBuffer)
where B::RawCommandBuffer: 'a;

impl<'a, B: Backend> CommandBuffer<B> for GeneralCommandBuffer<'a, B> {
    unsafe fn end(&mut self) -> B::SubmitInfo {
        self.0.end()
    }
}

// TODO: temporary derefs, remove once command buffers will be reworked
impl<'a, B: Backend> Deref for GeneralCommandBuffer<'a, B> {
    type Target = B::RawCommandBuffer;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a, B: Backend> DerefMut for GeneralCommandBuffer<'a, B> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

/// Command buffer with graphics and transfer functionality.
pub struct GraphicsCommandBuffer<'a, B: Backend>(pub(crate) &'a mut B::RawCommandBuffer)
where B::RawCommandBuffer: 'a;

impl<'a, B: Backend> CommandBuffer<B> for GraphicsCommandBuffer<'a, B> {
    unsafe fn end(&mut self) -> B::SubmitInfo {
        self.0.end()
    }
}

// TODO: temporary derefs, remove once command buffers will be reworked
impl<'a, B: Backend> Deref for GraphicsCommandBuffer<'a, B> {
    type Target = B::RawCommandBuffer;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a, B: Backend> DerefMut for GraphicsCommandBuffer<'a, B> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

/// Command buffer with compute and transfer functionality.
pub struct ComputeCommandBuffer<'a, B: Backend>(pub(crate) &'a mut B::RawCommandBuffer)
where B::RawCommandBuffer: 'a;

impl<'a, B: Backend> CommandBuffer<B> for ComputeCommandBuffer<'a, B> {
    unsafe fn end(&mut self) -> B::SubmitInfo {
        self.0.end()
    }
}

/// Command buffer with transfer functionality.
pub struct TransferCommandBuffer<'a, B: Backend>(pub(crate) &'a mut B::RawCommandBuffer)
where B::RawCommandBuffer: 'a;

impl<'a, B: Backend> CommandBuffer<B> for TransferCommandBuffer<'a, B> {
    unsafe fn end(&mut self) -> B::SubmitInfo {
        self.0.end()
    }
}
/// An interface of the abstract command buffer. It collects commands in an
/// efficient API-specific manner, to be ready for execution on the device.
#[allow(missing_docs)]
pub trait Buffer<R: Resources>: 'static + Send {
    /// Reset the command buffer contents, retain the allocated storage
    fn reset(&mut self);
    /// Bind a pipeline state object
    fn bind_pipeline_state(&mut self, R::PipelineStateObject);
    /// Bind a complete set of vertex buffers
    fn bind_vertex_buffers(&mut self, pso::VertexBufferSet<R>);
    /// Bind a complete set of constant buffers
    fn bind_constant_buffers(&mut self, &[pso::ConstantBufferParam<R>]);
    /// Bind a global constant
    fn bind_global_constant(&mut self, shade::Location, shade::UniformValue);
    /// Bind a complete set of shader resource views
    fn bind_resource_views(&mut self, &[pso::ResourceViewParam<R>]);
    /// Bind a complete set of unordered access views
    fn bind_unordered_views(&mut self, &[pso::UnorderedViewParam<R>]);
    /// Bind a complete set of samplers
    fn bind_samplers(&mut self, &[pso::SamplerParam<R>]);
    /// Bind a complete set of pixel targets, including multiple
    /// colors views and an optional depth/stencil view.
    fn bind_pixel_targets(&mut self, pso::PixelTargetSet<R>);
    /// Bind an index buffer
    fn bind_index(&mut self, R::Buffer, IndexType);
    /// Set scissor rectangle
    fn set_scissor(&mut self, target::Rect);
    /// Set reference values for the blending and stencil front/back
    fn set_ref_values(&mut self, state::RefValues);
    /// Copy part of a buffer to another
    fn copy_buffer(&mut self, src: R::Buffer, dst: R::Buffer,
                   src_offset_bytes: usize, dst_offset_bytes: usize,
                   size_bytes: usize);
    /// Copy part of a buffer to a texture
    fn copy_buffer_to_texture(&mut self,
                              src: R::Buffer, src_offset_bytes: usize,
                              dst: R::Texture, texture::Kind,
                              Option<texture::CubeFace>, texture::RawImageInfo);
    /// Copy part of a texture to a buffer
    fn copy_texture_to_buffer(&mut self,
                              src: R::Texture, texture::Kind,
                              Option<texture::CubeFace>, texture::RawImageInfo,
                              dst: R::Buffer, dst_offset_bytes: usize);
    /// Update a vertex/index/uniform buffer
    fn update_buffer(&mut self, R::Buffer, data: &[u8], offset: usize);
    /// Update a texture
    fn update_texture(&mut self, R::Texture, texture::Kind, Option<texture::CubeFace>,
                      data: &[u8], texture::RawImageInfo);
    fn generate_mipmap(&mut self, R::ShaderResourceView);
    /// Clear color target
    fn clear_color(&mut self, R::RenderTargetView, ClearColor);
    fn clear_depth_stencil(&mut self, R::DepthStencilView,
                           Option<target::Depth>, Option<target::Stencil>);
    /// Draw a primitive
    fn call_draw(&mut self, VertexCount, VertexCount, Option<InstanceParams>);
    /// Draw a primitive with index buffer
    fn call_draw_indexed(&mut self, VertexCount, VertexCount, VertexCount, Option<InstanceParams>);
}

macro_rules! impl_clear {
    { $( $ty:ty = $sub:ident[$a:expr, $b:expr, $c:expr, $d:expr], )* } => {
        $(
            impl From<$ty> for ClearColor {
                fn from(v: $ty) -> ClearColor {
                    ClearColor::$sub([v[$a], v[$b], v[$c], v[$d]])
                }
            }
        )*
    }
}

impl_clear! {
    [f32; 4] = Float[0, 1, 2, 3],
    [f32; 3] = Float[0, 1, 2, 0],
    [f32; 2] = Float[0, 1, 0, 0],
    [i32; 4] = Int  [0, 1, 2, 3],
    [i32; 3] = Int  [0, 1, 2, 0],
    [i32; 2] = Int  [0, 1, 0, 0],
    [u32; 4] = Uint [0, 1, 2, 3],
    [u32; 3] = Uint [0, 1, 2, 0],
    [u32; 2] = Uint [0, 1, 0, 0],
}

impl From<f32> for ClearColor {
    fn from(v: f32) -> ClearColor {
        ClearColor::Float([v, 0.0, 0.0, 0.0])
    }
}
impl From<i32> for ClearColor {
    fn from(v: i32) -> ClearColor {
        ClearColor::Int([v, 0, 0, 0])
    }
}
impl From<u32> for ClearColor {
    fn from(v: u32) -> ClearColor {
        ClearColor::Uint([v, 0, 0, 0])
    }
}

/// Informations about what is accessed by a bunch of commands.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AccessInfo<R: Resources> {
    mapped_reads: HashSet<handle::RawBuffer<R>>,
    mapped_writes: HashSet<handle::RawBuffer<R>>,
}

impl<R: Resources> AccessInfo<R> {
    /// Creates empty access informations
    pub fn new() -> Self {
        AccessInfo {
            mapped_reads: HashSet::new(),
            mapped_writes: HashSet::new(),
        }
    }

    /// Clear access informations
    pub fn clear(&mut self) {
        self.mapped_reads.clear();
        self.mapped_writes.clear();
    }

    /// Register a buffer read access
    pub fn buffer_read(&mut self, buffer: &handle::RawBuffer<R>) {
        if buffer.is_mapped() {
            self.mapped_reads.insert(buffer.clone());
        }
    }

    /// Register a buffer write access
    pub fn buffer_write(&mut self, buffer: &handle::RawBuffer<R>) {
        if buffer.is_mapped() {
            self.mapped_writes.insert(buffer.clone());
        }
    }

    /// Returns the mapped buffers that The GPU will read from
    pub fn mapped_reads(&self) -> AccessInfoBuffers<R> {
        self.mapped_reads.iter()
    }

    /// Returns the mapped buffers that The GPU will write to
    pub fn mapped_writes(&self) -> AccessInfoBuffers<R> {
        self.mapped_writes.iter()
    }

    /// Is there any mapped buffer reads ?
    pub fn has_mapped_reads(&self) -> bool {
        !self.mapped_reads.is_empty()
    }

    /// Is there any mapped buffer writes ?
    pub fn has_mapped_writes(&self) -> bool {
        !self.mapped_writes.is_empty()
    }

    /// Takes all the accesses necessary for submission
    pub fn take_accesses(&self) -> SubmissionResult<AccessGuard<R>> {
        for buffer in self.mapped_reads().chain(self.mapped_writes()) {
            unsafe {
                if !buffer.mapping().unwrap().take_access() {
                    return Err(SubmissionError::AccessOverlap);
                }
            }
        }
        Ok(AccessGuard { inner: self })
    }
}

#[allow(missing_docs)]
pub type AccessInfoBuffers<'a, R> = hash_set::Iter<'a, handle::RawBuffer<R>>;

#[allow(missing_docs)]
#[derive(Debug)]
pub struct AccessGuard<'a, R: Resources> {
    inner: &'a AccessInfo<R>,
}

#[allow(missing_docs)]
impl<'a, R: Resources> AccessGuard<'a, R> {
    /// Returns the mapped buffers that The GPU will read from,
    /// with exclusive acces to their mapping
    pub fn access_mapped_reads(&mut self) -> AccessGuardBuffers<R> {
        AccessGuardBuffers {
            buffers: self.inner.mapped_reads()
        }
    }

    /// Returns the mapped buffers that The GPU will write to,
    /// with exclusive acces to their mapping
    pub fn access_mapped_writes(&mut self) -> AccessGuardBuffers<R> {
        AccessGuardBuffers {
            buffers: self.inner.mapped_writes()
        }
    }

    pub fn access_mapped(&mut self) -> AccessGuardBuffersChain<R> {
        AccessGuardBuffersChain {
            fst: self.inner.mapped_reads(),
            snd: self.inner.mapped_writes(),
        }
    }
}

impl<'a, R: Resources> Deref for AccessGuard<'a, R> {
    type Target = AccessInfo<R>;
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<'a, R: Resources> Drop for AccessGuard<'a, R> {
    fn drop(&mut self) {
        for buffer in self.inner.mapped_reads().chain(self.inner.mapped_writes()) {
            unsafe {
                buffer.mapping().unwrap().release_access();
            }
        }
    }
}

#[allow(missing_docs)]
#[derive(Debug)]
pub struct AccessGuardBuffers<'a, R: Resources> {
    buffers: AccessInfoBuffers<'a, R>
}

impl<'a, R: Resources> Iterator for AccessGuardBuffers<'a, R> {
    type Item = (&'a handle::RawBuffer<R>, &'a mut R::Mapping);

    fn next(&mut self) -> Option<Self::Item> {
        self.buffers.next().map(|buffer| unsafe {
            (buffer, buffer.mapping().unwrap().use_access())
        })
    }
}

#[allow(missing_docs)]
#[derive(Debug)]
pub struct AccessGuardBuffersChain<'a, R: Resources> {
    fst: AccessInfoBuffers<'a, R>,
    snd: AccessInfoBuffers<'a, R>
}

impl<'a, R: Resources> Iterator for AccessGuardBuffersChain<'a, R> {
    type Item = (&'a handle::RawBuffer<R>, &'a mut R::Mapping);

    fn next(&mut self) -> Option<Self::Item> {
        self.fst.next().or_else(|| self.snd.next())
            .map(|buffer| unsafe {
                (buffer, buffer.mapping().unwrap().use_access())
            })
    }
}
<commit_msg>[ll] core: Remove trait bounds for Encoder<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Command Buffer device interface

use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::collections::hash_set::{self, HashSet};
use {Backend, Resources, IndexType, InstanceCount, VertexCount,
     SubmissionResult, SubmissionError};
use {state, target, pso, shade, texture, handle};

/// A universal clear color supporting integet formats
/// as well as the standard floating-point.
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub enum ClearColor {
    /// Standard floating-point vec4 color
    Float([f32; 4]),
    /// Integer vector to clear ivec4 targets.
    Int([i32; 4]),
    /// Unsigned int vector to clear uvec4 targets.
    Uint([u32; 4]),
}

/// Optional instance parameters: (instance count, buffer offset)
pub type InstanceParams = (InstanceCount, VertexCount);

/// Thread-safe finished command buffer for submission.
pub struct Submit<B: Backend>(B::SubmitInfo);
impl<B: Backend> Submit<B> {
    #[doc(hidden)]
    pub unsafe fn get_info(&self) -> &B::SubmitInfo {
        &self.0
    }
}

/// Encoder for a command buffer.
///
/// Pools will always return an Encoder on `acquire_command_buffer` to provide a safe interface.
#[derive(Debug)]
pub struct Encoder<B, C>(C, PhantomData<B>);

impl<B, C> Deref for Encoder<B, C> {
    type Target = C;
    fn deref(&self) -> &C {
        &self.0
    }
}

impl<B, C> DerefMut for Encoder<B, C> {
    fn deref_mut(&mut self) -> &mut C {
        &mut self.0
    }
}

impl<B, C> Encoder<B, C>
    where B: Backend, C: CommandBuffer<B>
{
    #[doc(hidden)]
    pub unsafe fn new(buffer: C) -> Self {
        Encoder(buffer, PhantomData)
    }

    /// Finish recording commands to the command buffers.
    ///
    /// The command buffer will be consumed and can't be modified further.
    /// The command pool must be reset to re-record the command buffer.
    pub fn finish(mut self) -> Submit<B> {
        Submit(unsafe { self.0.end() })
    }
}

/// Base trait for all CommandBuffers
pub trait CommandBuffer<B: Backend> {
    #[doc(hidden)]
    unsafe fn end(&mut self) -> B::SubmitInfo;
}

/// Command buffer with graphics, compute and transfer functionality.
pub struct GeneralCommandBuffer<'a, B: Backend>(pub(crate) &'a mut B::RawCommandBuffer)
where B::RawCommandBuffer: 'a;

impl<'a, B: Backend> CommandBuffer<B> for GeneralCommandBuffer<'a, B> {
    unsafe fn end(&mut self) -> B::SubmitInfo {
        self.0.end()
    }
}

// TODO: temporary derefs, remove once command buffers will be reworked
impl<'a, B: Backend> Deref for GeneralCommandBuffer<'a, B> {
    type Target = B::RawCommandBuffer;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a, B: Backend> DerefMut for GeneralCommandBuffer<'a, B> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

/// Command buffer with graphics and transfer functionality.
pub struct GraphicsCommandBuffer<'a, B: Backend>(pub(crate) &'a mut B::RawCommandBuffer)
where B::RawCommandBuffer: 'a;

impl<'a, B: Backend> CommandBuffer<B> for GraphicsCommandBuffer<'a, B> {
    unsafe fn end(&mut self) -> B::SubmitInfo {
        self.0.end()
    }
}

// TODO: temporary derefs, remove once command buffers will be reworked
impl<'a, B: Backend> Deref for GraphicsCommandBuffer<'a, B> {
    type Target = B::RawCommandBuffer;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a, B: Backend> DerefMut for GraphicsCommandBuffer<'a, B> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

/// Command buffer with compute and transfer functionality.
pub struct ComputeCommandBuffer<'a, B: Backend>(pub(crate) &'a mut B::RawCommandBuffer)
where B::RawCommandBuffer: 'a;

impl<'a, B: Backend> CommandBuffer<B> for ComputeCommandBuffer<'a, B> {
    unsafe fn end(&mut self) -> B::SubmitInfo {
        self.0.end()
    }
}

/// Command buffer with transfer functionality.
pub struct TransferCommandBuffer<'a, B: Backend>(pub(crate) &'a mut B::RawCommandBuffer)
where B::RawCommandBuffer: 'a;

impl<'a, B: Backend> CommandBuffer<B> for TransferCommandBuffer<'a, B> {
    unsafe fn end(&mut self) -> B::SubmitInfo {
        self.0.end()
    }
}
/// An interface of the abstract command buffer. It collects commands in an
/// efficient API-specific manner, to be ready for execution on the device.
#[allow(missing_docs)]
pub trait Buffer<R: Resources>: 'static + Send {
    /// Reset the command buffer contents, retain the allocated storage
    fn reset(&mut self);
    /// Bind a pipeline state object
    fn bind_pipeline_state(&mut self, R::PipelineStateObject);
    /// Bind a complete set of vertex buffers
    fn bind_vertex_buffers(&mut self, pso::VertexBufferSet<R>);
    /// Bind a complete set of constant buffers
    fn bind_constant_buffers(&mut self, &[pso::ConstantBufferParam<R>]);
    /// Bind a global constant
    fn bind_global_constant(&mut self, shade::Location, shade::UniformValue);
    /// Bind a complete set of shader resource views
    fn bind_resource_views(&mut self, &[pso::ResourceViewParam<R>]);
    /// Bind a complete set of unordered access views
    fn bind_unordered_views(&mut self, &[pso::UnorderedViewParam<R>]);
    /// Bind a complete set of samplers
    fn bind_samplers(&mut self, &[pso::SamplerParam<R>]);
    /// Bind a complete set of pixel targets, including multiple
    /// colors views and an optional depth/stencil view.
    fn bind_pixel_targets(&mut self, pso::PixelTargetSet<R>);
    /// Bind an index buffer
    fn bind_index(&mut self, R::Buffer, IndexType);
    /// Set scissor rectangle
    fn set_scissor(&mut self, target::Rect);
    /// Set reference values for the blending and stencil front/back
    fn set_ref_values(&mut self, state::RefValues);
    /// Copy part of a buffer to another
    fn copy_buffer(&mut self, src: R::Buffer, dst: R::Buffer,
                   src_offset_bytes: usize, dst_offset_bytes: usize,
                   size_bytes: usize);
    /// Copy part of a buffer to a texture
    fn copy_buffer_to_texture(&mut self,
                              src: R::Buffer, src_offset_bytes: usize,
                              dst: R::Texture, texture::Kind,
                              Option<texture::CubeFace>, texture::RawImageInfo);
    /// Copy part of a texture to a buffer
    fn copy_texture_to_buffer(&mut self,
                              src: R::Texture, texture::Kind,
                              Option<texture::CubeFace>, texture::RawImageInfo,
                              dst: R::Buffer, dst_offset_bytes: usize);
    /// Update a vertex/index/uniform buffer
    fn update_buffer(&mut self, R::Buffer, data: &[u8], offset: usize);
    /// Update a texture
    fn update_texture(&mut self, R::Texture, texture::Kind, Option<texture::CubeFace>,
                      data: &[u8], texture::RawImageInfo);
    fn generate_mipmap(&mut self, R::ShaderResourceView);
    /// Clear color target
    fn clear_color(&mut self, R::RenderTargetView, ClearColor);
    fn clear_depth_stencil(&mut self, R::DepthStencilView,
                           Option<target::Depth>, Option<target::Stencil>);
    /// Draw a primitive
    fn call_draw(&mut self, VertexCount, VertexCount, Option<InstanceParams>);
    /// Draw a primitive with index buffer
    fn call_draw_indexed(&mut self, VertexCount, VertexCount, VertexCount, Option<InstanceParams>);
}

macro_rules! impl_clear {
    { $( $ty:ty = $sub:ident[$a:expr, $b:expr, $c:expr, $d:expr], )* } => {
        $(
            impl From<$ty> for ClearColor {
                fn from(v: $ty) -> ClearColor {
                    ClearColor::$sub([v[$a], v[$b], v[$c], v[$d]])
                }
            }
        )*
    }
}

impl_clear! {
    [f32; 4] = Float[0, 1, 2, 3],
    [f32; 3] = Float[0, 1, 2, 0],
    [f32; 2] = Float[0, 1, 0, 0],
    [i32; 4] = Int  [0, 1, 2, 3],
    [i32; 3] = Int  [0, 1, 2, 0],
    [i32; 2] = Int  [0, 1, 0, 0],
    [u32; 4] = Uint [0, 1, 2, 3],
    [u32; 3] = Uint [0, 1, 2, 0],
    [u32; 2] = Uint [0, 1, 0, 0],
}

impl From<f32> for ClearColor {
    fn from(v: f32) -> ClearColor {
        ClearColor::Float([v, 0.0, 0.0, 0.0])
    }
}
impl From<i32> for ClearColor {
    fn from(v: i32) -> ClearColor {
        ClearColor::Int([v, 0, 0, 0])
    }
}
impl From<u32> for ClearColor {
    fn from(v: u32) -> ClearColor {
        ClearColor::Uint([v, 0, 0, 0])
    }
}

/// Informations about what is accessed by a bunch of commands.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AccessInfo<R: Resources> {
    mapped_reads: HashSet<handle::RawBuffer<R>>,
    mapped_writes: HashSet<handle::RawBuffer<R>>,
}

impl<R: Resources> AccessInfo<R> {
    /// Creates empty access informations
    pub fn new() -> Self {
        AccessInfo {
            mapped_reads: HashSet::new(),
            mapped_writes: HashSet::new(),
        }
    }

    /// Clear access informations
    pub fn clear(&mut self) {
        self.mapped_reads.clear();
        self.mapped_writes.clear();
    }

    /// Register a buffer read access
    pub fn buffer_read(&mut self, buffer: &handle::RawBuffer<R>) {
        if buffer.is_mapped() {
            self.mapped_reads.insert(buffer.clone());
        }
    }

    /// Register a buffer write access
    pub fn buffer_write(&mut self, buffer: &handle::RawBuffer<R>) {
        if buffer.is_mapped() {
            self.mapped_writes.insert(buffer.clone());
        }
    }

    /// Returns the mapped buffers that The GPU will read from
    pub fn mapped_reads(&self) -> AccessInfoBuffers<R> {
        self.mapped_reads.iter()
    }

    /// Returns the mapped buffers that The GPU will write to
    pub fn mapped_writes(&self) -> AccessInfoBuffers<R> {
        self.mapped_writes.iter()
    }

    /// Is there any mapped buffer reads ?
    pub fn has_mapped_reads(&self) -> bool {
        !self.mapped_reads.is_empty()
    }

    /// Is there any mapped buffer writes ?
    pub fn has_mapped_writes(&self) -> bool {
        !self.mapped_writes.is_empty()
    }

    /// Takes all the accesses necessary for submission
    pub fn take_accesses(&self) -> SubmissionResult<AccessGuard<R>> {
        for buffer in self.mapped_reads().chain(self.mapped_writes()) {
            unsafe {
                if !buffer.mapping().unwrap().take_access() {
                    return Err(SubmissionError::AccessOverlap);
                }
            }
        }
        Ok(AccessGuard { inner: self })
    }
}

#[allow(missing_docs)]
pub type AccessInfoBuffers<'a, R> = hash_set::Iter<'a, handle::RawBuffer<R>>;

#[allow(missing_docs)]
#[derive(Debug)]
pub struct AccessGuard<'a, R: Resources> {
    inner: &'a AccessInfo<R>,
}

#[allow(missing_docs)]
impl<'a, R: Resources> AccessGuard<'a, R> {
    /// Returns the mapped buffers that The GPU will read from,
    /// with exclusive acces to their mapping
    pub fn access_mapped_reads(&mut self) -> AccessGuardBuffers<R> {
        AccessGuardBuffers {
            buffers: self.inner.mapped_reads()
        }
    }

    /// Returns the mapped buffers that The GPU will write to,
    /// with exclusive acces to their mapping
    pub fn access_mapped_writes(&mut self) -> AccessGuardBuffers<R> {
        AccessGuardBuffers {
            buffers: self.inner.mapped_writes()
        }
    }

    pub fn access_mapped(&mut self) -> AccessGuardBuffersChain<R> {
        AccessGuardBuffersChain {
            fst: self.inner.mapped_reads(),
            snd: self.inner.mapped_writes(),
        }
    }
}

impl<'a, R: Resources> Deref for AccessGuard<'a, R> {
    type Target = AccessInfo<R>;
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<'a, R: Resources> Drop for AccessGuard<'a, R> {
    fn drop(&mut self) {
        for buffer in self.inner.mapped_reads().chain(self.inner.mapped_writes()) {
            unsafe {
                buffer.mapping().unwrap().release_access();
            }
        }
    }
}

#[allow(missing_docs)]
#[derive(Debug)]
pub struct AccessGuardBuffers<'a, R: Resources> {
    buffers: AccessInfoBuffers<'a, R>
}

impl<'a, R: Resources> Iterator for AccessGuardBuffers<'a, R> {
    type Item = (&'a handle::RawBuffer<R>, &'a mut R::Mapping);

    fn next(&mut self) -> Option<Self::Item> {
        self.buffers.next().map(|buffer| unsafe {
            (buffer, buffer.mapping().unwrap().use_access())
        })
    }
}

#[allow(missing_docs)]
#[derive(Debug)]
pub struct AccessGuardBuffersChain<'a, R: Resources> {
    fst: AccessInfoBuffers<'a, R>,
    snd: AccessInfoBuffers<'a, R>
}

impl<'a, R: Resources> Iterator for AccessGuardBuffersChain<'a, R> {
    type Item = (&'a handle::RawBuffer<R>, &'a mut R::Mapping);

    fn next(&mut self) -> Option<Self::Item> {
        self.fst.next().or_else(|| self.snd.next())
            .map(|buffer| unsafe {
                (buffer, buffer.mapping().unwrap().use_access())
            })
    }
}
<|endoftext|>


<commit_before><commit_msg>Start on 64-bit IDT<commit_after>use core::mem;
use spin::Mutex;

extern {
    /// Offset of the 64-bit GDT main code segment.
    /// This should be exported by ASM.
    static gdt64_offset: u16;
}

const IDT_ENTRIES: usize = 256;
type Handler = unsafe extern "C" fn() -> ();

/// An IDT entry is called a gate.
///
/// Based on code from the OS Dev Wiki
/// http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure
#[repr(C, packed)]
struct Gate { offset_lower: u16
            , selector: u16
            , zero: u8
            , type_attr: u8
            , offest_mid: u16
            , offset_upper: u32
            , reserved: u32
            }

impl Gate {
    /// Creates a new IDT gate marked as `absent`.
    ///
    /// This is basically just for filling the new IDT table
    /// with valid (but useless) gates upon init.
    const fn absent() -> Self {
        Gate { offset_lower: 0
             , selector: 0
             , zero: 0
             , type_attr: 0b0000_1110
             , offset_mid: 0
             , offset_upper: 0
             , reserved: 0
        }
    }

    fn new(handler: Handler) -> Gate {
        unsafe {
            // `mem::transmute()` is glorious black magic
            let (low, mid, high): (u16, u16, u32)
                = mem::transmute(handler)

            Gate { offset_lower: low
                 , selector: gdt64_offset
                 , zero: 0
                 , type_attr: 0b1000_1110
                 , offset_mid: mid
                 , offset_upper: high
                 , reserved: 0
                 }
        }
    }
}

struct Idt([Gate; IDT_ENTRIES]);

/// This is the format that `lidt` expects for the pointer to the IDT.
/// ...apparently.
#[repr(C, packed)]
struct IdtPtr { limit: u16
              , base: u64
              }

impl IdtPtr {
    /// Load the IDT at the given location.
    /// This just calls `lidt`.
    pub unsafe fn load(&self) {
        asm!(  "lidt ($0)"
            :: "{rax}"(self)
            :: "volatile" );
    }
}

/// Global Interrupt Descriptor Table instance
/// Our global IDT.
static IDT: Mutex<Idt>
    = Mutex::new(Idt([Gate::absent(); IDT_ENTRIES]));
<|endoftext|>


<commit_before>use module::helpers::header as headerhelpers;
use storage::file::header::data::FileHeaderData as FHD;
use storage::file::header::spec::FileHeaderSpec as FHS;

pub fn get_spec() -> FHS {
    FHS::Map {
        keys: vec![
            headerhelpers::tags::spec::url_key(),
            headerhelpers::tags::spec::tags_key(),
        ]
    }
}

pub fn build_header(url: String, tags: Vec<String>) -> FHD {
    FHD::Map {
        keys: vec![
            FHD::Key {
                name: String::from("URL"),
                value: Box::new(FHD::Text(url.clone()))
            },
            FHD::Key {
                name: String::from("TAGS"),
                value: Box::new(headerhelpers::tags::data::build_tag_array(tags))
            }
        ]
    }
}

pub fn get_tags_from_header(header: &FHD) -> Vec<String> {
    headerhelpers::tags::data::get_tags_from_header(header)
}

pub fn get_url_from_header(header: &FHD) -> Option<String> {
    headerhelpers::data::get_url_from_header(header)
}

<commit_msg>BM header helpers: Add set_tags_in_header()<commit_after>use module::helpers::header as headerhelpers;
use storage::file::header::data::FileHeaderData as FHD;
use storage::file::header::spec::FileHeaderSpec as FHS;

pub fn get_spec() -> FHS {
    FHS::Map {
        keys: vec![
            headerhelpers::tags::spec::url_key(),
            headerhelpers::tags::spec::tags_key(),
        ]
    }
}

pub fn build_header(url: String, tags: Vec<String>) -> FHD {
    FHD::Map {
        keys: vec![
            FHD::Key {
                name: String::from("URL"),
                value: Box::new(FHD::Text(url.clone()))
            },
            FHD::Key {
                name: String::from("TAGS"),
                value: Box::new(headerhelpers::tags::data::build_tag_array(tags))
            }
        ]
    }
}

pub fn get_tags_from_header(header: &FHD) -> Vec<String> {
    headerhelpers::tags::data::get_tags_from_header(header)
}

pub fn set_tags_in_header(header: &FHD, tags: Vec<String>) {
    headerhelpers::tags::data::set_tags_in_header(header, tags)
}

pub fn get_url_from_header(header: &FHD) -> Option<String> {
    headerhelpers::data::get_url_from_header(header)
}

<|endoftext|>


<commit_before><commit_msg>mmu: refactoring.<commit_after><|endoftext|>


<commit_before><commit_msg>Add url parameter to the servosrc gstreamer plugin<commit_after><|endoftext|>


<commit_before><commit_msg>Finish implementing tar archivers<commit_after><|endoftext|>


<commit_before><commit_msg>collections::pub use { ... }<commit_after><|endoftext|>


<commit_before><commit_msg>Another benchmark<commit_after>// This test creates a bunch of tasks that simultaneously send to each
// other in a ring. The messages should all be basically
// independent. It's designed to hammer the global kernel lock, so
// that things will look really good once we get that lock out of the
// message path.

import comm::*;
import future::future;

use std;
import std::time;

fn thread_ring(i: uint,
               count: uint,
               num_chan: comm::chan<uint>,
               num_port: comm::port<uint>) {
    // Send/Receive lots of messages.
    for uint::range(0u, count) {|j|
        num_chan.send(i * j);
        num_port.recv();
    };
}

fn main(args: [str]) {
    let args = if os::getenv("RUST_BENCH").is_some() {
        ["", "100", "10000"]
    } else if args.len() <= 1u {
        ["", "100", "1000"]
    } else {
        args
    };

    let num_tasks = option::get(uint::from_str(args[1]));
    let msg_per_task = option::get(uint::from_str(args[2]));

    let num_port = port();
    let mut num_chan = chan(num_port);

    let start = time::precise_time_s();

    // create the ring
    let mut futures = [];

    for uint::range(1u, num_tasks) {|i|
        let get_chan = port();
        let get_chan_chan = chan(get_chan);

        futures += [future::spawn {|copy num_chan, move get_chan_chan|
            let p = port();
            get_chan_chan.send(chan(p));
            thread_ring(i, msg_per_task, num_chan,  p)
        }];

        num_chan = get_chan.recv();
    };

    // do our iteration
    thread_ring(0u, msg_per_task, num_chan, num_port);

    // synchronize
    for futures.each {|f| f.get() };

    let stop = time::precise_time_s();

    // all done, report stats.
    let num_msgs = num_tasks * msg_per_task;
    let elapsed = (stop - start);
    let rate = (num_msgs as float) / elapsed;

    io::println(#fmt("Sent %? messages in %? seconds",
                     num_msgs, elapsed));
    io::println(#fmt("  %? messages / second", rate));
    io::println(#fmt("  %? μs / message", 1000000. / rate));
}
<|endoftext|>


<commit_before><commit_msg>Workaround for https://github.com/rust-lang/rust/issues/15763<commit_after><|endoftext|>


<commit_before><commit_msg>Added partial MBC1 impl<commit_after>use super::MemoryBankController;

/// MBC1 is the first MBC chip for the Gameboy. It can address a maximum of
/// 2MB ROM (divided in 125 banks of size 16KB) and/or 32KB RAM.
///
/// The first 16KB in the rom (0 to 0x3FFF) are always pointing to the first
/// ROM bank. The following 16KB refer to the selected ROM bank.
/// Banks are numbered from 0 to 0x7F (128), but bank numbers 0x20, 0x40 and
/// 0x60 are not usable, thus the total bank number is 125.
struct MBC1 {
    data: Vec<u8>,
    ram: [u8; 32768], // 32KB RAM
    selected_rom_bank: u8,
    selected_ram_bank: u8,
}

impl MemoryBankController for MBC1 {

    fn read(&self, addr: u16) -> u8 {
        match addr {
            0...0x3FFF => self.data[addr as usize], // bank 0
            0x4000...0x7FFF => {
                // the selected bank data (banks 1 to 0x7F)
                let base_address = self.selected_rom_bank as u16 * 0x4000;
                self.data[(base_address + addr) as usize]
            },
            0xA000...0xBFFF => {
                // the selected RAM bank data (banks 0 to 3)
                self.ram[(addr - 0xA000) as usize]
            }
            _ => panic!("RomOnly MBC attempted read at ${:04x}", addr),
        }
    }

    fn write(&mut self, addr: u16, data: u8) {
        // TODO finish this
    }
}<|endoftext|>


<commit_before><commit_msg>watcher fix<commit_after><|endoftext|>


<commit_before><commit_msg>Start of heap<commit_after>// SPDX-License-Identifier: Unlicense

#![feature(custom_test_frameworks)]
#![no_main]
#![no_std]
#![reexport_test_harness_main = "test_main"]
#![test_runner(libkernel::util::testing::test_runner)]
#![feature(format_args_nl)] // for debug macros

#[allow(unused_imports)]
#[macro_use]
extern crate libkernel;

use test_macros::kernel_test;

#[no_mangle]
fn kernel_init() {
    use libkernel::{handler, pager};

    fn next() -> ! {
        test_main();
        unreachable!()
    }

    handler::init().expect("handler::init");
    pager::init(next);
}

#[kernel_test]
fn device_init() {
    use libkernel::device;

    major!("initialising device");
    device::init().expect("device::init");
    debug!("returned");
}
<|endoftext|>