<commit_before>use std::path::PathBuf;
use std::fs::File;
use std::io::{Read, Result, Error, ErrorKind};
use book::bookitem::{BookItem, Chapter};

pub fn construct_bookitems(path: &PathBuf) -> Result<Vec<BookItem>> {
    debug!("[fn]: construct_bookitems");
    let mut summary = String::new();
    try!(try!(File::open(path)).read_to_string(&mut summary));

    debug!("[*]: Parse SUMMARY.md");
    let top_items = try!(parse_level(&mut summary.split('\n').collect(), 0, vec![0]));
    debug!("[*]: Done parsing SUMMARY.md");
    Ok(top_items)
}

fn parse_level(summary: &mut Vec<&str>, current_level: i32, mut section: Vec<i32>) -> Result<Vec<BookItem>> {
    debug!("[fn]: parse_level");
    let mut items: Vec<BookItem> = vec![];

    // Construct the book recursively
    while !summary.is_empty() {
        let item: BookItem;
        // Indentation level of the line to parse
        let level = try!(level(summary[0], 4));

        // if level < current_level we remove the last digit of section, exit the current function,
        // and return the parsed level to the calling function.
        if level < current_level { break }

        // if level > current_level we call ourselves to go one level deeper
        if level > current_level {
            // Level can not be root level !!
            // Add a sub-number to section
            section.push(1);
            let last = items.pop().expect("There should be at least one item since this can't be the root level");

            item = if let BookItem::Chapter(ref s, ref ch) = last {
                let mut ch = ch.clone();
                ch.sub_items = try!(parse_level(summary, level, section.clone()));
                items.push(BookItem::Chapter(s.clone(), ch));

                // Remove the last number from the section, because we got back to our level..
                section.pop();
                continue
            } else {
                return Err(Error::new( ErrorKind::Other, format!(
                        "Your summary.md is messed up\n\n
                        Prefix, Suffix and Spacer elements can only exist on the root level.\n
                        Prefix elements can only exist before any chapter and there can be no chapters after suffix elements."
                        )))
            };

        } else {
            // level and current_level are the same, parse the line
            item = if let Some(parsed_item) = parse_line(summary[0]) {

                // Eliminate possible errors and set section to -1 after suffix
                match parsed_item {
                    // error if level != 0 and BookItem is != Chapter
                    BookItem::Affix(_) | BookItem::Spacer if level > 0 => {
                        return Err(Error::new( ErrorKind::Other, format!(
                                "Your summary.md is messed up\n\n
                                Prefix, Suffix and Spacer elements can only exist on the root level.\n
                                Prefix elements can only exist before any chapter and there can be no chapters after suffix elements."
                                )))
                    },

                    // error if BookItem == Chapter and section == -1
                    BookItem::Chapter(_, _) if section[0] == -1 => {
                        return Err(Error::new( ErrorKind::Other, format!(
                                "Your summary.md is messed up\n\n
                                Prefix, Suffix and Spacer elements can only exist on the root level.\n
                                Prefix elements can only exist before any chapter and there can be no chapters after suffix elements."
                                )))
                    },

                    // Set section = -1 after suffix
                    BookItem::Affix(_) if section[0] > 0 => {
                        section[0] = -1;
                    }

                    _ => {},
                }

                match parsed_item {
                    BookItem::Chapter(_, ch) => {
                        // Increment section
                        let len = section.len() -1;
                        section[len] += 1;
                        let s = section.iter().fold("".to_owned(), |s, i| s + &i.to_string() + ".");
                        BookItem::Chapter(s, ch)
                    }
                    _ => parsed_item
                }

            } else {
                // If parse_line does not return Some(_) continue...
                summary.remove(0);
                continue;
            };
        }

        summary.remove(0);
        items.push(item)
    }
    debug!("[*]: Level: {:?}", items);
    Ok(items)
}

fn level(line: &str, spaces_in_tab: i32) -> Result<i32> {
    debug!("[fn]: level");
    let mut spaces = 0;
    let mut level = 0;

    for ch in line.chars() {
        match ch {
            ' ' => spaces += 1,
            '\t' => level += 1,
            _ => break,
        }
        if spaces >= spaces_in_tab {
            level += 1;
            spaces = 0;
        }
    }

    // If there are spaces left, there is an indentation error
    if spaces > 0 {
        debug!("[SUMMARY.md]:");
        debug!("\t[line]: {}", line);
        debug!("[*]: There is an indentation error on this line. Indentation should be {} spaces", spaces_in_tab);
        return Err(Error::new(
            ErrorKind::Other,
            format!("Indentation error on line:\n\n{}", line)
            )
        )
    }

    Ok(level)
}

fn parse_line(l: &str) -> Option<BookItem> {
    debug!("[fn]: parse_line");

    // Remove leading and trailing spaces or tabs
    let line = l.trim_matches(|c: char| { c == ' ' || c == '\t' });

    // Spacers are "------"
    if line.starts_with("--") {
        debug!("[*]: Line is spacer");
        return Some(BookItem::Spacer)
    }

    if let Some(c) = line.chars().nth(0) {
        match c {
            // List item
            '-' | '*' => {
                debug!("[*]: Line is list element");

                if let Some((name, path)) = read_link(line) {
                    return Some(BookItem::Chapter("0".to_owned(), Chapter::new(name, path)))
                } else { return None }
            },
            // Non-list element
            '[' => {
                debug!("[*]: Line is a link element");

                if let Some((name, path)) = read_link(line) {
                    return Some(BookItem::Affix(Chapter::new(name, path)))
                } else { return None }
            }
            _ => {}
        }
    }

    None
}

fn read_link(line: &str) -> Option<(String, PathBuf)> {
    let mut start_delimitor;
    let mut end_delimitor;

    // In the future, support for list item that is not a link
    // Not sure if I should error on line I can't parse or just ignore them...
    if let Some(i) = line.find('[') { start_delimitor = i; }
    else {
        debug!("[*]: '[' not found, this line is not a link. Ignoring...");
        return None
    }

    if let Some(i) = line[start_delimitor..].find("](") {
        end_delimitor = start_delimitor +i;
    }
    else {
        debug!("[*]: '](' not found, this line is not a link. Ignoring...");
        return None
    }

    let name = line[start_delimitor + 1 .. end_delimitor].to_owned();

    start_delimitor = end_delimitor + 1;
    if let Some(i) = line[start_delimitor..].find(')') {
        end_delimitor = start_delimitor + i;
    }
    else {
        debug!("[*]: ')' not found, this line is not a link. Ignoring...");
        return None
    }

    let path = PathBuf::from(line[start_delimitor + 1 .. end_delimitor].to_owned());

    Some((name, path))
}
<commit_msg>Should fix #56<commit_after>use std::path::PathBuf;
use std::fs::File;
use std::io::{Read, Result, Error, ErrorKind};
use book::bookitem::{BookItem, Chapter};

pub fn construct_bookitems(path: &PathBuf) -> Result<Vec<BookItem>> {
    debug!("[fn]: construct_bookitems");
    let mut summary = String::new();
    try!(try!(File::open(path)).read_to_string(&mut summary));

    debug!("[*]: Parse SUMMARY.md");
    let top_items = try!(parse_level(&mut summary.split('\n').collect(), 0, vec![0]));
    debug!("[*]: Done parsing SUMMARY.md");
    Ok(top_items)
}

fn parse_level(summary: &mut Vec<&str>, current_level: i32, mut section: Vec<i32>) -> Result<Vec<BookItem>> {
    debug!("[fn]: parse_level");
    let mut items: Vec<BookItem> = vec![];

    // Construct the book recursively
    while !summary.is_empty() {
        let item: BookItem;
        // Indentation level of the line to parse
        let level = try!(level(summary[0], 4));

        // if level < current_level we remove the last digit of section, exit the current function,
        // and return the parsed level to the calling function.
        if level < current_level { break }

        // if level > current_level we call ourselves to go one level deeper
        if level > current_level {
            // Level can not be root level !!
            // Add a sub-number to section
            section.push(0);
            let last = items.pop().expect("There should be at least one item since this can't be the root level");

            item = if let BookItem::Chapter(ref s, ref ch) = last {
                let mut ch = ch.clone();
                ch.sub_items = try!(parse_level(summary, level, section.clone()));
                items.push(BookItem::Chapter(s.clone(), ch));

                // Remove the last number from the section, because we got back to our level..
                section.pop();
                continue
            } else {
                return Err(Error::new( ErrorKind::Other, format!(
                        "Your summary.md is messed up\n\n
                        Prefix, Suffix and Spacer elements can only exist on the root level.\n
                        Prefix elements can only exist before any chapter and there can be no chapters after suffix elements."
                        )))
            };

        } else {
            // level and current_level are the same, parse the line
            item = if let Some(parsed_item) = parse_line(summary[0]) {

                // Eliminate possible errors and set section to -1 after suffix
                match parsed_item {
                    // error if level != 0 and BookItem is != Chapter
                    BookItem::Affix(_) | BookItem::Spacer if level > 0 => {
                        return Err(Error::new( ErrorKind::Other, format!(
                                "Your summary.md is messed up\n\n
                                Prefix, Suffix and Spacer elements can only exist on the root level.\n
                                Prefix elements can only exist before any chapter and there can be no chapters after suffix elements."
                                )))
                    },

                    // error if BookItem == Chapter and section == -1
                    BookItem::Chapter(_, _) if section[0] == -1 => {
                        return Err(Error::new( ErrorKind::Other, format!(
                                "Your summary.md is messed up\n\n
                                Prefix, Suffix and Spacer elements can only exist on the root level.\n
                                Prefix elements can only exist before any chapter and there can be no chapters after suffix elements."
                                )))
                    },

                    // Set section = -1 after suffix
                    BookItem::Affix(_) if section[0] > 0 => {
                        section[0] = -1;
                    }

                    _ => {},
                }

                match parsed_item {
                    BookItem::Chapter(_, ch) => {
                        // Increment section
                        let len = section.len() -1;
                        section[len] += 1;
                        let s = section.iter().fold("".to_owned(), |s, i| s + &i.to_string() + ".");
                        BookItem::Chapter(s, ch)
                    }
                    _ => parsed_item
                }

            } else {
                // If parse_line does not return Some(_) continue...
                summary.remove(0);
                continue;
            };
        }

        summary.remove(0);
        items.push(item)
    }
    debug!("[*]: Level: {:?}", items);
    Ok(items)
}

fn level(line: &str, spaces_in_tab: i32) -> Result<i32> {
    debug!("[fn]: level");
    let mut spaces = 0;
    let mut level = 0;

    for ch in line.chars() {
        match ch {
            ' ' => spaces += 1,
            '\t' => level += 1,
            _ => break,
        }
        if spaces >= spaces_in_tab {
            level += 1;
            spaces = 0;
        }
    }

    // If there are spaces left, there is an indentation error
    if spaces > 0 {
        debug!("[SUMMARY.md]:");
        debug!("\t[line]: {}", line);
        debug!("[*]: There is an indentation error on this line. Indentation should be {} spaces", spaces_in_tab);
        return Err(Error::new(
            ErrorKind::Other,
            format!("Indentation error on line:\n\n{}", line)
            )
        )
    }

    Ok(level)
}

fn parse_line(l: &str) -> Option<BookItem> {
    debug!("[fn]: parse_line");

    // Remove leading and trailing spaces or tabs
    let line = l.trim_matches(|c: char| { c == ' ' || c == '\t' });

    // Spacers are "------"
    if line.starts_with("--") {
        debug!("[*]: Line is spacer");
        return Some(BookItem::Spacer)
    }

    if let Some(c) = line.chars().nth(0) {
        match c {
            // List item
            '-' | '*' => {
                debug!("[*]: Line is list element");

                if let Some((name, path)) = read_link(line) {
                    return Some(BookItem::Chapter("0".to_owned(), Chapter::new(name, path)))
                } else { return None }
            },
            // Non-list element
            '[' => {
                debug!("[*]: Line is a link element");

                if let Some((name, path)) = read_link(line) {
                    return Some(BookItem::Affix(Chapter::new(name, path)))
                } else { return None }
            }
            _ => {}
        }
    }

    None
}

fn read_link(line: &str) -> Option<(String, PathBuf)> {
    let mut start_delimitor;
    let mut end_delimitor;

    // In the future, support for list item that is not a link
    // Not sure if I should error on line I can't parse or just ignore them...
    if let Some(i) = line.find('[') { start_delimitor = i; }
    else {
        debug!("[*]: '[' not found, this line is not a link. Ignoring...");
        return None
    }

    if let Some(i) = line[start_delimitor..].find("](") {
        end_delimitor = start_delimitor +i;
    }
    else {
        debug!("[*]: '](' not found, this line is not a link. Ignoring...");
        return None
    }

    let name = line[start_delimitor + 1 .. end_delimitor].to_owned();

    start_delimitor = end_delimitor + 1;
    if let Some(i) = line[start_delimitor..].find(')') {
        end_delimitor = start_delimitor + i;
    }
    else {
        debug!("[*]: ')' not found, this line is not a link. Ignoring...");
        return None
    }

    let path = PathBuf::from(line[start_delimitor + 1 .. end_delimitor].to_owned());

    Some((name, path))
}
<|endoftext|>


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

// Utility macros for implementing PartialEq on slice-like types

#![doc(hidden)]

#[macro_export]
macro_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { &self[..] != &other[..] }
        }
    }
}

#[macro_export]
macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { &self[..] == &other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { &self[..] != &other[..] }
        }
    }
}
<commit_msg>Auto merge of #28792 - dotdash:cmp_indirection, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Utility macros for implementing PartialEq on slice-like types

#![doc(hidden)]

#[macro_export]
macro_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
        }
    }
}

#[macro_export]
macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
        }
    }
}
<|endoftext|>


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

// A specialised string-like structure that is optimised for appending text and
// sequential reading.

// TODO
// Debug
// docs
// char iterator
//   Chars -> CharsAndPos
// Eq

extern crate unicode;

use std::str::FromStr;
use std::{cmp, fmt};

const MAX_CAPACITY: usize = 0xffff;
const INIT_CAPACITY: usize = 0xff;

pub struct StringBuffer {
    first: Box<StringNode>,
    // last: &self StringNode
    // Optimisation that saves us from walking the whole list of nodes everytime
    // we append a string.
    last: *mut StringNode,
    // The length of the whole StringBuffer.
    len: usize,
}

pub struct Chars<'a> {
    // Node we're currently iterating over.
    cur_node: &'a StringNode,
    // Byte in cur_node.
    cur_byte: usize,
    // Byte since start of StringBuffer.
    abs_byte: usize,
}

struct StringNode {
    data: String,
    next: Option<Box<StringNode>>,
}

impl StringBuffer {
    pub fn new() -> StringBuffer {
        StringBuffer::with_capacity(INIT_CAPACITY)
    }

    pub fn with_capacity(capacity: usize) -> StringBuffer {
        let mut result = StringBuffer {
            first: box StringNode::with_capacity(capacity),
            last: 0 as *mut StringNode,
            len: 0,
        };
        result.last = &mut *result.first;
        result
    }

    pub fn push_str(&mut self, text: &str) {
        self.len += text.len();
        unsafe {
            // Safety invariant: the `last` field will only ever point to
            // a node owned by self, and will live until destruction of self.
            self.last = (&mut *self.last).push_str(text);
        }
    }

    pub fn chars<'a>(&'a self) -> Chars<'a> {
        Chars::new(&self.first)
    }
}

impl StringNode {
    fn with_capacity(capacity: usize) -> StringNode {
        StringNode {
            data: String::with_capacity(capacity),
            next: None,
        }
    }

    // Returns a reference to the new last node.
    fn push_str(&mut self, text: &str) -> &mut StringNode {
        if let Some(ref mut n) = self.next {
            return n.push_str(text);
        }

        if self.data.capacity() - self.data.len() >= text.len() {
            self.data.push_str(text);
            self
        } else {
            self.data.shrink_to_fit();
            let next_cap = cmp::min(cmp::max(self.data.capacity(),
                                             INIT_CAPACITY) * 2,
                                    MAX_CAPACITY);
            let next_cap = cmp::max(next_cap, text.len());
            self.next = Some(box StringNode::with_capacity(next_cap));
            let next = self.next.as_mut().unwrap();
            next.push_str(text);
            &mut **next
        }
    }
}

impl FromStr for StringBuffer {
    type Err = ();
    fn from_str(text: &str) -> Result<StringBuffer, ()> {
        let mut result = StringBuffer::with_capacity(cmp::max(INIT_CAPACITY, text.len()));
        result.push_str(text);
        Ok(result)
    }
}

impl fmt::Display for StringBuffer {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fn fmt_node(node: &StringNode, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            try!(write!(fmt, "{}", node.data));
            if let Some(ref n) = node.next {
                fmt_node(n, fmt)
            } else {
                Ok(())
            }
        }

        fmt_node(&self.first, fmt)
    }
}

impl<'a> Iterator for Chars<'a> {
    type Item = (char, usize);

    fn next(&mut self) -> Option<(char, usize)> {
        while self.cur_byte >= self.cur_node.data.len() {
            if let Some(ref n) = self.cur_node.next {
                self.cur_byte = 0;
                self.cur_node = n;
            } else {
                return None;
            }
        }

        let byte = self.abs_byte;
        let result = self.read_char();

        return Some((result, byte));
    }
}

impl<'a> Chars<'a> {
    fn new<'b>(first_node: &'b StringNode) -> Chars<'b> {
        Chars {
            cur_node: first_node,
            cur_byte: 0,
            abs_byte: 0,
        }
    }

    fn read_char(&mut self) -> char {
        let first_byte = self.read_byte();
        let width = unicode::str::utf8_char_width(first_byte);
        if width == 1 {
            return first_byte as char
        }
        if width == 0 {
            panic!("non-utf8 char in StringBuffer");
        }
        let mut buf = [first_byte, 0, 0, 0];
        {
            let mut start = 1;
            while start < width {
                buf[start] = self.read_byte();
                start += 1;
            }
        }
        match ::std::str::from_utf8(&buf[..width]).ok() {
            Some(s) => s.char_at(0),
            None => panic!("bad chars in StringBuffer")
        }
    }

    fn read_byte(&mut self) -> u8 {
        let result = self.cur_node.data.as_bytes()[self.cur_byte];
        self.cur_byte += 1;
        self.abs_byte += 1;
        result
    }
}

#[cfg(test)]
mod test {
    use super::*;
    // Bug #23157
    use super::{StringNode, INIT_CAPACITY};

    #[test]
    fn test_new() {
        let s = StringBuffer::new();
        assert!(s.len == 0);
        assert!(s.to_string() == "");
        assert!(count_nodes(&s) == 1);
        assert!(first_capacity(&s) == INIT_CAPACITY);

        let s = StringBuffer::with_capacity(64);
        assert!(s.len == 0);
        assert!(s.to_string() == "");
        assert!(count_nodes(&s) == 1);
        assert!(first_capacity(&s) == 64);
    }

    #[test]
    fn test_from_str() {
        let s: StringBuffer = "Hello".parse().unwrap();
        assert!(s.len == 5);
        assert!(s.to_string() == "Hello");
        assert!(count_nodes(&s) == 1);
        assert!(first_capacity(&s) == INIT_CAPACITY);

        let expected = "Hello";
        for ((i, (c, b)), cc) in s.chars().enumerate().zip(expected.chars()) {
            assert!(c == cc);
            assert!(i == b);
        }
    }

    #[test]
    fn test_push_str() {
        let mut s: StringBuffer = "Hello".parse().unwrap();
        assert!(first_capacity(&s) == INIT_CAPACITY);

        s.push_str(" world!");
        assert!(s.to_string() == "Hello world!");
        assert!(s.len == 12);
        s.push_str(" foo");
        assert!(s.to_string() == "Hello world! foo");
        assert!(s.len == 16);

        assert!(count_nodes(&s) == 1);

        let expected = "Hello world! foo";
        for ((i, (c, b)), cc) in s.chars().enumerate().zip(expected.chars()) {
            assert!(c == cc);
            assert!(i == b);
        }
    }

    // push_str requiring multiple nodes
    #[test]
    fn test_push_str_multi() {
        let mut s: StringBuffer = StringBuffer::with_capacity(2);
        assert!(first_capacity(&s) == 2);

        s.push_str("Hello");
        assert!(s.to_string() == "Hello");
        assert!(s.len == 5);
        assert!(count_nodes(&s) == 2);
        s.push_str(" world!");
        assert!(s.to_string() == "Hello world!");
        assert!(s.len == 12);
        assert!(count_nodes(&s) == 2);

        let expected = "Hello world!";
        for ((i, (c, b)), cc) in s.chars().enumerate().zip(expected.chars()) {
            assert!(c == cc);
            assert!(i == b);
        }
    }

    // TODO test unicode

    fn count_nodes(s: &StringBuffer) -> usize {
        count_nodes_from(&s.first)
    }
    fn count_nodes_from(s: &StringNode) -> usize {
        match s.next {
            Some(ref n) => 1 + count_nodes_from(n),
            None => 1,
        }
    }
    fn first_capacity(s: &StringBuffer) -> usize {
        s.first.data.capacity()
    }
}
<|endoftext|>


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

// no-pretty-expanded unnecessary unsafe block generated

#![deny(warnings)]
#![allow(unused_must_use)]
#![allow(unknown_features)]
#![feature(box_syntax)]

use std::fmt::{self, Write};
use std::usize;

struct A;
struct B;
struct C;
struct D;

impl fmt::LowerHex for A {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("aloha")
    }
}
impl fmt::UpperHex for B {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("adios")
    }
}
impl fmt::Display for C {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad_integral(true, "☃", "123")
    }
}
impl fmt::Binary for D {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(f.write_str("aa"));
        try!(f.write_char('☃'));
        f.write_str("bb")
    }
}

macro_rules! t {
    ($a:expr, $b:expr) => { assert_eq!($a, $b) }
}

pub fn main() {
    // Various edge cases without formats
    t!(format!(""), "");
    t!(format!("hello"), "hello");
    t!(format!("hello {{"), "hello {");

    // default formatters should work
    t!(format!("{}", 1.0f32), "1");
    t!(format!("{}", 1.0f64), "1");
    t!(format!("{}", "a"), "a");
    t!(format!("{}", "a".to_string()), "a");
    t!(format!("{}", false), "false");
    t!(format!("{}", 'a'), "a");

    // At least exercise all the formats
    t!(format!("{}", true), "true");
    t!(format!("{}", '☃'), "☃");
    t!(format!("{}", 10), "10");
    t!(format!("{}", 10_usize), "10");
    t!(format!("{:?}", '☃'), "'\\u{2603}'");
    t!(format!("{:?}", 10), "10");
    t!(format!("{:?}", 10_usize), "10");
    t!(format!("{:?}", "true"), "\"true\"");
    t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
    t!(format!("{:o}", 10_usize), "12");
    t!(format!("{:x}", 10_usize), "a");
    t!(format!("{:X}", 10_usize), "A");
    t!(format!("{}", "foo"), "foo");
    t!(format!("{}", "foo".to_string()), "foo");
    if cfg!(target_pointer_width = "32") {
        t!(format!("{:#p}", 0x1234 as *const isize), "0x00001234");
        t!(format!("{:#p}", 0x1234 as *mut isize), "0x00001234");
    } else {
        t!(format!("{:#p}", 0x1234 as *const isize), "0x0000000000001234");
        t!(format!("{:#p}", 0x1234 as *mut isize), "0x0000000000001234");
    }
    t!(format!("{:p}", 0x1234 as *const isize), "0x1234");
    t!(format!("{:p}", 0x1234 as *mut isize), "0x1234");
    t!(format!("{:x}", A), "aloha");
    t!(format!("{:X}", B), "adios");
    t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃");
    t!(format!("{1} {0}", 0, 1), "1 0");
    t!(format!("{foo} {bar}", foo=0, bar=1), "0 1");
    t!(format!("{foo} {1} {bar} {0}", 0, 1, foo=2, bar=3), "2 1 3 0");
    t!(format!("{} {0}", "a"), "a a");
    t!(format!("{foo_bar}", foo_bar=1), "1");
    t!(format!("{}", 5 + 5), "10");
    t!(format!("{:#4}", C), "☃123");
    t!(format!("{:b}", D), "aa☃bb");

    let a: &fmt::Debug = &1;
    t!(format!("{:?}", a), "1");

    // Formatting strings and their arguments
    t!(format!("{}", "a"), "a");
    t!(format!("{:4}", "a"), "a   ");
    t!(format!("{:4}", "☃"), "☃   ");
    t!(format!("{:>4}", "a"), "   a");
    t!(format!("{:<4}", "a"), "a   ");
    t!(format!("{:^5}", "a"),  "  a  ");
    t!(format!("{:^5}", "aa"), " aa  ");
    t!(format!("{:^4}", "a"),  " a  ");
    t!(format!("{:^4}", "aa"), " aa ");
    t!(format!("{:.4}", "a"), "a");
    t!(format!("{:4.4}", "a"), "a   ");
    t!(format!("{:4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:2.4}", "aaaaa"), "aaaa");
    t!(format!("{:2.4}", "aaaa"), "aaaa");
    t!(format!("{:2.4}", "aaa"), "aaa");
    t!(format!("{:2.4}", "aa"), "aa");
    t!(format!("{:2.4}", "a"), "a ");
    t!(format!("{:0>2}", "a"), "0a");
    t!(format!("{:.*}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:.1$}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa");
    t!(format!("{:.a$}", "aaaaaaaaaaaaaaaaaa", a=4), "aaaa");
    t!(format!("{:1$}", "a", 4), "a   ");
    t!(format!("{1:0$}", 4, "a"), "a   ");
    t!(format!("{:a$}", "a", a=4), "a   ");
    t!(format!("{:-#}", "a"), "a");
    t!(format!("{:+#}", "a"), "a");

    // Some float stuff
    t!(format!("{:}", 1.0f32), "1");
    t!(format!("{:}", 1.0f64), "1");
    t!(format!("{:.3}", 1.0f64), "1.000");
    t!(format!("{:10.3}", 1.0f64),   "     1.000");
    t!(format!("{:+10.3}", 1.0f64),  "    +1.000");
    t!(format!("{:+10.3}", -1.0f64), "    -1.000");

    t!(format!("{:e}", 1.2345e6f32), "1.2345e6");
    t!(format!("{:e}", 1.2345e6f64), "1.2345e6");
    t!(format!("{:E}", 1.2345e6f64), "1.2345E6");
    t!(format!("{:.3e}", 1.2345e6f64), "1.234e6");
    t!(format!("{:10.3e}", 1.2345e6f64),   "   1.234e6");
    t!(format!("{:+10.3e}", 1.2345e6f64),  "  +1.234e6");
    t!(format!("{:+10.3e}", -1.2345e6f64), "  -1.234e6");

    // Float edge cases
    t!(format!("{}", -0.0), "0");
    t!(format!("{:?}", -0.0), "-0");
    t!(format!("{:?}", 0.0), "0");

    // Test that pointers don't get truncated.
    {
        let val = usize::MAX;
        let exp = format!("{:#x}", val);
        t!(format!("{:p}", val as *const isize), exp);
    }

    // Escaping
    t!(format!("{{"), "{");
    t!(format!("}}"), "}");

    test_write();
    test_print();
    test_order();

    // make sure that format! doesn't move out of local variables
    let a: Box<_> = box 3;
    format!("{}", a);
    format!("{}", a);

    // make sure that format! doesn't cause spurious unused-unsafe warnings when
    // it's inside of an outer unsafe block
    unsafe {
        let a: isize = ::std::mem::transmute(3_usize);
        format!("{}", a);
    }

    test_format_args();

    // test that trailing commas are acceptable
    format!("{}", "test",);
    format!("{foo}", foo="test",);
}

// Basic test to make sure that we can invoke the `write!` macro with an
// fmt::Write instance.
fn test_write() {
    use std::fmt::Write;
    let mut buf = String::new();
    write!(&mut buf, "{}", 3);
    {
        let w = &mut buf;
        write!(w, "{foo}", foo=4);
        write!(w, "{}", "hello");
        writeln!(w, "{}", "line");
        writeln!(w, "{foo}", foo="bar");
        w.write_char('☃');
        w.write_str("str");
    }

    t!(buf, "34helloline\nbar\n☃str");
}

// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_print() {
    print!("hi");
    print!("{:?}", vec!(0u8));
    println!("hello");
    println!("this is a {}", "test");
    println!("{foo}", foo="bar");
}

// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_format_args() {
    use std::fmt::Write;
    let mut buf = String::new();
    {
        let w = &mut buf;
        write!(w, "{}", format_args!("{}", 1));
        write!(w, "{}", format_args!("test"));
        write!(w, "{}", format_args!("{test}", test=3));
    }
    let s = buf;
    t!(s, "1test3");

    let s = fmt::format(format_args!("hello {}", "world"));
    t!(s, "hello world");
    let s = format!("{}: {}", "args were", format_args!("hello {}", "world"));
    t!(s, "args were: hello world");
}

fn test_order() {
    // Make sure format!() arguments are always evaluated in a left-to-right
    // ordering
    fn foo() -> isize {
        static mut FOO: isize = 0;
        unsafe {
            FOO += 1;
            FOO
        }
    }
    assert_eq!(format!("{} {} {a} {b} {} {c}",
                       foo(), foo(), foo(), a=foo(), b=foo(), c=foo()),
               "1 2 4 5 3 6".to_string());
}
<commit_msg>Add `fmt::Debug` string escape tests<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// no-pretty-expanded unnecessary unsafe block generated

#![deny(warnings)]
#![allow(unused_must_use)]
#![allow(unknown_features)]
#![feature(box_syntax)]

use std::fmt::{self, Write};
use std::usize;

struct A;
struct B;
struct C;
struct D;

impl fmt::LowerHex for A {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("aloha")
    }
}
impl fmt::UpperHex for B {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("adios")
    }
}
impl fmt::Display for C {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad_integral(true, "☃", "123")
    }
}
impl fmt::Binary for D {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(f.write_str("aa"));
        try!(f.write_char('☃'));
        f.write_str("bb")
    }
}

macro_rules! t {
    ($a:expr, $b:expr) => { assert_eq!($a, $b) }
}

pub fn main() {
    // Various edge cases without formats
    t!(format!(""), "");
    t!(format!("hello"), "hello");
    t!(format!("hello {{"), "hello {");

    // default formatters should work
    t!(format!("{}", 1.0f32), "1");
    t!(format!("{}", 1.0f64), "1");
    t!(format!("{}", "a"), "a");
    t!(format!("{}", "a".to_string()), "a");
    t!(format!("{}", false), "false");
    t!(format!("{}", 'a'), "a");

    // At least exercise all the formats
    t!(format!("{}", true), "true");
    t!(format!("{}", '☃'), "☃");
    t!(format!("{}", 10), "10");
    t!(format!("{}", 10_usize), "10");
    t!(format!("{:?}", '☃'), "'\\u{2603}'");
    t!(format!("{:?}", 10), "10");
    t!(format!("{:?}", 10_usize), "10");
    t!(format!("{:?}", "true"), "\"true\"");
    t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
    t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"),
       r#""foo\n\"bar\"\r\n\'baz\'\t\\qux\\""#);
    t!(format!("{:?}", "foo\0bar\x01baz\u{3b1}q\u{75}x"),
       r#""foo\u{0}bar\u{1}baz\u{3b1}qux""#);
    t!(format!("{:o}", 10_usize), "12");
    t!(format!("{:x}", 10_usize), "a");
    t!(format!("{:X}", 10_usize), "A");
    t!(format!("{}", "foo"), "foo");
    t!(format!("{}", "foo".to_string()), "foo");
    if cfg!(target_pointer_width = "32") {
        t!(format!("{:#p}", 0x1234 as *const isize), "0x00001234");
        t!(format!("{:#p}", 0x1234 as *mut isize), "0x00001234");
    } else {
        t!(format!("{:#p}", 0x1234 as *const isize), "0x0000000000001234");
        t!(format!("{:#p}", 0x1234 as *mut isize), "0x0000000000001234");
    }
    t!(format!("{:p}", 0x1234 as *const isize), "0x1234");
    t!(format!("{:p}", 0x1234 as *mut isize), "0x1234");
    t!(format!("{:x}", A), "aloha");
    t!(format!("{:X}", B), "adios");
    t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃");
    t!(format!("{1} {0}", 0, 1), "1 0");
    t!(format!("{foo} {bar}", foo=0, bar=1), "0 1");
    t!(format!("{foo} {1} {bar} {0}", 0, 1, foo=2, bar=3), "2 1 3 0");
    t!(format!("{} {0}", "a"), "a a");
    t!(format!("{foo_bar}", foo_bar=1), "1");
    t!(format!("{}", 5 + 5), "10");
    t!(format!("{:#4}", C), "☃123");
    t!(format!("{:b}", D), "aa☃bb");

    let a: &fmt::Debug = &1;
    t!(format!("{:?}", a), "1");

    // Formatting strings and their arguments
    t!(format!("{}", "a"), "a");
    t!(format!("{:4}", "a"), "a   ");
    t!(format!("{:4}", "☃"), "☃   ");
    t!(format!("{:>4}", "a"), "   a");
    t!(format!("{:<4}", "a"), "a   ");
    t!(format!("{:^5}", "a"),  "  a  ");
    t!(format!("{:^5}", "aa"), " aa  ");
    t!(format!("{:^4}", "a"),  " a  ");
    t!(format!("{:^4}", "aa"), " aa ");
    t!(format!("{:.4}", "a"), "a");
    t!(format!("{:4.4}", "a"), "a   ");
    t!(format!("{:4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:2.4}", "aaaaa"), "aaaa");
    t!(format!("{:2.4}", "aaaa"), "aaaa");
    t!(format!("{:2.4}", "aaa"), "aaa");
    t!(format!("{:2.4}", "aa"), "aa");
    t!(format!("{:2.4}", "a"), "a ");
    t!(format!("{:0>2}", "a"), "0a");
    t!(format!("{:.*}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa");
    t!(format!("{:.1$}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa");
    t!(format!("{:.a$}", "aaaaaaaaaaaaaaaaaa", a=4), "aaaa");
    t!(format!("{:1$}", "a", 4), "a   ");
    t!(format!("{1:0$}", 4, "a"), "a   ");
    t!(format!("{:a$}", "a", a=4), "a   ");
    t!(format!("{:-#}", "a"), "a");
    t!(format!("{:+#}", "a"), "a");

    // Some float stuff
    t!(format!("{:}", 1.0f32), "1");
    t!(format!("{:}", 1.0f64), "1");
    t!(format!("{:.3}", 1.0f64), "1.000");
    t!(format!("{:10.3}", 1.0f64),   "     1.000");
    t!(format!("{:+10.3}", 1.0f64),  "    +1.000");
    t!(format!("{:+10.3}", -1.0f64), "    -1.000");

    t!(format!("{:e}", 1.2345e6f32), "1.2345e6");
    t!(format!("{:e}", 1.2345e6f64), "1.2345e6");
    t!(format!("{:E}", 1.2345e6f64), "1.2345E6");
    t!(format!("{:.3e}", 1.2345e6f64), "1.234e6");
    t!(format!("{:10.3e}", 1.2345e6f64),   "   1.234e6");
    t!(format!("{:+10.3e}", 1.2345e6f64),  "  +1.234e6");
    t!(format!("{:+10.3e}", -1.2345e6f64), "  -1.234e6");

    // Float edge cases
    t!(format!("{}", -0.0), "0");
    t!(format!("{:?}", -0.0), "-0");
    t!(format!("{:?}", 0.0), "0");

    // Test that pointers don't get truncated.
    {
        let val = usize::MAX;
        let exp = format!("{:#x}", val);
        t!(format!("{:p}", val as *const isize), exp);
    }

    // Escaping
    t!(format!("{{"), "{");
    t!(format!("}}"), "}");

    test_write();
    test_print();
    test_order();

    // make sure that format! doesn't move out of local variables
    let a: Box<_> = box 3;
    format!("{}", a);
    format!("{}", a);

    // make sure that format! doesn't cause spurious unused-unsafe warnings when
    // it's inside of an outer unsafe block
    unsafe {
        let a: isize = ::std::mem::transmute(3_usize);
        format!("{}", a);
    }

    test_format_args();

    // test that trailing commas are acceptable
    format!("{}", "test",);
    format!("{foo}", foo="test",);
}

// Basic test to make sure that we can invoke the `write!` macro with an
// fmt::Write instance.
fn test_write() {
    use std::fmt::Write;
    let mut buf = String::new();
    write!(&mut buf, "{}", 3);
    {
        let w = &mut buf;
        write!(w, "{foo}", foo=4);
        write!(w, "{}", "hello");
        writeln!(w, "{}", "line");
        writeln!(w, "{foo}", foo="bar");
        w.write_char('☃');
        w.write_str("str");
    }

    t!(buf, "34helloline\nbar\n☃str");
}

// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_print() {
    print!("hi");
    print!("{:?}", vec!(0u8));
    println!("hello");
    println!("this is a {}", "test");
    println!("{foo}", foo="bar");
}

// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_format_args() {
    use std::fmt::Write;
    let mut buf = String::new();
    {
        let w = &mut buf;
        write!(w, "{}", format_args!("{}", 1));
        write!(w, "{}", format_args!("test"));
        write!(w, "{}", format_args!("{test}", test=3));
    }
    let s = buf;
    t!(s, "1test3");

    let s = fmt::format(format_args!("hello {}", "world"));
    t!(s, "hello world");
    let s = format!("{}: {}", "args were", format_args!("hello {}", "world"));
    t!(s, "args were: hello world");
}

fn test_order() {
    // Make sure format!() arguments are always evaluated in a left-to-right
    // ordering
    fn foo() -> isize {
        static mut FOO: isize = 0;
        unsafe {
            FOO += 1;
            FOO
        }
    }
    assert_eq!(format!("{} {} {a} {b} {} {c}",
                       foo(), foo(), foo(), a=foo(), b=foo(), c=foo()),
               "1 2 4 5 3 6".to_string());
}
<|endoftext|>


<commit_before><commit_msg>Use timetable distances to infer the minimal spanning tree.<commit_after><|endoftext|>


<commit_before><commit_msg>rm no-op `#[unsafe_no_drop_flag]` attribute<commit_after><|endoftext|>


<commit_before><commit_msg>Test that `core::assert!` is valid<commit_after>// compile-flags: --crate-type=lib
// check-pass
// issue #55482
#![no_std]

macro_rules! foo {
    ($e:expr) => {
        $crate::core::assert!($e);
        $crate::core::assert_eq!($e, true);
    };
}

pub fn foo() { foo!(true); }
<|endoftext|>


<commit_before>//! Window creation using glutin for gfx.
//!
//! # Examples
//! The following code creates a `gfx::WindowExt` using glutin.
//!
//! ```no_run
//! extern crate glutin;
//! extern crate gfx_device_gl;
//! extern crate gfx_window_glutin;
//!
//! fn main() {
//!     use gfx_window_glutin::Window;
//!     use glutin::{EventsLoop, WindowBuilder, ContextBuilder, GlWindow};
//!
//!     // First create a window using glutin.
//!     let mut events_loop = EventsLoop::new();
//!     let wb = WindowBuilder::new();
//!     let cb = ContextBuilder::new().with_vsync(true);
//!     let glutin_window = GlWindow::new(wb, cb, &events_loop).unwrap();
//!
//!     // Then use the glutin window to create a gfx window.
//!     let window = Window::new(glutin_window);
//! }
//! ```
#[deny(missing_docs)]

extern crate gfx_core as core;
extern crate gfx_device_gl as device_gl;
extern crate glutin;

#[cfg(feature = "headless")]
pub use headless::Headless;

use core::{format, handle, texture};
use core::memory;
use device_gl::Resources as R;
use glutin::GlContext;
use std::rc::Rc;

#[cfg(feature = "headless")]
mod headless;

fn get_window_dimensions(window: &glutin::GlWindow) -> texture::Dimensions {
    let (width, height) = window.get_inner_size().unwrap();
    let aa = window.get_pixel_format().multisampling
                   .unwrap_or(0) as texture::NumSamples;
    ((width as f32 * window.hidpi_factor()) as texture::Size, (height as f32 * window.hidpi_factor()) as texture::Size, 1, aa.into())
}

/*
/// Update the internal dimensions of the main framebuffer targets. Generic version over the format.
pub fn update_views<Cf, Df>(window: &glutin::GlWindow, color_view: &mut handle::RenderTargetView<R, Cf>,
                    ds_view: &mut handle::DepthStencilView<R, Df>)
where
    Cf: format::RenderFormat,
    Df: format::DepthFormat,
{
    let dim = color_view.get_dimensions();
    assert_eq!(dim, ds_view.get_dimensions());
    if let Some((cv, dv)) = update_views_raw(window, dim, Cf::get_format(), Df::get_format()) {
        *color_view = Typed::new(cv);
        *ds_view = Typed::new(dv);
    }
}

/// Return new main target views if the window resolution has changed from the old dimensions.
pub fn update_views_raw(window: &glutin::GlWindow, old_dimensions: texture::Dimensions,
                        color_format: format::Format, ds_format: format::Format)
                        -> Option<(handle::RawRenderTargetView<R>, handle::RawDepthStencilView<R>)>
{
    let dim = get_window_dimensions(window);
    if dim != old_dimensions {
        Some(device_gl::create_main_targets_raw(dim, color_format.0, ds_format.0))
    }else {
        None
    }
}
*/

pub struct Swapchain {
    // Underlying window, required for presentation
    window: Rc<glutin::GlWindow>,
    // Single element backbuffer
    backbuffer: [core::Backbuffer<device_gl::Backend>; 1],
}

impl core::Swapchain<device_gl::Backend> for Swapchain {
    fn get_backbuffers(&mut self) -> &[core::Backbuffer<device_gl::Backend>] {
        &self.backbuffer
    }

    fn acquire_frame(&mut self, sync: core::FrameSync<device_gl::Resources>) -> core::Frame {
        // TODO: sync
        core::Frame::new(0)
    }

    fn present<Q>(&mut self, _: &mut Q, _: &[&handle::Semaphore<device_gl::Resources>])
        where Q: AsMut<device_gl::CommandQueue>
    {
        self.window.swap_buffers();
    }
}

pub struct Surface {
    window: Rc<glutin::GlWindow>,
    manager: handle::Manager<R>,
}

impl core::Surface<device_gl::Backend> for Surface {
    type Swapchain = Swapchain;

    fn supports_queue(&self, _: &device_gl::QueueFamily) -> bool { true }
    fn build_swapchain<Q>(&mut self, config: core::SwapchainConfig, present_queue: &Q) -> Swapchain
        where Q: AsRef<device_gl::CommandQueue>
    {
        use core::handle::Producer;
        let dim = get_window_dimensions(&self.window);
        let color = self.manager.make_texture(
            device_gl::NewTexture::Surface(0),
            texture::Info {
                levels: 1,
                kind: texture::Kind::D2(dim.0, dim.1, dim.3),
                format: config.color_format.0,
                bind: memory::RENDER_TARGET | memory::TRANSFER_SRC,
                usage: memory::Usage::Data,
            },
        );

        let ds = config.depth_stencil_format.map(|ds_format| {
            self.manager.make_texture(
                device_gl::NewTexture::Surface(0),
                texture::Info {
                    levels: 1,
                    kind: texture::Kind::D2(dim.0, dim.1, dim.3),
                    format: ds_format.0,
                    bind: memory::DEPTH_STENCIL | memory::TRANSFER_SRC,
                    usage: memory::Usage::Data,
                },
            )
        });

        Swapchain {
            window: self.window.clone(),
            backbuffer: [(color, ds); 1],
        }
    }
}

pub struct Window(Rc<glutin::GlWindow>);

pub fn config_context(
    builder: glutin::ContextBuilder,
    color_format: format::Format, ds_format: format::Format) -> glutin::ContextBuilder
{
    let color_total_bits = color_format.0.get_total_bits();
    let alpha_bits = color_format.0.get_alpha_stencil_bits();
    let depth_total_bits = ds_format.0.get_total_bits();
    let stencil_bits = ds_format.0.get_alpha_stencil_bits();
    builder
        .with_depth_buffer(depth_total_bits - stencil_bits)
        .with_stencil_buffer(stencil_bits)
        .with_pixel_format(color_total_bits - alpha_bits, alpha_bits)
        .with_srgb(color_format.1 == format::ChannelType::Srgb)
}

impl Window {
    /// Create a new window.
    pub fn new(window: glutin::GlWindow) -> Self {
        Window(Rc::new(window))
    }

    /// Get the internal glutin window.
    pub fn raw(&self) -> &glutin::GlWindow {
        &self.0
    }
}
impl core::WindowExt<device_gl::Backend> for Window {
    type Surface = Surface;
    type Adapter = device_gl::Adapter;

    fn get_surface_and_adapters(&mut self) -> (Surface, Vec<device_gl::Adapter>) {
        unsafe { self.0.make_current().unwrap() };
        let adapter = device_gl::Adapter::new(|s| self.0.get_proc_address(s) as *const std::os::raw::c_void);
        let surface = Surface {
            window: self.0.clone(),
            manager: handle::Manager::new(),
        };

        (surface, vec![adapter])
    }
}
<commit_msg>[ll] gl: Fix glutin window build<commit_after>//! Window creation using glutin for gfx.
//!
//! # Examples
//! The following code creates a `gfx::WindowExt` using glutin.
//!
//! ```no_run
//! extern crate glutin;
//! extern crate gfx_device_gl;
//! extern crate gfx_window_glutin;
//!
//! fn main() {
//!     use gfx_window_glutin::Window;
//!     use glutin::{EventsLoop, WindowBuilder, ContextBuilder, GlWindow};
//!
//!     // First create a window using glutin.
//!     let mut events_loop = EventsLoop::new();
//!     let wb = WindowBuilder::new();
//!     let cb = ContextBuilder::new().with_vsync(true);
//!     let glutin_window = GlWindow::new(wb, cb, &events_loop).unwrap();
//!
//!     // Then use the glutin window to create a gfx window.
//!     let window = Window::new(glutin_window);
//! }
//! ```
#[deny(missing_docs)]

extern crate gfx_core as core;
extern crate gfx_device_gl as device_gl;
extern crate glutin;

#[cfg(feature = "headless")]
pub use headless::Headless;

use core::{format, handle, texture};
use core::memory;
use device_gl::{native as n, Backend as B};
use glutin::GlContext;
use std::rc::Rc;

#[cfg(feature = "headless")]
mod headless;

fn get_window_dimensions(window: &glutin::GlWindow) -> texture::Dimensions {
    let (width, height) = window.get_inner_size().unwrap();
    let aa = window.get_pixel_format().multisampling
                   .unwrap_or(0) as texture::NumSamples;
    ((width as f32 * window.hidpi_factor()) as texture::Size, (height as f32 * window.hidpi_factor()) as texture::Size, 1, aa.into())
}

/*
/// Update the internal dimensions of the main framebuffer targets. Generic version over the format.
pub fn update_views<Cf, Df>(window: &glutin::GlWindow, color_view: &mut handle::RenderTargetView<R, Cf>,
                    ds_view: &mut handle::DepthStencilView<R, Df>)
where
    Cf: format::RenderFormat,
    Df: format::DepthFormat,
{
    let dim = color_view.get_dimensions();
    assert_eq!(dim, ds_view.get_dimensions());
    if let Some((cv, dv)) = update_views_raw(window, dim, Cf::get_format(), Df::get_format()) {
        *color_view = Typed::new(cv);
        *ds_view = Typed::new(dv);
    }
}

/// Return new main target views if the window resolution has changed from the old dimensions.
pub fn update_views_raw(window: &glutin::GlWindow, old_dimensions: texture::Dimensions,
                        color_format: format::Format, ds_format: format::Format)
                        -> Option<(handle::RawRenderTargetView<R>, handle::RawDepthStencilView<R>)>
{
    let dim = get_window_dimensions(window);
    if dim != old_dimensions {
        Some(device_gl::create_main_targets_raw(dim, color_format.0, ds_format.0))
    }else {
        None
    }
}
*/

pub struct Swapchain {
    // Underlying window, required for presentation
    window: Rc<glutin::GlWindow>,
    // Single element backbuffer
    backbuffer: [core::Backbuffer<B>; 1],
}

impl core::Swapchain<B> for SwapChain {
    fn get_backbuffers(&mut self) -> &[core::Backbuffer<B>] {
        &self.backbuffer
    }

    fn acquire_frame(&mut self, sync: core::FrameSync<B>) -> core::Frame {
        // TODO: sync
        core::Frame::new(0)
    }

    fn present<Q>(&mut self, _: &mut Q, _: &[&handle::Semaphore<B>])
        where Q: AsMut<device_gl::CommandQueue>
    {
        self.window.swap_buffers();
    }
}

pub struct Surface {
    window: Rc<glutin::GlWindow>,
    manager: handle::Manager<B>,
}

impl core::Surface<B> for Surface {
    type Swapchain = Swapchain;

    fn supports_queue(&self, _: &device_gl::QueueFamily) -> bool { true }
    fn build_swapchain<Q>(&mut self, config: core::SwapchainConfig, present_queue: &Q) -> Swapchain
        where Q: AsRef<device_gl::CommandQueue>
    {
        use core::handle::Producer;
        let dim = get_window_dimensions(&self.window);
        let color = self.manager.make_image(
            n::Image::Surface(0),
            texture::Info {
                levels: 1,
                kind: texture::Kind::D2(dim.0, dim.1, dim.3),
                format: config.color_format.0,
                bind: memory::RENDER_TARGET | memory::TRANSFER_SRC,
                usage: memory::Usage::Data,
            },
        );

        let ds = config.depth_stencil_format.map(|ds_format| {
            self.manager.make_image(
                n::Image::Surface(0),
                texture::Info {
                    levels: 1,
                    kind: texture::Kind::D2(dim.0, dim.1, dim.3),
                    format: ds_format.0,
                    bind: memory::DEPTH_STENCIL | memory::TRANSFER_SRC,
                    usage: memory::Usage::Data,
                },
            )
        });

        Swapchain {
            window: self.window.clone(),
            backbuffer: [(color, ds); 1],
        }
    }
}

pub struct Window(Rc<glutin::GlWindow>);

pub fn config_context(
    builder: glutin::ContextBuilder,
    color_format: format::Format, ds_format: format::Format) -> glutin::ContextBuilder
{
    let color_total_bits = color_format.0.get_total_bits();
    let alpha_bits = color_format.0.get_alpha_stencil_bits();
    let depth_total_bits = ds_format.0.get_total_bits();
    let stencil_bits = ds_format.0.get_alpha_stencil_bits();
    builder
        .with_depth_buffer(depth_total_bits - stencil_bits)
        .with_stencil_buffer(stencil_bits)
        .with_pixel_format(color_total_bits - alpha_bits, alpha_bits)
        .with_srgb(color_format.1 == format::ChannelType::Srgb)
}

impl Window {
    /// Create a new window.
    pub fn new(window: glutin::GlWindow) -> Self {
        Window(Rc::new(window))
    }

    /// Get the internal glutin window.
    pub fn raw(&self) -> &glutin::GlWindow {
        &self.0
    }
}
impl core::WindowExt<B> for Window {
    type Surface = Surface;
    type Adapter = device_gl::Adapter;

    fn get_surface_and_adapters(&mut self) -> (Surface, Vec<device_gl::Adapter>) {
        unsafe { self.0.make_current().unwrap() };
        let adapter = device_gl::Adapter::new(|s| self.0.get_proc_address(s) as *const std::os::raw::c_void);
        let surface = Surface {
            window: self.0.clone(),
            manager: handle::Manager::new(),
        };

        (surface, vec![adapter])
    }
}
<|endoftext|>


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

// compile-flags: -O

#![allow(dead_code)]

#[repr(C, u8)]
enum ReprCu8 {
    A(u16),
    B,
}

#[repr(C)]
struct ReprC {
    tag: u8,
    padding: u8,
    payload: u16,
}

fn main() {
    let r1 = ReprC { tag: 0, padding: 0, payload: 0 };
    let r2 = ReprC { tag: 0, padding: 1, payload: 1 };

    let t1: &ReprCu8 = unsafe { std::mem::transmute(&r1) };
    let t2: &ReprCu8 = unsafe { std::mem::transmute(&r2) };

    match (t1, t2) {
        (ReprCu8::A(_), ReprCu8::A(_)) => (),
        _ => assert!(false)
    };
}
<commit_msg>Add repr(u8) to the test<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags: -O

#![allow(dead_code)]

#[repr(C, u8)]
enum ReprCu8 {
    A(u16),
    B,
}

#[repr(u8)]
enum Repru8 {
    A(u16),
    B,
}

#[repr(C)]
struct ReprC {
    tag: u8,
    padding: u8,
    payload: u16,
}

fn main() {
    // Test `repr(C, u8)`.
    let r1 = ReprC { tag: 0, padding: 0, payload: 0 };
    let r2 = ReprC { tag: 0, padding: 1, payload: 1 };

    let t1: &ReprCu8 = unsafe { std::mem::transmute(&r1) };
    let t2: &ReprCu8 = unsafe { std::mem::transmute(&r2) };

    match (t1, t2) {
        (ReprCu8::A(_), ReprCu8::A(_)) => (),
        _ => assert!(false)
    };

    // Test `repr(u8)`.
    let t1: &Repru8 = unsafe { std::mem::transmute(&r1) };
    let t2: &Repru8 = unsafe { std::mem::transmute(&r2) };

    match (t1, t2) {
        (Repru8::A(_), Repru8::A(_)) => (),
        _ => assert!(false)
    };
}
<|endoftext|>


<commit_before><commit_msg>started implementation of trace for constant collection<commit_after>//! A trace implementation for a collection that does not change.
//!
//! This trace avoids maintaining times and differences, as it only needs to record keys and values.
//! Unlike the `time.rs` trace, we are "assured" that the collection accumulates to positive counts,
//! and we are able to represent the frequency of each record in "unary", by the number of times it
//! occurs.
//!
//! This is perhaps the tightest representation I can think of for otherwise arbitrary keys and vals.

/// An immutable collection of keys and values.
pub struct Spine<Key: Ord, Val: Ord> {
	batch: Option<Layer<Key, Val>>,
}

impl<Key: Ord, Val: Ord, Time: Lattice+Ord> Trace<Key, Val, Time> for Spine<Key, Val> {

	type Batch = Rc<Layer<Key, Val>>;
	type Cursor = LayerCursor<Key, Val, Time>;

	fn new(default: Time) -> Self { Spine { batch: None } }

	fn insert(&mut self, batch: Self::Batch) {
		self.batch = Some(batch);
	}
	fn cursor(&self) -> Self::Cursor {
		if let Some(&ref batch) = self.batch {
			batch.cursor()
		}
		else {
			panic!("no batch present; what to do?");
		}
	}
	fn advance_by(&mut self, frontier: &[Time]) { /* totally ignored */ }
}

/// Represents an immutable collection of updates at the base time.
pub struct Layer<Key: Ord, Val: Ord> {
	keys: Vec<Key>,
	offs: Vec<usize>,
	vals: Vec<Val>,
}

impl<Key: Ord, Val: Ord, Time: Lattice+Ord> Batch<Key, Val, Time> for Layer<Key, Val> {

	type Builder = LayerBuilder<Key, Val>;
	type Cursor = LayerCursor<Key, Val, Time>;

	fn cursor(&self) -> Self::Cursor;
	fn len(&self) -> usize;
}

/// Supports navigation through a single layer.
pub struct LayerCursor<Key: Ord, Val: Ord, Time: Lattice+Ord> {
	time: Time,
	layer: Rc<Layer<Key, Val>>,
	key_off: (usize, usize),
	val_off: (usize, usize),
}

impl<Key: Ord, Val: Ord, Time: Lattice+Ord> Cursor<Key, Val, Time> for LayerCursor<Key, Val, Time> {

	type Key = Key;
	type Val = Val;
	type Time = Time;

	fn key_valid(&self) -> bool { self.key_off.0 < self.key_off.1 }
	fn val_valid(&self) -> bool { self.val_off.0 < self.val_off.1 }

	fn key(&self) -> &Self::Key {
		debug_assert!(self.key_valid());
		&self.layer.keys[self.key_off.0]
	}
	fn val(&self) -> &Self::Val {
		debug_assert!(self.key_valid());
		debug_assert!(self.val_valid());
		&self.layer.vals[self.val_off.0];
	}
	fn map_times<L: FnMut(&Self::Time, isize)>(&self, logic: L) {
		logic(&self.time, 1);
	}

	fn step_key(&mut self) {
		self.key_off.0 += 1;
		if self.key_off.0 < self.key_off.1 {
			self.val_off.0 = self.layer.offs[self.key_off.0-1];
			self.val_off.1 = self.layer.offs[self.key_off.0];
		}
		else {
			self.key_off.0 = self.key_off.1;
			self.val_off.0 = self.val_off.1;
		}
	}
	fn seek_key(&mut self, key: &Self::Key) {
		self.key_off.0 += advance(&self.layer.keys[self.key_off.0 ..], |k| k.lt(key));
		if self.key_off.0 < self.key_off.1 {
			self.val_off.0 = self.layer.offs[self.key_off.0-1];
			self.val_off.1 = self.layer.offs[self.key_off.0];
		}
		else {
			self.key_off.0 = self.key_off.1;
			self.val_off.0 = self.val_off.1;
		}
	}
	fn peek_key(&self) -> Option<&Self::Key> {
		if self.key_valid() { Some(self.key()) } else { None }
	}

	fn step_val(&mut self) {
		self.val_off.0 += 1;
		if self.val_off.0 >= self.val_off.1 {
			self.val_off.0 = self.val_off.1;
		}
	}
	fn seek_val(&mut self, val: &Self::Val) {
		self.val_off += advance(&self.layer.vals[self.val_off.0 .. self.val_off.1], |v| v.lt(val));
	}
	fn peek_val(&self) -> Option<&Self::Val> {
		if self.val_valid() { Some(self.val()) } else { None }
	}

	fn rewind_keys(&mut self) {
		self.key_off.0 = 0;
		self.val_off.0 = 0;
		if self.key_off.1 > 0 {
			self.val_off.1 = self.layer.offs[0];
		}
		else {
			self.val_off.1 = 0;
		}
	}
	fn rewind_vals(&mut self) {
		self.val_off.0 = if self.key_off.0 == 0 { 0 } else { self.layer.offs[self.key_off.0-1] };
	}

}<|endoftext|>


<commit_before>use {Interest, Selector, PollOpt, Token};
use buf::{Buf, MutBuf};

// Re-export the io::Result / Error types for convenience
pub use std::io::{Read, Write, Result, Error};

/// A value that may be registered with an `EventLoop`
pub trait Evented {
    #[doc(hidden)]
    fn register(&self, selector: &mut Selector, token: Token, interest: Interest, opts: PollOpt) -> Result<()>;

    #[doc(hidden)]
    fn reregister(&self, selector: &mut Selector, token: Token, interest: Interest, opts: PollOpt) -> Result<()>;

    #[doc(hidden)]
    fn deregister(&self, selector: &mut Selector) -> Result<()>;
}

pub trait TryRead {
    fn try_read_buf<B: MutBuf>(&mut self, buf: &mut B) -> Result<Option<usize>> {
        // Reads the length of the slice supplied by buf.mut_bytes into the buffer
        // This is not guaranteed to consume an entire datagram or segment.
        // If your protocol is msg based (instead of continuous stream) you should
        // ensure that your buffer is large enough to hold an entire segment (1532 bytes if not jumbo
        // frames)
        let res = self.try_read(buf.mut_bytes());

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }

    fn try_read(&mut self, buf: &mut [u8]) -> Result<Option<usize>>;
}

pub trait TryWrite {
    fn try_write_buf<B: Buf>(&mut self, buf: &mut B) -> Result<Option<usize>> {
        let res = self.try_write(buf.bytes());

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }

    fn try_write(&mut self, buf: &[u8]) -> Result<Option<usize>>;
}

impl<T: Read> TryRead for T {
    fn try_read(&mut self, dst: &mut [u8]) -> Result<Option<usize>> {
        self.read(dst)
            .map(|cnt| Some(cnt))
            .or_else(to_non_block)
    }
}

impl<T: Write> TryWrite for T {
    fn try_write(&mut self, src: &[u8]) -> Result<Option<usize>> {
        self.write(src)
            .map(|cnt| Some(cnt))
            .or_else(to_non_block)
    }
}

/*
 *
 * ===== Helpers =====
 *
 */

pub fn to_non_block<T>(err: Error) -> Result<Option<T>> {
    use std::io::ErrorKind::WouldBlock;

    if let WouldBlock = err.kind() {
        return Ok(None);
    }

    Err(err)
}
<commit_msg>Make `TryRead` and `TryWrite` object-safe.<commit_after>use {Interest, Selector, PollOpt, Token};
use buf::{Buf, MutBuf};

// Re-export the io::Result / Error types for convenience
pub use std::io::{Read, Write, Result, Error};

/// A value that may be registered with an `EventLoop`
pub trait Evented {
    #[doc(hidden)]
    fn register(&self, selector: &mut Selector, token: Token, interest: Interest, opts: PollOpt) -> Result<()>;

    #[doc(hidden)]
    fn reregister(&self, selector: &mut Selector, token: Token, interest: Interest, opts: PollOpt) -> Result<()>;

    #[doc(hidden)]
    fn deregister(&self, selector: &mut Selector) -> Result<()>;
}

pub trait TryRead {
    fn try_read_buf<B: MutBuf>(&mut self, buf: &mut B) -> Result<Option<usize>>
        where Self : Sized
    {
        // Reads the length of the slice supplied by buf.mut_bytes into the buffer
        // This is not guaranteed to consume an entire datagram or segment.
        // If your protocol is msg based (instead of continuous stream) you should
        // ensure that your buffer is large enough to hold an entire segment (1532 bytes if not jumbo
        // frames)
        let res = self.try_read(buf.mut_bytes());

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }

    fn try_read(&mut self, buf: &mut [u8]) -> Result<Option<usize>>;
}

pub trait TryWrite {
    fn try_write_buf<B: Buf>(&mut self, buf: &mut B) -> Result<Option<usize>>
        where Self : Sized
    {
        let res = self.try_write(buf.bytes());

        if let Ok(Some(cnt)) = res {
            buf.advance(cnt);
        }

        res
    }

    fn try_write(&mut self, buf: &[u8]) -> Result<Option<usize>>;
}

impl<T: Read> TryRead for T {
    fn try_read(&mut self, dst: &mut [u8]) -> Result<Option<usize>> {
        self.read(dst)
            .map(|cnt| Some(cnt))
            .or_else(to_non_block)
    }
}

impl<T: Write> TryWrite for T {
    fn try_write(&mut self, src: &[u8]) -> Result<Option<usize>> {
        self.write(src)
            .map(|cnt| Some(cnt))
            .or_else(to_non_block)
    }
}

/*
 *
 * ===== Helpers =====
 *
 */

pub fn to_non_block<T>(err: Error) -> Result<Option<T>> {
    use std::io::ErrorKind::WouldBlock;

    if let WouldBlock = err.kind() {
        return Ok(None);
    }

    Err(err)
}
<|endoftext|>


<commit_before>use core::ptr::{read, write};

use common::memory::*;
use common::pci::*;
use common::pio::*;
use common::scheduler::*;

use programs::common::*;

#[repr(packed)]
struct BD {
    ptr: u32,
    samples: u32
}

struct AC97Resource {
    audio: usize,
    bus_master: usize
}

impl Resource for AC97Resource {
    fn url(&self) -> URL {
        return URL::from_string(&"audio://".to_string());
    }

    fn stat(&self) -> ResourceType {
        return ResourceType::File;
    }

    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        return Option::None;
    }

    fn read_to_end(&mut self, vec: &mut Vec<u8>) -> Option<usize> {
        return Option::None;
    }

    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        unsafe {
            let audio = self.audio as u16;
            let master_volume = audio + 2;
            let pcm_volume = audio + 0x18;

            outw(master_volume, 0);
            outw(pcm_volume, 0);

            let bus_master = self.bus_master as u16;

            let po_bdbar = bus_master + 0x10;
            let po_civ = bus_master + 0x14;
            let po_lvi = bus_master + 0x15;
            let po_sr = bus_master + 0x16;
            let po_picb = bus_master + 0x18;
            let po_piv = bus_master + 0x1A;
            let po_cr = bus_master + 0x1B;
            let glob_cnt = bus_master + 0x2C;
            let glob_sta = bus_master + 0x30;

            outb(po_cr, 0);

            let mut bdl = ind(po_bdbar) as *mut BD;
            if bdl as usize == 0 {
                bdl = alloc(32 * size_of::<BD>()) as *mut BD;
                outd(po_bdbar, bdl as u32);
            }

            for i in 0..32 {
                ptr::write(bdl.offset(i), BD {
                    ptr: 0,
                    samples: 0
                });
            }

            let mut wait = false;
            let mut position = 0;

            let mut lvi = inb(po_lvi);

            let start_lvi;
            if lvi == 0 {
                start_lvi = 31;
            }else{
                start_lvi = lvi - 1;
            }

            lvi += 1;
            if lvi >= 32 {
                lvi = 0;
            }
            loop {
                while wait {
                    if inb(po_civ) != lvi as u8 {
                        break;
                    }
                    Duration::new(0, 100000000).sleep();
                }

                dd(inb(po_civ) as usize);
                d(" / ");
                dd(lvi as usize);
                d(": ");
                dd(position);
                d(" / ");
                dd(buf.len());
                dl();

                let bytes = min(65534 * 2, (buf.len() - position + 1));
                let samples = bytes/2;

                ptr::write(bdl.offset(lvi as isize), BD {
                    ptr: buf.as_ptr().offset(position as isize) as u32,
                    samples: (samples & 0xFFFF) as u32
                });

                position += bytes;

                if position >= buf.len() {
                    break;
                }

                lvi += 1;

                if lvi >= 32 {
                    lvi = 0;
                }

                if lvi == start_lvi {
                    outb(po_lvi, start_lvi);
                    outb(po_cr, 1);
                    wait = true;
                }
            }

            outb(po_lvi, lvi);
            outb(po_cr, 1);

            loop {
                if inb(po_civ) == lvi {
                    outb(po_cr, 0);
                    break;
                }
                Duration::new(0, 100000000).sleep();
            }

            d("Finished ");
            dd(inb(po_civ) as usize);
            d(" / ");
            dd(lvi as usize);
            dl();
        }

        return Option::Some(buf.len());
    }

    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        return Option::None;
    }

    fn flush(&mut self) -> bool {
        return false;
    }
}

pub struct AC97 {
    pub audio: usize,
    pub bus_master: usize,
    pub irq: u8
}

impl SessionItem for AC97 {
    fn scheme(&self) -> String {
        return "audio".to_string();
    }

    fn open(&mut self, url: &URL) -> Box<Resource> {
        return box AC97Resource {
            audio: self.audio,
            bus_master: self.bus_master
        };
    }

    fn on_irq(&mut self, irq: u8){
        if irq == self.irq {
            d("AC97 IRQ\n");
        }
    }

    fn on_poll(&mut self){
    }
}

impl AC97 {
    pub unsafe fn new(bus: usize, slot: usize, func: usize) -> Box<AC97> {
        pci_write(bus, slot, func, 0x04, pci_read(bus, slot, func, 0x04) | (1 << 2)); // Bus mastering

        let mut module = box AC97 {
            audio: pci_read(bus, slot, 0, 0x10) & 0xFFFFFFF0,
            bus_master: pci_read(bus, slot, 0, 0x14) & 0xFFFFFFF0,
            irq: pci_read(bus, slot, func, 0x3C) as u8 & 0xF
        };

        module.init();

        return module;
    }

    pub unsafe fn init(&self){
        d("AC97 on: ");
        dh(self.audio);
        d(", ");
        dh(self.bus_master);
        d(", IRQ: ");
        dbh(self.irq);

        dl();
    }
}
<commit_msg>Wait for other files<commit_after>use core::ptr::{read, write};

use common::memory::*;
use common::pci::*;
use common::pio::*;
use common::scheduler::*;

use programs::common::*;

#[repr(packed)]
struct BD {
    ptr: u32,
    samples: u32
}

struct AC97Resource {
    audio: usize,
    bus_master: usize
}

impl Resource for AC97Resource {
    fn url(&self) -> URL {
        return URL::from_string(&"audio://".to_string());
    }

    fn stat(&self) -> ResourceType {
        return ResourceType::File;
    }

    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        return Option::None;
    }

    fn read_to_end(&mut self, vec: &mut Vec<u8>) -> Option<usize> {
        return Option::None;
    }

    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        unsafe {
            let audio = self.audio as u16;
            let master_volume = audio + 2;
            let pcm_volume = audio + 0x18;

            outw(master_volume, 0);
            outw(pcm_volume, 0);

            let bus_master = self.bus_master as u16;

            let po_bdbar = bus_master + 0x10;
            let po_civ = bus_master + 0x14;
            let po_lvi = bus_master + 0x15;
            let po_sr = bus_master + 0x16;
            let po_picb = bus_master + 0x18;
            let po_piv = bus_master + 0x1A;
            let po_cr = bus_master + 0x1B;
            let glob_cnt = bus_master + 0x2C;
            let glob_sta = bus_master + 0x30;

            loop {
                if inb(po_cr) & 1 == 0 {
                    break;
                }
                Duration::new(0, 10000000).sleep();
            }

            outb(po_cr, 0);

            let mut bdl = ind(po_bdbar) as *mut BD;
            if bdl as usize == 0 {
                bdl = alloc(32 * size_of::<BD>()) as *mut BD;
                outd(po_bdbar, bdl as u32);
            }

            for i in 0..32 {
                ptr::write(bdl.offset(i), BD {
                    ptr: 0,
                    samples: 0
                });
            }

            let mut wait = false;
            let mut position = 0;

            let mut lvi = inb(po_lvi);

            let start_lvi;
            if lvi == 0 {
                start_lvi = 31;
            }else{
                start_lvi = lvi - 1;
            }

            lvi += 1;
            if lvi >= 32 {
                lvi = 0;
            }
            loop {
                while wait {
                    if inb(po_civ) != lvi as u8 {
                        break;
                    }
                    Duration::new(0, 10000000).sleep();
                }

                dd(inb(po_civ) as usize);
                d(" / ");
                dd(lvi as usize);
                d(": ");
                dd(position);
                d(" / ");
                dd(buf.len());
                dl();

                let bytes = min(65534 * 2, (buf.len() - position + 1));
                let samples = bytes/2;

                ptr::write(bdl.offset(lvi as isize), BD {
                    ptr: buf.as_ptr().offset(position as isize) as u32,
                    samples: (samples & 0xFFFF) as u32
                });

                position += bytes;

                if position >= buf.len() {
                    break;
                }

                lvi += 1;

                if lvi >= 32 {
                    lvi = 0;
                }

                if lvi == start_lvi {
                    outb(po_lvi, start_lvi);
                    outb(po_cr, 1);
                    wait = true;
                }
            }

            outb(po_lvi, lvi);
            outb(po_cr, 1);

            loop {
                if inb(po_civ) == lvi {
                    outb(po_cr, 0);
                    break;
                }
                Duration::new(0, 10000000).sleep();
            }

            d("Finished ");
            dd(inb(po_civ) as usize);
            d(" / ");
            dd(lvi as usize);
            dl();
        }

        return Option::Some(buf.len());
    }

    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        return Option::None;
    }

    fn flush(&mut self) -> bool {
        return false;
    }
}

pub struct AC97 {
    pub audio: usize,
    pub bus_master: usize,
    pub irq: u8
}

impl SessionItem for AC97 {
    fn scheme(&self) -> String {
        return "audio".to_string();
    }

    fn open(&mut self, url: &URL) -> Box<Resource> {
        return box AC97Resource {
            audio: self.audio,
            bus_master: self.bus_master
        };
    }

    fn on_irq(&mut self, irq: u8){
        if irq == self.irq {
            d("AC97 IRQ\n");
        }
    }

    fn on_poll(&mut self){
    }
}

impl AC97 {
    pub unsafe fn new(bus: usize, slot: usize, func: usize) -> Box<AC97> {
        pci_write(bus, slot, func, 0x04, pci_read(bus, slot, func, 0x04) | (1 << 2)); // Bus mastering

        let mut module = box AC97 {
            audio: pci_read(bus, slot, 0, 0x10) & 0xFFFFFFF0,
            bus_master: pci_read(bus, slot, 0, 0x14) & 0xFFFFFFF0,
            irq: pci_read(bus, slot, func, 0x3C) as u8 & 0xF
        };

        module.init();

        return module;
    }

    pub unsafe fn init(&self){
        d("AC97 on: ");
        dh(self.audio);
        d(", ");
        dh(self.bus_master);
        d(", IRQ: ");
        dbh(self.irq);

        dl();
    }
}
<|endoftext|>


<commit_before><commit_msg>Added some prototype matrix debugging code<commit_after><|endoftext|>


<commit_before>use super::*;
use redox::*;

impl Editor {
    /// Redraw the window
    pub fn redraw(&mut self) {
        // TODO: Only draw when relevant for the window
        let x = self.x();
        let y = self.y();
        // Redraw window
        self.window.set(Color::BLACK);

        self.window.rect(8 * (x - self.scroll_y) as isize,
                         16 * (y - self.scroll_x) as isize,
                         8,
                         16,
                         Color::WHITE);

        for (y, row) in self.text.iter().enumerate() {
            for (x, c) in row.iter().enumerate() {
                if self.x() == x && self.y() == y {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     Color::BLACK);
                } else {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     Color::WHITE);
                }
            }
        }
        let h = self.window.height();
        let w = self.window.width();
        self.window.rect(0, h as isize - 18, w, 18, Color::rgba(74, 74, 74, 255));

        let mut string = false;

        for (n, c) in (if self.status_bar.mode.len() > w / (8 * 4) {
            self.status_bar.mode.chars().take(w / (8 * 4) - 5).chain(vec!['.', '.', '.']).collect::<Vec<_>>()
        } else {
            self.status_bar.mode.chars().collect()
        }).into_iter().enumerate() {
            let color = match c {
                _ if string => Color::BLUE,
                '\'' | '"' => {
                    string = true;
                    Color::RED
                },
                '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '+' | '-' | '/' | ':' | '=' | '<' | '>' => Color::RED,
                '.' | ',' => Color::BLUE,
                '(' | ')' | '[' | ']' | '{' | '}' => Color::GREEN,
                _ => Color::WHITE,
            };

            self.window.char(n as isize * 8, h as isize - 16 - 1, if c == '\t' { ' ' } else { c }, color);
        }

        self.window.sync();
    }
}

/// The statubar (showing various info about the current state of the editor)
pub struct StatusBar {
    /// The current mode
    pub mode: String,
    /// The cureent char
    pub file: String,
    /// The current command
    pub cmd: String,
    /// A message (such as an error or other info to the user)
    pub msg: String,
}

impl StatusBar {
    /// Create new status bar
    pub fn new() -> Self {
        StatusBar {
            mode: "Normal".to_string(),
            file: String::new(),
            cmd: String::new(),
            msg: String::new(),
        }
    }
}
<commit_msg>Fix highlighting<commit_after>use super::*;
use redox::*;

impl Editor {
    /// Redraw the window
    pub fn redraw(&mut self) {
        // TODO: Only draw when relevant for the window
        let x = self.x();
        let y = self.y();
        // Redraw window
        self.window.set(Color::BLACK);

        self.window.rect(8 * (x - self.scroll_y) as isize,
                         16 * (y - self.scroll_x) as isize,
                         8,
                         16,
                         Color::WHITE);

        let mut string = false;

        for (y, row) in self.text.iter().enumerate() {
            for (x, &c) in row.iter().enumerate() {
                let color = match c {
                    '\'' | '"' => {
                        string = !string;
                        (226, 225, 167) //(167, 222, 156)
                    },
                    _ if string => (226, 225, 167), //(167, 222, 156)
                    '!' | '@' | '#' | '$' | '%' | '^' | '&' | '|' | '*' | '+' | '-' | '/' | ':' | '=' | '<' | '>' => (198, 83, 83), //(228, 190, 175), //(194, 106, 71),
                    '.' | ',' => (241, 213, 226),
                    '(' | ')' | '[' | ']' | '{' | '}' => (164, 212, 125), //(195, 139, 75),
                    '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => (209, 209, 177),
                    _ => (255, 255, 255),
                };

                if self.x() == x && self.y() == y {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     c,
                                     Color::rgb(color.0 / 3, color.1 / 3, color.2 / 3));
                } else {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     c,
                                     Color::rgb(color.0, color.1, color.2));
                }
            }
        }
        let h = self.window.height();
        let w = self.window.width();
        self.window.rect(0, h as isize - 18, w, 18, Color::rgba(74, 74, 74, 255));

        for (n, c) in (if self.status_bar.mode.len() > w / (8 * 4) {
            self.status_bar.mode.chars().take(w / (8 * 4) - 5).chain(vec!['.', '.', '.']).collect::<Vec<_>>()
        } else {
            self.status_bar.mode.chars().collect()
        }).into_iter().enumerate() {

            self.window.char(n as isize * 8, h as isize - 16 - 1, if c == '\t' { ' ' } else { c }, Color::RED);
        }

        self.window.sync();
    }
}

/// The statubar (showing various info about the current state of the editor)
pub struct StatusBar {
    /// The current mode
    pub mode: String,
    /// The cureent char
    pub file: String,
    /// The current command
    pub cmd: String,
    /// A message (such as an error or other info to the user)
    pub msg: String,
}

impl StatusBar {
    /// Create new status bar
    pub fn new() -> Self {
        StatusBar {
            mode: "Normal".to_string(),
            file: String::new(),
            cmd: String::new(),
            msg: String::new(),
        }
    }
}
<|endoftext|>