<commit_before>#![feature(macro_rules)]

macro_rules! return_if_some(
    ($arg:expr) => (
        match $arg {
            Some(val) => return val,
            None => {},
        }
    );
)

pub fn pathmatch(pattern: &str, pathstring: &str) -> bool
{
    use std::str::Chars;
    let pattern_chars = cursor(pattern);
    let mut path_chars = cursor(pathstring);
    return pathmatch_impl(pattern_chars, &mut path_chars, false);

    #[deriving(Clone)]
    struct Cursor<'a>
    {
        chars: Chars<'a>,
        at_the_beginning: bool,
    }

    fn cursor<'a>(arg: &'a str) -> Cursor<'a>
    {
        Cursor { chars: arg.chars(), at_the_beginning: true }
    }

    impl<'a> Cursor<'a>
    {
        fn clone_times_next(&'a self, n: int) -> Cursor<'a>
        {
            let mut rv = self.clone();
            for _ in range(0, n) {
                if None == rv.next() { break }
            }
            return rv
        }
    }

    impl<'a> Iterator<char> for Cursor<'a>
    {
        fn next<'a>(&mut self) -> Option<char>
        {
            self.at_the_beginning = false;
            return self.chars.next();
        }
    }

    fn pathmatch_impl(mut pattern_chars: Cursor, path_chars: &mut Cursor, alt_branch_mode: bool) -> bool
    {
        if path_chars.at_the_beginning && char_iter_equals(pattern_chars, "**/", alt_branch_mode, true) {
            if !path_chars.peekable().is_empty() && pathmatch_try(pattern_chars.clone_times_next(3), path_chars, alt_branch_mode) {
                return true;
            }
        }
        loop {
            if !path_chars.at_the_beginning && char_iter_equals(pattern_chars, "/**", alt_branch_mode, false) && path_chars.peekable().is_empty() {
                return true;
            }
            match pattern_chars.next() {
                None => return path_chars.next().is_none(),
                Some('?') => match path_chars.next() {
                    None | Some('/') => return false,
                    _ => (),
                },
                Some('*') => match pattern_chars.peekable().peek() {
                    Some(&'*') => {
                        pattern_chars.next();
                        return_if_some!(match_any(pattern_chars, path_chars, alt_branch_mode, true));
                    },
                    _ => return_if_some!(match_any(pattern_chars, path_chars, alt_branch_mode, false)),
                },
                Some('/') => {
                    return_if_some!(match_exact('/', path_chars.next(), alt_branch_mode));
                    if char_iter_equals(pattern_chars, "**/", alt_branch_mode, true) {
                        if pathmatch_try(pattern_chars.clone_times_next(3), path_chars, alt_branch_mode) {
                            return true;
                        }
                    }
                },
                Some('{') => {
                    let mut matched_something = false;
                    loop {
                        if !matched_something && pathmatch_try(pattern_chars, path_chars, true) {
                            matched_something = true;
                        }
                        match skip_alt_branch(&mut pattern_chars) {
                            Some(false) => break,
                            Some(true) => {},
                            None => /* error in pattern */ return false,
                        }
                    }
                    if !matched_something {
                        return false;
                    }
                },
                Some(',') | Some('}') if alt_branch_mode => return true,
                Some(pc) => return_if_some!(match_exact(pc, path_chars.next(), alt_branch_mode)),
            }
        }
    }

    fn pathmatch_try(pattern_chars: Cursor, path_chars: &mut Cursor, alt_branch_mode: bool) -> bool
    {
        let mut path_chars_copy = path_chars.clone();
        if pathmatch_impl(pattern_chars, &mut path_chars_copy, alt_branch_mode) {
            *path_chars = path_chars_copy;
            return true;
        }
        return false;
    }

    fn skip_alt_branch(pattern_chars: &mut Cursor) -> Option<bool>
    {
        loop {
            match pattern_chars.next() {
                Some(',') => return Some(true),
                Some('}') => return Some(false),
                Some('{') => loop {
                    match skip_alt_branch(pattern_chars)
                    {
                        Some(true) => {},
                        Some(false) => break,
                        None => return None,
                    }
                },
                None => return None,
                _ => {},
            }
        }
    }

    fn match_any(pattern_chars: Cursor, path_chars: &mut Cursor, alt_branch_mode: bool, allow_pathsep: bool) -> Option<bool>
    {
        loop {
            if pathmatch_try(pattern_chars, path_chars, alt_branch_mode) {
                return Some(true);
            }
            match path_chars.next() {
                None => return None,
                Some('/') if !allow_pathsep => return Some(false),
                _ => {},
            }
        }
    }

    fn match_exact(pattern_char: char, path_char: Option<char>, alt_branch_mode: bool) -> Option<bool>
    {
        match path_char {
            None => return Some(false),
            Some(',') | Some('}') if alt_branch_mode => return Some(false),
            Some(x) if x != pattern_char => return Some(false),
            _ => return None,
        }
    }

    fn char_iter_equals(mut char_iter: Cursor, needle: &str, alt_branch_mode: bool, startswith: bool) -> bool
    {
        for needle_char in needle.chars() {
            match char_iter.next() {
                Some(x) if x == needle_char => (),
                _ => return false,
            }
        }
        if startswith { true }
        else if alt_branch_mode {
            match char_iter.next() {
                Some(',') | Some('}') => true,
                _ => false,
            }
        } else { char_iter.next().is_none() }
    }
}

#[cfg(test)]
fn assert_pathmatch_many(pattern: &str, paths_yes: &[&str], paths_no: &[&str])
{
    for path in paths_yes.iter() {
        assert!(pathmatch(pattern, *path), "should match: pattern:'{}' path:'{}'", pattern, path);
    }
    for path in paths_no.iter() {
        assert!(!pathmatch(pattern, *path), "must not match: pattern:'{}' path:'{}'", pattern, path);
    }
}

#[test]
fn pathmatch_test_regressions()
{
    assert_pathmatch_many("{*.foo,bar,**/{one,two}}", &["1.foo", "2.foo", ".foo", "bar", "one", "two", "three/one"], &["foo"]);
}

#[test]
fn pathmatch_test_alt_combos()
{
    assert_pathmatch_many("a{?,/}c", &["abc", "a/c"], &["ac", "abbc"]);
    assert_pathmatch_many("{foo/**,**/bar}", &["foo", "bar"], &["foobar"]);
    assert_pathmatch_many("{foo/**,bar}baz", &["barbaz", "foo/baz"], &["foobaz"]);
    assert_pathmatch_many("foo{bar,**/baz}", &["foobar", "foo/baz"], &["foobaz"]);
    assert!(!pathmatch("{**/}", ""));
    assert!(!pathmatch("{{**/}}", ""));
}

#[test]
fn pathmatch_test_alt()
{
    assert!(pathmatch("{foo}", "foo"));
    assert_pathmatch_many("{foo,bar,baz}", &["foo", "bar", "baz"], &["", "foobarbaz", "qux"]);
    assert_pathmatch_many("{foo,bar}", &["foo", "bar"], &["", "foobar"]);
    assert!(pathmatch("{}", ""));
    assert!(!pathmatch("{}", "{}"));
    assert!(pathmatch("{foo}{bar}", "foobar"));
    assert!(pathmatch("{foo}*{bar}", "foobar"));
    assert!(pathmatch("{foo}*{bar}", "fooXXbar"));
}

#[test]
fn pathmatch_test_collapse()
{
    // `/**/` may match a single slash.
    assert!(pathmatch("foo/**/bar", "foo/bar"));
    assert!(pathmatch("foo/**/", "foo/"));
    assert!(!pathmatch("foo/**/", "foo"));
    assert!(pathmatch("/**/bar", "/bar"));
    assert!(!pathmatch("/**/bar", "bar"));
    // to prevent this behavior, you would use this
    assert!(!pathmatch("foo/*/**/bar", "foo/bar"));
    assert!(!pathmatch("foo/**/*/bar", "foo/bar"));
    assert!(pathmatch("foo/**/bar", "foo//bar"));
    assert!(pathmatch("foo/*/**/bar", "foo//bar"));
}

#[test]
fn pathmatch_test_anypath_leading()
{
    // `**/` at the beginning of pattern may match nothing.
    assert!(pathmatch("**/bar", "bar"));
    assert!(pathmatch("**/bar", "/bar"));
    assert!(!pathmatch("a**/bar", "abar"));
    assert!(!pathmatch("*/bar", "bar"));
    assert!(!pathmatch("**/", ""));
}

#[test]
fn pathmatch_test_anypath_trailing()
{
    // `/**` at the end of pattern may match nothing.
    assert!(pathmatch("foo/**", "foo"));
    assert!(pathmatch("foo/**", "foo/"));
    assert!(!pathmatch("foo/**g", "foog"));
    assert!(!pathmatch("foo/*", "foo"));
    assert!(!pathmatch("/**", ""));
    assert!(pathmatch("/**", "/"));
}

#[test]
fn pathmatch_test_anypath()
{
    assert!(pathmatch("**", ""));
    assert!(pathmatch("a**", "a/b/c"));
    assert!(pathmatch("**c", "a/b/c"));
    assert!(pathmatch("a**c", "a/b/c"));
    assert!(pathmatch("a/**/c", "a/b/c"));
    assert!(pathmatch("**/c", "a/b/c"));
    assert!(!pathmatch("**/g", "e/fg"));
    assert!(pathmatch("a/**", "a/b/c"));
    assert!(!pathmatch("e/**", "ef/g"));
}

#[test]
fn pathmatch_test_pathsep()
{
    assert!(!pathmatch("a?b", "a/b"));
    assert!(!pathmatch("a*b", "a/b"));
    assert!(pathmatch("a*/b", "a/b"));
    assert!(pathmatch("a/*b", "a/b"));
}

#[test]
fn pathmatch_test_anyname()
{
    assert!(pathmatch("*", ""));
    assert!(pathmatch("*", "?"));
    assert!(pathmatch("*", "d?F"));
    assert!(pathmatch("a*", "a"));
    assert!(pathmatch("a*", "abcdef"));
    assert!(pathmatch("*f", "abcdef"));
    assert!(pathmatch("a*f", "abcdef"));
    assert!(pathmatch("*cd*", "abcdef"));
    assert!(pathmatch("a*cd*f", "abcdef"));
    assert!(pathmatch("acdf", "acdf"));
    assert!(!pathmatch("*a", "abc"));
    assert!(!pathmatch("c*", "abc"));
}

#[test]
fn pathmatch_test_anychar()
{
    assert!(pathmatch("?", "?"));
    assert!(pathmatch("?", "a"));
    assert!(pathmatch("??", "BC"));
    assert!(pathmatch("B?", "BC"));
    assert!(pathmatch("?C", "BC"));
    assert!(!pathmatch("?", ""));
    assert!(!pathmatch("D?", "BC"));
    assert!(!pathmatch("?E", "BC"));
}

#[test]
fn pathmatch_test_exact_equality()
{
    assert!(pathmatch("", ""));
    assert!(pathmatch("a", "a"));
    assert!(pathmatch("BC", "BC"));
    assert!(!pathmatch("a", ""));
    assert!(!pathmatch("", "BC"));
}

<commit_msg>fixed compilation with the nightly<commit_after>use std::clone::Clone;

macro_rules! return_if_some {
    ($arg:expr) => (
        match $arg {
            Some(val) => return val,
            None => {},
        }
    );
}

pub fn pathmatch(pattern: &str, pathstring: &str) -> bool
{
    use std::str::Chars;
    let pattern_chars = cursor(pattern);
    let mut path_chars = cursor(pathstring);
    return pathmatch_impl(pattern_chars, &mut path_chars, false);

    #[derive(Clone,Copy)]
    struct Cursor<'a>
    {
        chars: Chars<'a>,
        at_the_beginning: bool,
    }

    fn cursor<'a>(arg: &'a str) -> Cursor<'a>
    {
        Cursor { chars: arg.chars(), at_the_beginning: true }
    }

    impl<'a> Cursor<'a>
    {
        fn clone_times_next(&'a self, n: u8) -> Cursor<'a>
        {
            let mut rv = self.clone();
            for _ in range(0, n) {
                if None == rv.next() { break }
            }
            return rv
        }
    }

    impl<'a> Iterator for Cursor<'a>
    {
        type Item = char;

        fn next(&mut self) -> Option<char>
        {
            self.at_the_beginning = false;
            return self.chars.next();
        }
    }

    fn pathmatch_impl(mut pattern_chars: Cursor, path_chars: &mut Cursor, alt_branch_mode: bool) -> bool
    {
        if path_chars.at_the_beginning && char_iter_equals(pattern_chars, "**/", alt_branch_mode, true) {
            if !path_chars.peekable().is_empty() && pathmatch_try(pattern_chars.clone_times_next(3), path_chars, alt_branch_mode) {
                return true;
            }
        }
        loop {
            if !path_chars.at_the_beginning && char_iter_equals(pattern_chars, "/**", alt_branch_mode, false) && path_chars.peekable().is_empty() {
                return true;
            }
            match pattern_chars.next() {
                None => return path_chars.next().is_none(),
                Some('?') => match path_chars.next() {
                    None | Some('/') => return false,
                    _ => (),
                },
                Some('*') => match pattern_chars.peekable().peek() {
                    Some(&'*') => {
                        pattern_chars.next();
                        return_if_some!(match_any(pattern_chars, path_chars, alt_branch_mode, true));
                    },
                    _ => return_if_some!(match_any(pattern_chars, path_chars, alt_branch_mode, false)),
                },
                Some('/') => {
                    return_if_some!(match_exact('/', path_chars.next(), alt_branch_mode));
                    if char_iter_equals(pattern_chars, "**/", alt_branch_mode, true) {
                        if pathmatch_try(pattern_chars.clone_times_next(3), path_chars, alt_branch_mode) {
                            return true;
                        }
                    }
                },
                Some('{') => {
                    let mut matched_something = false;
                    loop {
                        if !matched_something && pathmatch_try(pattern_chars, path_chars, true) {
                            matched_something = true;
                        }
                        match skip_alt_branch(&mut pattern_chars) {
                            Some(false) => break,
                            Some(true) => {},
                            None => /* error in pattern */ return false,
                        }
                    }
                    if !matched_something {
                        return false;
                    }
                },
                Some(',') | Some('}') if alt_branch_mode => return true,
                Some(pc) => return_if_some!(match_exact(pc, path_chars.next(), alt_branch_mode)),
            }
        }
    }

    fn pathmatch_try(pattern_chars: Cursor, path_chars: &mut Cursor, alt_branch_mode: bool) -> bool
    {
        let mut path_chars_copy = path_chars.clone();
        if pathmatch_impl(pattern_chars, &mut path_chars_copy, alt_branch_mode) {
            *path_chars = path_chars_copy;
            return true;
        }
        return false;
    }

    fn skip_alt_branch(pattern_chars: &mut Cursor) -> Option<bool>
    {
        loop {
            match pattern_chars.next() {
                Some(',') => return Some(true),
                Some('}') => return Some(false),
                Some('{') => loop {
                    match skip_alt_branch(pattern_chars)
                    {
                        Some(true) => {},
                        Some(false) => break,
                        None => return None,
                    }
                },
                None => return None,
                _ => {},
            }
        }
    }

    fn match_any(pattern_chars: Cursor, path_chars: &mut Cursor, alt_branch_mode: bool, allow_pathsep: bool) -> Option<bool>
    {
        loop {
            if pathmatch_try(pattern_chars, path_chars, alt_branch_mode) {
                return Some(true);
            }
            match path_chars.next() {
                None => return None,
                Some('/') if !allow_pathsep => return Some(false),
                _ => {},
            }
        }
    }

    fn match_exact(pattern_char: char, path_char: Option<char>, alt_branch_mode: bool) -> Option<bool>
    {
        match path_char {
            None => return Some(false),
            Some(',') | Some('}') if alt_branch_mode => return Some(false),
            Some(x) if x != pattern_char => return Some(false),
            _ => return None,
        }
    }

    fn char_iter_equals(mut char_iter: Cursor, needle: &str, alt_branch_mode: bool, startswith: bool) -> bool
    {
        for needle_char in needle.chars() {
            match char_iter.next() {
                Some(x) if x == needle_char => (),
                _ => return false,
            }
        }
        if startswith { true }
        else if alt_branch_mode {
            match char_iter.next() {
                Some(',') | Some('}') => true,
                _ => false,
            }
        } else { char_iter.next().is_none() }
    }
}

#[cfg(test)]
fn assert_pathmatch_many(pattern: &str, paths_yes: &[&str], paths_no: &[&str])
{
    for path in paths_yes.iter() {
        assert!(pathmatch(pattern, *path), "should match: pattern:'{}' path:'{}'", pattern, path);
    }
    for path in paths_no.iter() {
        assert!(!pathmatch(pattern, *path), "must not match: pattern:'{}' path:'{}'", pattern, path);
    }
}

#[test]
fn pathmatch_test_regressions()
{
    assert_pathmatch_many("{*.foo,bar,**/{one,two}}", &["1.foo", "2.foo", ".foo", "bar", "one", "two", "three/one"], &["foo"]);
}

#[test]
fn pathmatch_test_alt_combos()
{
    assert_pathmatch_many("a{?,/}c", &["abc", "a/c"], &["ac", "abbc"]);
    assert_pathmatch_many("{foo/**,**/bar}", &["foo", "bar"], &["foobar"]);
    assert_pathmatch_many("{foo/**,bar}baz", &["barbaz", "foo/baz"], &["foobaz"]);
    assert_pathmatch_many("foo{bar,**/baz}", &["foobar", "foo/baz"], &["foobaz"]);
    assert!(!pathmatch("{**/}", ""));
    assert!(!pathmatch("{{**/}}", ""));
}

#[test]
fn pathmatch_test_alt()
{
    assert!(pathmatch("{foo}", "foo"));
    assert_pathmatch_many("{foo,bar,baz}", &["foo", "bar", "baz"], &["", "foobarbaz", "qux"]);
    assert_pathmatch_many("{foo,bar}", &["foo", "bar"], &["", "foobar"]);
    assert!(pathmatch("{}", ""));
    assert!(!pathmatch("{}", "{}"));
    assert!(pathmatch("{foo}{bar}", "foobar"));
    assert!(pathmatch("{foo}*{bar}", "foobar"));
    assert!(pathmatch("{foo}*{bar}", "fooXXbar"));
}

#[test]
fn pathmatch_test_collapse()
{
    // `/**/` may match a single slash.
    assert!(pathmatch("foo/**/bar", "foo/bar"));
    assert!(pathmatch("foo/**/", "foo/"));
    assert!(!pathmatch("foo/**/", "foo"));
    assert!(pathmatch("/**/bar", "/bar"));
    assert!(!pathmatch("/**/bar", "bar"));
    // to prevent this behavior, you would use this
    assert!(!pathmatch("foo/*/**/bar", "foo/bar"));
    assert!(!pathmatch("foo/**/*/bar", "foo/bar"));
    assert!(pathmatch("foo/**/bar", "foo//bar"));
    assert!(pathmatch("foo/*/**/bar", "foo//bar"));
}

#[test]
fn pathmatch_test_anypath_leading()
{
    // `**/` at the beginning of pattern may match nothing.
    assert!(pathmatch("**/bar", "bar"));
    assert!(pathmatch("**/bar", "/bar"));
    assert!(!pathmatch("a**/bar", "abar"));
    assert!(!pathmatch("*/bar", "bar"));
    assert!(!pathmatch("**/", ""));
}

#[test]
fn pathmatch_test_anypath_trailing()
{
    // `/**` at the end of pattern may match nothing.
    assert!(pathmatch("foo/**", "foo"));
    assert!(pathmatch("foo/**", "foo/"));
    assert!(!pathmatch("foo/**g", "foog"));
    assert!(!pathmatch("foo/*", "foo"));
    assert!(!pathmatch("/**", ""));
    assert!(pathmatch("/**", "/"));
}

#[test]
fn pathmatch_test_anypath()
{
    assert!(pathmatch("**", ""));
    assert!(pathmatch("a**", "a/b/c"));
    assert!(pathmatch("**c", "a/b/c"));
    assert!(pathmatch("a**c", "a/b/c"));
    assert!(pathmatch("a/**/c", "a/b/c"));
    assert!(pathmatch("**/c", "a/b/c"));
    assert!(!pathmatch("**/g", "e/fg"));
    assert!(pathmatch("a/**", "a/b/c"));
    assert!(!pathmatch("e/**", "ef/g"));
}

#[test]
fn pathmatch_test_pathsep()
{
    assert!(!pathmatch("a?b", "a/b"));
    assert!(!pathmatch("a*b", "a/b"));
    assert!(pathmatch("a*/b", "a/b"));
    assert!(pathmatch("a/*b", "a/b"));
}

#[test]
fn pathmatch_test_anyname()
{
    assert!(pathmatch("*", ""));
    assert!(pathmatch("*", "?"));
    assert!(pathmatch("*", "d?F"));
    assert!(pathmatch("a*", "a"));
    assert!(pathmatch("a*", "abcdef"));
    assert!(pathmatch("*f", "abcdef"));
    assert!(pathmatch("a*f", "abcdef"));
    assert!(pathmatch("*cd*", "abcdef"));
    assert!(pathmatch("a*cd*f", "abcdef"));
    assert!(pathmatch("acdf", "acdf"));
    assert!(!pathmatch("*a", "abc"));
    assert!(!pathmatch("c*", "abc"));
}

#[test]
fn pathmatch_test_anychar()
{
    assert!(pathmatch("?", "?"));
    assert!(pathmatch("?", "a"));
    assert!(pathmatch("??", "BC"));
    assert!(pathmatch("B?", "BC"));
    assert!(pathmatch("?C", "BC"));
    assert!(!pathmatch("?", ""));
    assert!(!pathmatch("D?", "BC"));
    assert!(!pathmatch("?E", "BC"));
}

#[test]
fn pathmatch_test_exact_equality()
{
    assert!(pathmatch("", ""));
    assert!(pathmatch("a", "a"));
    assert!(pathmatch("BC", "BC"));
    assert!(!pathmatch("a", ""));
    assert!(!pathmatch("", "BC"));
}

<|endoftext|>


<commit_before>mod mtl_device;
mod mtl_command_buffer;
mod mtl_command_queue;

pub use self::mtl_command_buffer::MTLCommandBuffer;
pub use self::mtl_command_queue::MTLCommandQueue;
pub use self::mtl_device::MTLDevice;
pub use self::mtl_device::{MTLNewComputePipelineStateCompletionHandler,
                           MTLNewComputePipelineStateWithReflectionCompletionHandler, MTLNewLibraryCompletionHandler,
                           MTLNewRenderPipelineStateWithReflectionCompletionHandler,
                           MTLNewRenderPipleineStateCompletionHandler};
pub use self::mtl_drawable::MTLDrawable;
<commit_msg>Forgot to declare mod which `MTLDrawable` is defined in<commit_after>mod mtl_command_buffer;
mod mtl_command_queue;
mod mtl_device;
mod mtl_drawable;

pub use self::mtl_command_buffer::MTLCommandBuffer;
pub use self::mtl_command_queue::MTLCommandQueue;
pub use self::mtl_device::MTLDevice;
pub use self::mtl_device::{MTLNewComputePipelineStateCompletionHandler,
                           MTLNewComputePipelineStateWithReflectionCompletionHandler, MTLNewLibraryCompletionHandler,
                           MTLNewRenderPipelineStateWithReflectionCompletionHandler,
                           MTLNewRenderPipleineStateCompletionHandler};
pub use self::mtl_drawable::MTLDrawable;
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// 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
//
//     https://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.

//! Driver for the UART controllers capable of sending and receiving data
//! asynchronously.
//!
//! The UART has a configurable baud rate and can run with or without hardware
//! flow-control. There is no DMA for the UART, but it has a 32-character deep
//! FIFO transmit and receive buffer.
//!
//! # Examples
//!
//! Before using the UART you must configure the TX and/or RX pins and set the
//! baud rate:w
//!
//! ```
//! let uart = &h1b::uart::UART0;
//! let pinmux = unsafe { &mut *h1b::pinmux::PINMUX };
//! pinmux.dioa0.select.set(h1b::pinmux::Function::Uart0Tx);
//! uart.config(115200);
//! uart.enable_tx();
//! ```
//! Then, you can (unsafely) send bytes synchronously (e.g. for debugging)
//!
//! ```
//! uart.send_bytes_sync("Debug string".as_bytes());
//! ```
//!
//! Or asynchornously:
//!
//! ```
//! uart.send_bytes("Pretend I'm a very long string").as_bytes());
//! ```
//! you'll be notified of completion through a callback
//!
//! TODO
//!

use core::cell::Cell;
use kernel::common::cells::TakeCell;
use kernel::common::cells::VolatileCell;
use kernel::hil;
use kernel::ReturnCode;
use pmu::{Clock, PeripheralClock, PeripheralClock1};

/// Registers for the UART controller
#[allow(dead_code)]
struct Registers {
    read_data: VolatileCell<u32>,
    write_data: VolatileCell<u32>,
    nco: VolatileCell<u32>,
    control: VolatileCell<u32>,
    interrupt_control: VolatileCell<u32>,
    state: VolatileCell<u32>,
    clear_state: VolatileCell<u32>,
    interrupt_state: VolatileCell<u32>,
    clear_interrupt_state: VolatileCell<u32>,
}

const UART0_BASE: *mut Registers = 0x40600000 as *mut Registers;
const UART1_BASE: *mut Registers = 0x40610000 as *mut Registers;
const UART2_BASE: *mut Registers = 0x40620000 as *mut Registers;

pub static mut UART0: UART = unsafe { UART::new(UART0_BASE, PeripheralClock1::Uart0Timer) };

pub static mut UART1: UART = unsafe { UART::new(UART1_BASE, PeripheralClock1::Uart1Timer) };

pub static mut UART2: UART = unsafe { UART::new(UART2_BASE, PeripheralClock1::Uart2Timer) };

// A resumable buffer that tracks the last written index
//struct Buffer {
//    bytes: &'static mut [u8],
//    cursor: usize,
//    limit: usize,
//}

/// A UART channel
///
/// Each UART manages its own clock and NVIC interrupt internally.
pub struct UART {
    regs: *mut Registers,
    clock: Clock,
    tx_buffer: TakeCell<'static, [u8]>,
    tx_limit: Cell<usize>,
    tx_cursor: Cell<usize>,
    client: Cell<Option<&'static hil::uart::Client>>,
}

impl UART {
    const unsafe fn new(uart: *mut Registers, clock: PeripheralClock1) -> UART {
        UART {
            regs: uart,
            clock: Clock::new(PeripheralClock::Bank1(clock)),
            tx_buffer: TakeCell::empty(),
            tx_limit: Cell::new(0),
            tx_cursor: Cell::new(0),
            client: Cell::new(None),
        }
    }

    /// Enables transmission on the UART
    ///
    /// Side-effect: ensures the clock is on.
    pub fn enable_tx(&self) {
        let regs = unsafe { &*self.regs };

        self.clock.enable();

        let ctrl = regs.control.get() | 0b1;
        regs.control.set(ctrl);
    }

    /// Disable transmission on the UART
    ///
    /// Side-effect: turns the clock off if RX is also disabled.
    pub fn disable_tx(&self) {
        let regs = unsafe { &*self.regs };

        let ctrl = regs.control.get() & !(0b1);
        regs.control.set(ctrl);

        if ctrl & 0b11 == 0 {
            // Neither TX nor RX enabled anymore
            self.clock.disable();
        }
    }

    /// Enables reception on the UART
    ///
    /// Side-effect: ensures the clock is on.
    pub fn enable_rx(&self) {
        let regs = unsafe { &*self.regs };

        self.clock.enable();

        let ctrl = regs.control.get() | 0b10;
        regs.control.set(ctrl);
        regs.interrupt_control.set(regs.interrupt_control.get() | 2);
    }

    /// Disable reception on the UART
    ///
    /// Side-effect: turns the clock off if TX is also disabled.
    pub fn disable_rx(&self) {
        let regs = unsafe { &*self.regs };

        let ctrl = regs.control.get() & !(0b10);
        regs.control.set(ctrl);

        if ctrl & 0b11 == 0 {
            // Neither TX nor RX enabled anymore
            self.clock.disable();
        }
        regs.interrupt_control.set(regs.interrupt_control.get() & !2);
    }

    /// Prepare the UART for operation
    ///
    /// `baudrate` is specified in Hz (e.g. 9600, 115200).
    // TODO: Allow specification of other parameters like hardware flow control,
    // parity, etc.
    pub fn config(&self, baudrate: u32) {
        let regs = unsafe { &*self.regs };

        // NCO is 2**20 * f_baud / f_pclk
        // f_pclk is 24_000_000 (24Mhz)
        // To avoid overflow, we use 2**14 * f_baud / (24Mhz / 2**6)
        let nco = (1 << 14) * baudrate / 375000;
        regs.nco.set(nco);

        regs.clear_interrupt_state.set(!0);
        regs.state.set(!0);
    }

    /// Send an array of bytes synchronously over the UART
    ///
    /// # Safety
    ///
    /// This method is marked unsafe because you shouldn't use it, in general.
    /// Sending bytes synchronously over UART takes forever and will result in
    /// missed interrupts. For example, at 115200 baud rate, each byte takes
    /// ~69 micrseconds to send.
    ///
    /// As a result, this method also takes some liberties enabling/disabling
    /// the TX and doesn't check if there is a pending operation.
    pub unsafe fn send_bytes_sync(&self, bytes: &[u8]) {
        let regs = &*self.regs;

        self.enable_tx();

        for b in bytes {
            while regs.state.get() & 1 != 0 {}
            regs.write_data.set(*b as u32);
        }

        while regs.state.get() & (1 << 5 | 1 << 4) != 0b110000 {}
    }

    // Call this function when there might be bytes left in the `buffer` to
    // send. Writes bytes out to the TX FIFO until there are no bytes left, or
    // the FIFO is full. If any bytes _were_ written, it will enable the TX
    // interrupt, which will fire when number of bytes in the FIFO drops to a
    // certain threshold (determined by the `fifo` register and defaults to 1
    // byte).
    //
    // Returns the number of bytes written.
    fn send_remaining_bytes(&self) -> usize {
        let regs = unsafe { &*self.regs };

        // If there is no current buffer, just return zero. Probably shouldn't
        // happen though.
        let nwritten = self.tx_buffer.map(|bytes| {
            let init_cursor = self.tx_cursor.get();
            let limit = self.tx_limit.get();

            for b in bytes[init_cursor..limit].iter() {
                if regs.state.get() & 1 == 1 {
                    break; // TX Buffer full, we'll continue later
                }
                self.tx_cursor.set(self.tx_cursor.get() + 1);
                regs.write_data.set(*b as u32);
            }
            self.tx_cursor.get() - init_cursor
        })
            .unwrap_or(0);

        if nwritten > 0 {
            // if we wrote anything, we're gonna want to get notified when the FIFO has room again.
            // Technically we could be done here if there is nothing left to send, but we want to
            // get an interrupt anyway so we can return the buffer to the client from
            // `handle_tx_interrupt`.
            regs.interrupt_control.set(regs.interrupt_control.get() | 1);
        }

        nwritten

    }

    /// Called by the chip following a TX interrupt.
    ///
    /// If there are bytes left in the buffer to send, write another batch to the TX FIFO.
    /// Otherwise, return the buffer back to the client.
    ///
    /// # Invariants
    ///
    ///   * NVIC is disabled
    ///
    ///   * NVIC pending bit is high
    ///
    pub fn handle_tx_interrupt(&self) {
        let regs = unsafe { &*self.regs };

        regs.clear_interrupt_state.set(1);
        if self.send_remaining_bytes() == 0 {
            self.client.get().map(|client| {
                if self.tx_buffer.is_some() {
                    client.transmit_complete(self.tx_buffer.take().unwrap(), hil::uart::Error::CommandComplete);
                }
//                }
//                self.tx_buffer.map(|buffer| {
//                    client.transmit_complete(buffer, hil::uart::Error::CommandComplete);
//                });
            });
        }
    }

    /// Called by the chip following a RX interrupt.
    ///
    /// This will clear the NVIC pending bit to mark that we've handled the
    /// interrupt. Then, if there are bytes left in the buffer to send, write
    /// another batch to the TX FIFO. Otherwise, return the buffer back to the
    /// client (TODO: no client yet, so not yet implemented).
    ///
    /// # Invariants
    ///
    ///   * NVIC is disabled
    ///
    ///   * NVIC pending bit is high
    ///
    pub fn handle_rx_interrupt(&self) {
        let regs = unsafe { &*self.regs };
        // Currently discards bytes: need to read into buffer. -pal 4/11/18
        regs.clear_interrupt_state.set(2);
        self.client.get().map(|_client| {
            while regs.state.get() & 1 << 7 == 0 {
                // While RX FIFO not empty
                let _b = regs.read_data.get() as u8;
//                client.receive_complete(b, hil::uart::Error::CommandComplete);
            }
        });
    }
}

impl hil::uart::UART for UART {
    fn set_client(&self, client: &'static hil::uart::Client) {
        self.client.set(Some(client));
    }

    fn transmit(&self, tx_buffer: &'static mut [u8], tx_len: usize) {
        self.tx_buffer.replace(tx_buffer);
        self.tx_cursor.set(0);
        self.tx_limit.set(tx_len);
        self.send_remaining_bytes();
    }

    fn receive(&self, _rx_buffer: &'static mut[u8], _rx_len: usize) {
        unimplemented!();
    }

    fn abort_receive(&self) {
        unimplemented!();
    }

    fn configure(&self, params: hil::uart::UARTParameters) -> ReturnCode {
        self.config(params.baud_rate);
        ReturnCode::SUCCESS
    }
}
<commit_msg>This fixes a bug in the H1B UART driver. The observed behavior is that writes longer than the FIFO length can be truncated to the FIFO length. In the context of console, since there is an internal static buffer to copy userspace writes to, a long userspace printf appears as a series of truncated UART writes. E.g., if the FIFO is 32 bytes and the Console buffer is 64 bytes, then bytes 0-31, 64-95 will be actually written and 32-63 will be missed.<commit_after>// Copyright 2018 Google LLC
//
// 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
//
//     https://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.

//! Driver for the UART controllers capable of sending and receiving data
//! asynchronously.
//!
//! The UART has a configurable baud rate and can run with or without hardware
//! flow-control. There is no DMA for the UART, but it has a 32-character deep
//! FIFO transmit and receive buffer.
//!
//! # Examples
//!
//! Before using the UART you must configure the TX and/or RX pins and set the
//! baud rate:w
//!
//! ```
//! let uart = &h1b::uart::UART0;
//! let pinmux = unsafe { &mut *h1b::pinmux::PINMUX };
//! pinmux.dioa0.select.set(h1b::pinmux::Function::Uart0Tx);
//! uart.config(115200);
//! uart.enable_tx();
//! ```
//! Then, you can (unsafely) send bytes synchronously (e.g. for debugging)
//!
//! ```
//! uart.send_bytes_sync("Debug string".as_bytes());
//! ```
//!
//! Or asynchornously:
//!
//! ```
//! uart.send_bytes("Pretend I'm a very long string").as_bytes());
//! ```
//! you'll be notified of completion through a callback
//!
//! TODO
//!

use core::cell::Cell;
use kernel::common::cells::TakeCell;
use kernel::common::cells::VolatileCell;
use kernel::hil;
use kernel::ReturnCode;
use pmu::{Clock, PeripheralClock, PeripheralClock1};

/// Registers for the UART controller
#[allow(dead_code)]
struct Registers {
    read_data: VolatileCell<u32>,
    write_data: VolatileCell<u32>,
    nco: VolatileCell<u32>,
    control: VolatileCell<u32>,
    interrupt_control: VolatileCell<u32>,
    state: VolatileCell<u32>,
    clear_state: VolatileCell<u32>,
    interrupt_state: VolatileCell<u32>,
    clear_interrupt_state: VolatileCell<u32>,
}

const UART0_BASE: *mut Registers = 0x40600000 as *mut Registers;
const UART1_BASE: *mut Registers = 0x40610000 as *mut Registers;
const UART2_BASE: *mut Registers = 0x40620000 as *mut Registers;

pub static mut UART0: UART = unsafe { UART::new(UART0_BASE, PeripheralClock1::Uart0Timer) };

pub static mut UART1: UART = unsafe { UART::new(UART1_BASE, PeripheralClock1::Uart1Timer) };

pub static mut UART2: UART = unsafe { UART::new(UART2_BASE, PeripheralClock1::Uart2Timer) };

// A resumable buffer that tracks the last written index
//struct Buffer {
//    bytes: &'static mut [u8],
//    cursor: usize,
//    limit: usize,
//}

/// A UART channel
///
/// Each UART manages its own clock and NVIC interrupt internally.
pub struct UART {
    regs: *mut Registers,
    clock: Clock,
    tx_buffer: TakeCell<'static, [u8]>,
    tx_limit: Cell<usize>,
    tx_cursor: Cell<usize>,
    client: Cell<Option<&'static hil::uart::Client>>,
}

impl UART {
    const unsafe fn new(uart: *mut Registers, clock: PeripheralClock1) -> UART {
        UART {
            regs: uart,
            clock: Clock::new(PeripheralClock::Bank1(clock)),
            tx_buffer: TakeCell::empty(),
            tx_limit: Cell::new(0),
            tx_cursor: Cell::new(0),
            client: Cell::new(None),
        }
    }

    /// Enables transmission on the UART
    ///
    /// Side-effect: ensures the clock is on.
    pub fn enable_tx(&self) {
        let regs = unsafe { &*self.regs };

        self.clock.enable();

        let ctrl = regs.control.get() | 0b1;
        regs.control.set(ctrl);
    }

    /// Disable transmission on the UART
    ///
    /// Side-effect: turns the clock off if RX is also disabled.
    pub fn disable_tx(&self) {
        let regs = unsafe { &*self.regs };

        let ctrl = regs.control.get() & !(0b1);
        regs.control.set(ctrl);

        if ctrl & 0b11 == 0 {
            // Neither TX nor RX enabled anymore
            self.clock.disable();
        }
    }

    /// Enables reception on the UART
    ///
    /// Side-effect: ensures the clock is on.
    pub fn enable_rx(&self) {
        let regs = unsafe { &*self.regs };

        self.clock.enable();

        let ctrl = regs.control.get() | 0b10;
        regs.control.set(ctrl);
        regs.interrupt_control.set(regs.interrupt_control.get() | 2);
    }

    /// Disable reception on the UART
    ///
    /// Side-effect: turns the clock off if TX is also disabled.
    pub fn disable_rx(&self) {
        let regs = unsafe { &*self.regs };

        let ctrl = regs.control.get() & !(0b10);
        regs.control.set(ctrl);

        if ctrl & 0b11 == 0 {
            // Neither TX nor RX enabled anymore
            self.clock.disable();
        }
        regs.interrupt_control.set(regs.interrupt_control.get() & !2);
    }

    /// Prepare the UART for operation
    ///
    /// `baudrate` is specified in Hz (e.g. 9600, 115200).
    // TODO: Allow specification of other parameters like hardware flow control,
    // parity, etc.
    pub fn config(&self, baudrate: u32) {
        let regs = unsafe { &*self.regs };

        // NCO is 2**20 * f_baud / f_pclk
        // f_pclk is 24_000_000 (24Mhz)
        // To avoid overflow, we use 2**14 * f_baud / (24Mhz / 2**6)
        let nco = (1 << 14) * baudrate / 375000;
        regs.nco.set(nco);

        regs.clear_interrupt_state.set(!0);
        regs.state.set(!0);
    }

    /// Send an array of bytes synchronously over the UART
    ///
    /// # Safety
    ///
    /// This method is marked unsafe because you shouldn't use it, in general.
    /// Sending bytes synchronously over UART takes forever and will result in
    /// missed interrupts. For example, at 115200 baud rate, each byte takes
    /// ~69 micrseconds to send.
    ///
    /// As a result, this method also takes some liberties enabling/disabling
    /// the TX and doesn't check if there is a pending operation.
    pub unsafe fn send_bytes_sync(&self, bytes: &[u8]) {
        let regs = &*self.regs;

        self.enable_tx();

        for b in bytes {
            while regs.state.get() & 1 != 0 {}
            regs.write_data.set(*b as u32);
        }

        while regs.state.get() & (1 << 5 | 1 << 4) != 0b110000 {}
    }

    // Call this function when there might be bytes left in the `buffer` to
    // send. Writes bytes out to the TX FIFO until there are no bytes left, or
    // the FIFO is full. If any bytes _were_ written, it will enable the TX
    // interrupt, which will fire when number of bytes in the FIFO drops to a
    // certain threshold (determined by the `fifo` register and defaults to 1
    // byte).
    //
    // Returns the number of bytes written, -1 if no more to write.
    fn send_remaining_bytes(&self) -> isize {
        let regs = unsafe { &*self.regs };

        // If there is no current buffer, just return zero. Probably shouldn't
        // happen though.
        let nwritten: isize = self.tx_buffer.map(|bytes| {
            let init_cursor = self.tx_cursor.get();
            let limit = self.tx_limit.get();
            if init_cursor == limit {
                -1 // done
            } else {
                for b in bytes[init_cursor..limit].iter() {
                    if regs.state.get() & 1 == 1 {
                        break; // TX Buffer full, we'll continue later
                    }
                    self.tx_cursor.set(self.tx_cursor.get() + 1);
                    regs.write_data.set(*b as u32);
                }
                (self.tx_cursor.get() - init_cursor) as isize
            }
        })
            .unwrap_or(0 as isize);

        if nwritten >= 0 {
            // if we wrote anything, we're gonna want to get notified when the FIFO has room again.
            // Technically we could be done here if there is nothing left to send, but we want to
            // get an interrupt anyway so we can return the buffer to the client from
            // `handle_tx_interrupt`.
            regs.interrupt_control.set(regs.interrupt_control.get() | 1);
        }

        nwritten

    }

    /// Called by the chip following a TX interrupt.
    ///
    /// If there are bytes left in the buffer to send, write another batch to the TX FIFO.
    /// Otherwise, return the buffer back to the client.
    ///
    /// # Invariants
    ///
    ///   * NVIC is disabled
    ///
    ///   * NVIC pending bit is high
    ///
    pub fn handle_tx_interrupt(&self) {
        let regs = unsafe { &*self.regs };

        regs.clear_interrupt_state.set(1);
        if self.send_remaining_bytes() == -1 {
            self.client.get().map(|client| {
                if self.tx_buffer.is_some() {
                    client.transmit_complete(self.tx_buffer.take().unwrap(), hil::uart::Error::CommandComplete);
                }
//                }
//                self.tx_buffer.map(|buffer| {
//                    client.transmit_complete(buffer, hil::uart::Error::CommandComplete);
//                });
            });
        }
    }

    /// Called by the chip following a RX interrupt.
    ///
    /// This will clear the NVIC pending bit to mark that we've handled the
    /// interrupt. Then, if there are bytes left in the buffer to send, write
    /// another batch to the TX FIFO. Otherwise, return the buffer back to the
    /// client (TODO: no client yet, so not yet implemented).
    ///
    /// # Invariants
    ///
    ///   * NVIC is disabled
    ///
    ///   * NVIC pending bit is high
    ///
    pub fn handle_rx_interrupt(&self) {
        let regs = unsafe { &*self.regs };
        // Currently discards bytes: need to read into buffer. -pal 4/11/18
        regs.clear_interrupt_state.set(2);
        self.client.get().map(|_client| {
            while regs.state.get() & 1 << 7 == 0 {
                // While RX FIFO not empty
                let _b = regs.read_data.get() as u8;
//                client.receive_complete(b, hil::uart::Error::CommandComplete);
            }
        });
    }
}

impl hil::uart::UART for UART {
    fn set_client(&self, client: &'static hil::uart::Client) {
        self.client.set(Some(client));
    }

    fn transmit(&self, tx_buffer: &'static mut [u8], tx_len: usize) {
        self.tx_buffer.replace(tx_buffer);
        self.tx_cursor.set(0);
        self.tx_limit.set(tx_len);
        self.send_remaining_bytes();
    }

    fn receive(&self, _rx_buffer: &'static mut[u8], _rx_len: usize) {
        unimplemented!();
    }

    fn abort_receive(&self) {
        unimplemented!();
    }

    fn configure(&self, params: hil::uart::UARTParameters) -> ReturnCode {
        self.config(params.baud_rate);
        ReturnCode::SUCCESS
    }
}
<|endoftext|>


<commit_before>//! SOCKSv5 protocol support

use std::comm::channel;
use std::io::{IoError, IoResult, Reader, TcpStream};
use std::io::net::ip::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::io::net::addrinfo;
use std::str;
use std::time::duration::Duration;

#[allow(dead_code)]
mod consts {
    pub static VERSION_NUMBER: u8 = 0x05;

    pub mod auth {
        pub static NONE: u8 = 0x00;
    }

    pub mod atype {
        pub static IPV4:   u8 = 0x1;
        pub static IPV6:   u8 = 0x4;
        pub static DOMAIN: u8 = 0x3;
    }

    pub mod command {
        pub static CONNECT:       u8 = 0x01;
        pub static BIND:          u8 = 0x02;
        pub static UDP_ASSOCIATE: u8 = 0x04;
    }

    pub mod reply {
        pub static SUCCESS:          u8 = 0x00;
        pub static GENERAL_FAILURE:  u8 = 0x01;
        pub static CONN_DENIED:      u8 = 0x02;
        pub static NET_UNREACHABLE:  u8 = 0x03;
        pub static HOST_UNREACHABLE: u8 = 0x04;
        pub static CONN_REFUSED:     u8 = 0x05;
        pub static TTL_EXPIRED:      u8 = 0x06;
        pub static CMD_UNSUPPORTED:  u8 = 0x07;
        pub static ADDR_UNSUPPORTED: u8 = 0x08;
    }
}

struct SocksConnection<'a> {
    stream: &'a mut TcpStream
}

impl <'a> SocksConnection<'a> {
    /// Make sure that the client sends the right version number at
    /// the start of the message, or fail
    fn read_client_version(&mut self) -> IoResult<()> {
        match try!(self.stream.read_byte()) {
            consts::VERSION_NUMBER => Ok(()),
            _ => Err(IoError::last_error())
        }
    }

    /// Client -> Server:
    ///
    /// |VER | NMETHODS | METHODS  |
    /// |----+----------+----------|
    /// | 1  |    1     | 1 to 255 |
    ///
    /// Client <- Server:
    /// +----+--------+
    /// |VER | METHOD |
    /// +----+--------+
    /// | 1  |   1    |
    fn read_client_hello(&mut self) -> IoResult<()> {
        try!(self.read_client_version());

        // Number of authentication methods
        let nmethods = try!(self.stream.read_byte());

        // Authentication methods
        let methods = try!(self.stream.read_exact(nmethods as uint));

        // If the client doesn't respond to NULL-auth, we can't proceed.
        if !methods.contains(&consts::auth::NONE) {
            // Send the error back
            try!(self.stream.write(&[consts::VERSION_NUMBER, 0xFF]));

            return Err(IoError::last_error());
        }

        // Now respond that we're using NULL auth.
        try!(self.stream.write(&[consts::VERSION_NUMBER, consts::auth::NONE]));

        Ok(())
    }

    /// Client -> Server:
    /// +----+-----+-------+------+----------+----------+
    /// |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
    /// +----+-----+-------+------+----------+----------+
    /// | 1  |  1  | X'00' |  1   | Variable |    2     |
    ///
    /// o  VER    protocol version: X'05'
    /// o  CMD
    /// o  RSV    RESERVED
    /// o  ATYP   address type of following address
    /// o  DST.ADDR desired destination address
    /// o  DST.PORT desired destination port in network octet
    ///    order
    fn read_client_request(&mut self) -> IoResult<TcpStream> {
        try!(self.read_client_version());

        // Commands (for now only connect is supported)
        match try!(self.stream.read_byte()) {
            consts::command::CONNECT => (),
            _ => {
                // Tell client we don't support that command
                try!(self.send_error_reply(consts::reply::CMD_UNSUPPORTED));
                return Err(IoError::last_error());
            }
        };

        // Reserved byte
        match try!(self.stream.read_byte()) {
            0u8 => (),
            _ => { return Err(IoError::last_error()); }
        };

        // Address type
        let addr = match try!(self.stream.read_byte()) {
            // 4 bytes
            consts::atype::IPV4 => {
                let a = try!(self.stream.read_byte());
                let b = try!(self.stream.read_byte());
                let c = try!(self.stream.read_byte());
                let d = try!(self.stream.read_byte());

                Ipv4Addr(a, b, c, d)
            },

            // 16 bytes
            consts::atype::IPV6 => {
                let a = try!(self.stream.read_be_u16());
                let b = try!(self.stream.read_be_u16());
                let c = try!(self.stream.read_be_u16());
                let d = try!(self.stream.read_be_u16());
                let e = try!(self.stream.read_be_u16());
                let f = try!(self.stream.read_be_u16());
                let g = try!(self.stream.read_be_u16());
                let h = try!(self.stream.read_be_u16());

                Ipv6Addr(a, b, c, d, e, f, g, h)
            },

            // len | hostname
            consts::atype::DOMAIN => {
                let len = try!(self.stream.read_byte());
                let hostname = try!(self.stream.read_exact(len as uint));

                let mut hosts = match str::from_utf8(hostname.as_slice()) {
                    Some(host) => try!(addrinfo::get_host_addresses(host)),
                    None => { return Err(IoError::last_error()); }
                };

                match hosts.remove(0) {
                    Some(host) => host,
                    None => { return Err(IoError::last_error()); }
                }
            },

            // Unsupported address type
            _ => {
                try!(self.send_error_reply(consts::reply::ADDR_UNSUPPORTED));
                return Err(IoError::last_error());
            }
        };

        // Network port
        let port = try!(self.stream.read_be_u16());

        Ok(try!(TcpStream::connect_timeout(
            SocketAddr { ip: addr, port: port },
            Duration::seconds(1000))))
    }

    /// Client <- Server:
    /// +----+-----+-------+------+----------+----------+
    /// |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
    /// +----+-----+-------+------+----------+----------+
    /// | 1  |  1  | X'00' |  1   | Variable |    2     |
    ///
    ///   o  VER    protocol version: X'05'
    ///   o  REP    Reply field
    ///   o  RSV    RESERVED
    ///   o  ATYP   address type of following address
    ///   o  BND.ADDR       server bound address
    ///   o  BND.PORT       server bound port in network octet order
    fn send_reply(&mut self, rep: u8, atype: u8, addr: &[u8], port: u16) -> IoResult<()> {
        try!(self.stream.write(&[consts::VERSION_NUMBER, rep, 0x00, atype]));
        try!(self.stream.write(addr));
        try!(self.stream.write_be_u16(port));

        Ok(())
    }

    fn send_error_reply(&mut self, rep: u8) -> IoResult<()> {
        self.send_reply(rep, 0, &[0u8, 0, 0, 0], 0)
    }
}

pub fn handle_stream<'a>(client_stream: &'a mut TcpStream) -> () {
    let mut conn = SocksConnection { stream: client_stream };

    if conn.read_client_hello().is_err() {
        return;
    }

    // FIXME: A ton of probably redundant clone()s here.
    // FIXME: This causes an ICE:
    // match conn.read_client_request() {
    //     Ok(server_stream) => {
    //         let (client_send, client_recv) = channel();
    //         let (server_send, server_recv) = channel();

    //         let client = conn.stream.clone();
    //         let server = server_stream.clone();

    //         // client -> server
    //         spawn(proc() {
    //             let mut client = client.clone();
    //             loop {
    //                 let mut buf = [0u8, ..4096];
    //                 match client.read(buf) {
    //                     Ok(_) => client_send.send(buf),
    //                     Err(_) => break
    //                 }
    //             }
    //         });

    //         // client <- server
    //         spawn(proc() {
    //             let mut server = server.clone();
    //             loop {
    //                 let mut buf = [0u8, ..4096];
    //                 match server.read(buf) {
    //                     Ok(_) => server_send.send(buf),
    //                     Err(_) => break
    //                 }
    //             }
    //         });

    //         loop {
    //             let mut client = conn.stream.clone();
    //             let mut server = server_stream.clone();

    //             let result = select! {
    //                 buf = client_recv.recv() => server.write(buf),
    //                 buf = server_recv.recv() => client.write(buf)
    //             };

    //             match result {
    //                 Err(e) => println!("Something broke: {}", e),
    //                 _ => ()
    //             }
    //         }
    //     },
    //     Err(_) => ()
    // }
}
<commit_msg>static -> const<commit_after>//! SOCKSv5 protocol support

use std::comm::channel;
use std::io::{IoError, IoResult, Reader, TcpStream};
use std::io::net::ip::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::io::net::addrinfo;
use std::str;
use std::time::duration::Duration;

#[allow(dead_code)]
mod consts {
    pub const VERSION_NUMBER: u8 = 0x05;

    pub mod auth {
        pub const NONE: u8 = 0x00;
    }

    pub mod atype {
        pub const IPV4:   u8 = 0x1;
        pub const IPV6:   u8 = 0x4;
        pub const DOMAIN: u8 = 0x3;
    }

    pub mod command {
        pub const CONNECT:       u8 = 0x01;
        pub const BIND:          u8 = 0x02;
        pub const UDP_ASSOCIATE: u8 = 0x04;
    }

    pub mod reply {
        pub const SUCCESS:          u8 = 0x00;
        pub const GENERAL_FAILURE:  u8 = 0x01;
        pub const CONN_DENIED:      u8 = 0x02;
        pub const NET_UNREACHABLE:  u8 = 0x03;
        pub const HOST_UNREACHABLE: u8 = 0x04;
        pub const CONN_REFUSED:     u8 = 0x05;
        pub const TTL_EXPIRED:      u8 = 0x06;
        pub const CMD_UNSUPPORTED:  u8 = 0x07;
        pub const ADDR_UNSUPPORTED: u8 = 0x08;
    }
}

struct SocksConnection<'a> {
    stream: &'a mut TcpStream
}

impl <'a> SocksConnection<'a> {
    /// Make sure that the client sends the right version number at
    /// the start of the message, or fail
    fn read_client_version(&mut self) -> IoResult<()> {
        match try!(self.stream.read_byte()) {
            consts::VERSION_NUMBER => Ok(()),
            _ => Err(IoError::last_error())
        }
    }

    /// Client -> Server:
    ///
    /// |VER | NMETHODS | METHODS  |
    /// |----+----------+----------|
    /// | 1  |    1     | 1 to 255 |
    ///
    /// Client <- Server:
    /// +----+--------+
    /// |VER | METHOD |
    /// +----+--------+
    /// | 1  |   1    |
    fn read_client_hello(&mut self) -> IoResult<()> {
        try!(self.read_client_version());

        // Number of authentication methods
        let nmethods = try!(self.stream.read_byte());

        // Authentication methods
        let methods = try!(self.stream.read_exact(nmethods as uint));

        // If the client doesn't respond to NULL-auth, we can't proceed.
        if !methods.contains(&consts::auth::NONE) {
            // Send the error back
            try!(self.stream.write(&[consts::VERSION_NUMBER, 0xFF]));

            return Err(IoError::last_error());
        }

        // Now respond that we're using NULL auth.
        try!(self.stream.write(&[consts::VERSION_NUMBER, consts::auth::NONE]));

        Ok(())
    }

    /// Client -> Server:
    /// +----+-----+-------+------+----------+----------+
    /// |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
    /// +----+-----+-------+------+----------+----------+
    /// | 1  |  1  | X'00' |  1   | Variable |    2     |
    ///
    /// o  VER    protocol version: X'05'
    /// o  CMD
    /// o  RSV    RESERVED
    /// o  ATYP   address type of following address
    /// o  DST.ADDR desired destination address
    /// o  DST.PORT desired destination port in network octet
    ///    order
    fn read_client_request(&mut self) -> IoResult<TcpStream> {
        try!(self.read_client_version());

        // Commands (for now only connect is supported)
        match try!(self.stream.read_byte()) {
            consts::command::CONNECT => (),
            _ => {
                // Tell client we don't support that command
                try!(self.send_error_reply(consts::reply::CMD_UNSUPPORTED));
                return Err(IoError::last_error());
            }
        };

        // Reserved byte
        match try!(self.stream.read_byte()) {
            0u8 => (),
            _ => { return Err(IoError::last_error()); }
        };

        // Address type
        let addr = match try!(self.stream.read_byte()) {
            // 4 bytes
            consts::atype::IPV4 => {
                let a = try!(self.stream.read_byte());
                let b = try!(self.stream.read_byte());
                let c = try!(self.stream.read_byte());
                let d = try!(self.stream.read_byte());

                Ipv4Addr(a, b, c, d)
            },

            // 16 bytes
            consts::atype::IPV6 => {
                let a = try!(self.stream.read_be_u16());
                let b = try!(self.stream.read_be_u16());
                let c = try!(self.stream.read_be_u16());
                let d = try!(self.stream.read_be_u16());
                let e = try!(self.stream.read_be_u16());
                let f = try!(self.stream.read_be_u16());
                let g = try!(self.stream.read_be_u16());
                let h = try!(self.stream.read_be_u16());

                Ipv6Addr(a, b, c, d, e, f, g, h)
            },

            // len | hostname
            consts::atype::DOMAIN => {
                let len = try!(self.stream.read_byte());
                let hostname = try!(self.stream.read_exact(len as uint));

                let mut hosts = match str::from_utf8(hostname.as_slice()) {
                    Some(host) => try!(addrinfo::get_host_addresses(host)),
                    None => { return Err(IoError::last_error()); }
                };

                match hosts.remove(0) {
                    Some(host) => host,
                    None => { return Err(IoError::last_error()); }
                }
            },

            // Unsupported address type
            _ => {
                try!(self.send_error_reply(consts::reply::ADDR_UNSUPPORTED));
                return Err(IoError::last_error());
            }
        };

        // Network port
        let port = try!(self.stream.read_be_u16());

        Ok(try!(TcpStream::connect_timeout(
            SocketAddr { ip: addr, port: port },
            Duration::seconds(1000))))
    }

    /// Client <- Server:
    /// +----+-----+-------+------+----------+----------+
    /// |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
    /// +----+-----+-------+------+----------+----------+
    /// | 1  |  1  | X'00' |  1   | Variable |    2     |
    ///
    ///   o  VER    protocol version: X'05'
    ///   o  REP    Reply field
    ///   o  RSV    RESERVED
    ///   o  ATYP   address type of following address
    ///   o  BND.ADDR       server bound address
    ///   o  BND.PORT       server bound port in network octet order
    fn send_reply(&mut self, rep: u8, atype: u8, addr: &[u8], port: u16) -> IoResult<()> {
        try!(self.stream.write(&[consts::VERSION_NUMBER, rep, 0x00, atype]));
        try!(self.stream.write(addr));
        try!(self.stream.write_be_u16(port));

        Ok(())
    }

    fn send_error_reply(&mut self, rep: u8) -> IoResult<()> {
        self.send_reply(rep, 0, &[0u8, 0, 0, 0], 0)
    }
}

pub fn handle_stream<'a>(client_stream: &'a mut TcpStream) -> () {
    let mut conn = SocksConnection { stream: client_stream };

    if conn.read_client_hello().is_err() {
        return;
    }

    // FIXME: A ton of probably redundant clone()s here.
    // FIXME: This causes an ICE:
    // match conn.read_client_request() {
    //     Ok(server_stream) => {
    //         let (client_send, client_recv) = channel();
    //         let (server_send, server_recv) = channel();

    //         let client = conn.stream.clone();
    //         let server = server_stream.clone();

    //         // client -> server
    //         spawn(proc() {
    //             let mut client = client.clone();
    //             loop {
    //                 let mut buf = [0u8, ..4096];
    //                 match client.read(buf) {
    //                     Ok(_) => client_send.send(buf),
    //                     Err(_) => break
    //                 }
    //             }
    //         });

    //         // client <- server
    //         spawn(proc() {
    //             let mut server = server.clone();
    //             loop {
    //                 let mut buf = [0u8, ..4096];
    //                 match server.read(buf) {
    //                     Ok(_) => server_send.send(buf),
    //                     Err(_) => break
    //                 }
    //             }
    //         });

    //         loop {
    //             let mut client = conn.stream.clone();
    //             let mut server = server_stream.clone();

    //             let result = select! {
    //                 buf = client_recv.recv() => server.write(buf),
    //                 buf = server_recv.recv() => client.write(buf)
    //             };

    //             match result {
    //                 Err(e) => println!("Something broke: {}", e),
    //                 _ => ()
    //             }
    //         }
    //     },
    //     Err(_) => ()
    // }
}
<|endoftext|>


<commit_before>// Copyright 2013 Torste Aikio and gl-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.

#[feature(globs)];
#[feature(macro_rules)];

extern mod glfw;
extern mod gl;

use std::libc;

use std::cast;
use std::ptr;
use std::str;
use std::sys;
use std::vec;

use std::io;
use std::path::PosixPath;

use gl::types::*;

// COMPONENT DEFINITIONS
struct Position {
    x: f64,
    y: f64
}

struct HorizVelocity {
    x: f64
}

struct VertVelocity {
    y: f64
}

struct Sprite {
    x_size: f64,
    y_size: f64,
    color: [f64, ..4]
}

struct Components {
    position: Option<@mut Position>,
    horiz_velocity: Option<@mut HorizVelocity>,
    vert_velocity: Option<@mut VertVelocity>,
    sprite: Option<@mut Sprite>
}

// SYSTEM DEFINITIONS
trait System {
    fn process(&self, entity: @Components) -> ();
}

struct MovementSystem;

impl System for MovementSystem {
    fn process(&self, entity: @Components) -> () {
        match entity.position {
            Some(pos) => {
                match entity.vert_velocity {
                    Some(v) => pos.y += v.y,
                    None => ()
                }
                match entity.horiz_velocity {
                    Some(v) => pos.x += v.x,
                    None => ()
                }
            },
            None => ()
        }
    }
}

struct EdgeCollisionSystem;

impl System for EdgeCollisionSystem {
    fn process(&self, entity: @Components) -> () {
        match (entity.position, entity.vert_velocity) {
            (Some(pos), Some(vel)) => {
                if pos.y >= 4.0 || pos.y <= 0.0 {
                    vel.y *= -1.0;
                }
            },
            (_, _) => ()
        }
    }
}

struct PaddleCollisionSystem {
    left_paddle: @Components,
    right_paddle: @Components,
}

impl System for PaddleCollisionSystem {
    fn process(&self, entity: @Components) -> () {
        //TODO use a hitbox or something instead of sprite
        match (entity.position, entity.horiz_velocity, entity.sprite) {
            (Some(pos), Some(vel), Some(spr)) => {
                if (pos.x+(spr.x_size)/2.0) >= (self.right_paddle.position.unwrap().x-(self.right_paddle.sprite.unwrap().x_size)/2.0) {
                    if std::num::abs(pos.y - self.right_paddle.position.unwrap().y) < (self.right_paddle.sprite.unwrap().y_size/2.0) {
                        vel.x *= -1.0;
                    }
                }
                if (pos.x-(spr.x_size)/2.0) <= (self.left_paddle.position.unwrap().x+(self.left_paddle.sprite.unwrap().x_size)/2.0) {
                    if std::num::abs(pos.y - self.left_paddle.position.unwrap().y) < (self.left_paddle.sprite.unwrap().y_size/2.0) {
                        vel.x *= -1.0;
                    }
                }
            },
            (_, _, _) => ()
        }
    }
}

struct RenderSystem {
    program: GLuint,
    position_uniform: GLint,
    scale_uniform: GLint,
    color_uniform: GLint
}

impl System for RenderSystem {
    fn process(&self, entity: @Components) -> () {
        match (entity.position, entity.sprite) {
            (Some(pos), Some(sprite)) => {
                // Set uniforms
                gl::ProgramUniform2f(self.program, self.position_uniform, pos.x as f32, pos.y as f32);
                gl::ProgramUniform2f(self.program, self.scale_uniform, sprite.x_size as f32, sprite.y_size as f32);
                gl::ProgramUniform4f(self.program, self.color_uniform, sprite.color[0] as f32, sprite.color[1] as f32, sprite.color[2] as f32, sprite.color[3] as f32);
                // Draw a rect from the 4 vertices
                gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4);
            },
            (_, _) => ()
        }
    }
}

// WORLD DEFINITION
// We need to figure out how to integrate World with the main game loop
// in Artemis world has a `setDelta` method for timestep
struct World {
    entities: ~[@Components],
    systems: ~[@System]
}

impl World {
    fn new() -> World {
        return World {entities: ~[], systems: ~[]};
    }

    fn process(&self) {
        for system in self.systems.iter() {
            for entity in self.entities.iter() {
                system.process(*entity);
            }
        }
    }
}

//ENTITY CONSTRUCTORS
enum PaddleSide {
    RIGHT,
    LEFT
}

fn new_ball() -> @Components {
    @Components {
        position: Some(@mut Position { x: 2.0, y: 1.5 }),
        horiz_velocity: Some(@mut HorizVelocity { x: 1.0/60.0 }),
        vert_velocity: Some(@mut VertVelocity { y: 0.0 }),
        sprite: Some(@mut Sprite {
            x_size: 0.05,
            y_size: 0.05,
            color: [0.3, 0.3, 0.8, 1.0]
        })
    }
}

fn new_paddle(side: PaddleSide) -> @Components {
    let xpos = match side {
        RIGHT => 3.9,
        LEFT => 0.1
    };
    @Components {
        position: Some(@mut Position { x: xpos, y: 1.5 }),
        horiz_velocity: None,
        vert_velocity: Some(@mut VertVelocity { y: 0.0 }),
        sprite: Some(@mut Sprite {
            x_size: 0.1,
            y_size: 0.4,
            color: [xpos/4.0, 1.0-(xpos/4.0), 0.3, 1.0]
        })
    }
}

// OPENGL ETC STUFF

// Vertex data
static VERTEX_DATA: [GLfloat, ..8] = [
    -1.0,  1.0,
    -1.0, -1.0,
     1.0,  1.0,
     1.0, -1.0
];

#[start]
fn start(argc: int, argv: **u8) -> int {
    std::rt::start_on_main_thread(argc, argv, main)
}

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
        // Attempt to compile the shader
        src.with_c_str(|ptr| gl::ShaderSource(shader, 1, &ptr, ptr::null()));
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::mut_null(), vec::raw::to_mut_ptr(buf) as *mut GLchar);
            fail!(str::raw::from_utf8(buf));
        }
    }
    shader
}

fn link_program(vs: GLuint, fs: GLuint, out_color: &str) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vs);
    gl::AttachShader(program, fs);
    // gl::BindFragDataLocation needs to be called before linking to have effect
    unsafe {
        out_color.with_c_str(|ptr| gl::BindFragDataLocation(program, 0, ptr));
    }
    gl::LinkProgram(program);
    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), vec::raw::to_mut_ptr(buf) as *mut GLchar);
            fail!(str::raw::from_utf8(buf));
        }
    }
    program
}

fn main() {
    do glfw::set_error_callback |_, description| {
        println!("GLFW Error: {}", description);
    }

    do glfw::start {
        // initialize game world
        let left_paddle: @Components = new_paddle(LEFT);
        let right_paddle: @Components = new_paddle(RIGHT);
        let ball: @Components = new_ball();
        let ms: @System = @MovementSystem as @System;
        let es: @System = @EdgeCollisionSystem as @System;
        let ps: @System = @PaddleCollisionSystem{ right_paddle: right_paddle, left_paddle: left_paddle } as @System;

        let mut world: World = World::new();
        world.entities.push(left_paddle);
        world.entities.push(right_paddle);
        world.entities.push(ball);
        world.systems.push(ms);
        world.systems.push(es);
        world.systems.push(ps);

        // Choose a GL profile that is compatible with OS X 10.7+
        glfw::window_hint::context_version(3, 2);
        glfw::window_hint::opengl_profile(glfw::OpenGlCoreProfile);
        glfw::window_hint::opengl_forward_compat(true);

        let window = glfw::Window::create(1024, 600, "Pong", glfw::Windowed).unwrap();
        window.set_key_callback(key_callback);
        window.make_context_current();

        // Load the OpenGL function pointers
        gl::load_with(glfw::get_proc_address);

        // Create GLSL shaders
        let vs_src = io::read_whole_file_str(&PosixPath("main.vs.glsl")).unwrap();
        let vs = compile_shader(vs_src, gl::VERTEX_SHADER);
        let fs_src = io::read_whole_file_str(&PosixPath("main.fs.glsl")).unwrap();
        let fs = compile_shader(fs_src, gl::FRAGMENT_SHADER);
        let program = link_program(vs, fs, "out_color");

        let mut vao = 0;
        let mut vbo = 0;

        let position_uniform: GLint;
        let scale_uniform: GLint;
        let color_uniform: GLint;

        unsafe {
            position_uniform = "position".with_c_str(|ptr| gl::GetUniformLocation(program, ptr));
            scale_uniform = "scale".with_c_str(|ptr| gl::GetUniformLocation(program, ptr));
            color_uniform = "color".with_c_str(|ptr| gl::GetUniformLocation(program, ptr));
            // Create Vertex Array Object
            gl::GenVertexArrays(1, &mut vao);
            gl::BindVertexArray(vao);

            // Create a Vertex Buffer Object and copy the vertex data to it
            gl::GenBuffers(1, &mut vbo);
            gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
            gl::BufferData(gl::ARRAY_BUFFER,
                           (VERTEX_DATA.len() * sys::size_of::<GLfloat>()) as GLsizeiptr,
                           cast::transmute(&VERTEX_DATA[0]),
                           gl::STATIC_DRAW);

            // Use shader program
            gl::UseProgram(program);

            // Specify the layout of the vertex data
            let vert_attr = "vertex".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
            gl::EnableVertexAttribArray(vert_attr as GLuint);
            gl::VertexAttribPointer(vert_attr as GLuint, 2, gl::FLOAT,
                                    gl::FALSE as GLboolean, 0, ptr::null());
        }

        let rs: @System = @RenderSystem {program: program, position_uniform: position_uniform, scale_uniform: scale_uniform, color_uniform: color_uniform} as @System;
        world.systems.push(rs);

        while !window.should_close() {
            // Poll events
            glfw::poll_events();

            // Clear the screen to black
            gl::ClearColor(0.8, 0.8, 0.8, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);

            // process game world
            world.process();

            // Swap buffers
            window.swap_buffers();
        }

        // Cleanup
        gl::DeleteProgram(program);
        gl::DeleteShader(fs);
        gl::DeleteShader(vs);
        unsafe {
            gl::DeleteBuffers(1, &vbo);
            gl::DeleteVertexArrays(1, &vao);
        }
    }
}

fn key_callback(window: &glfw::Window, key: glfw::Key, _: libc::c_int, action: glfw::Action, _: glfw::Modifiers) {
    if action == glfw::Press && key == glfw::KeyEscape {
        window.set_should_close(true);
    }
}
<commit_msg>fixed sprite vertex positions/size<commit_after>// Copyright 2013 Torste Aikio and gl-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.

#[feature(globs)];
#[feature(macro_rules)];

extern mod glfw;
extern mod gl;

use std::libc;

use std::cast;
use std::ptr;
use std::str;
use std::sys;
use std::vec;

use std::io;
use std::path::PosixPath;

use gl::types::*;

// COMPONENT DEFINITIONS
struct Position {
    x: f64,
    y: f64
}

struct HorizVelocity {
    x: f64
}

struct VertVelocity {
    y: f64
}

struct Sprite {
    x_size: f64,
    y_size: f64,
    color: [f64, ..4]
}

struct Components {
    position: Option<@mut Position>,
    horiz_velocity: Option<@mut HorizVelocity>,
    vert_velocity: Option<@mut VertVelocity>,
    sprite: Option<@mut Sprite>
}

// SYSTEM DEFINITIONS
trait System {
    fn process(&self, entity: @Components) -> ();
}

struct MovementSystem;

impl System for MovementSystem {
    fn process(&self, entity: @Components) -> () {
        match entity.position {
            Some(pos) => {
                match entity.vert_velocity {
                    Some(v) => pos.y += v.y,
                    None => ()
                }
                match entity.horiz_velocity {
                    Some(v) => pos.x += v.x,
                    None => ()
                }
            },
            None => ()
        }
    }
}

struct EdgeCollisionSystem;

impl System for EdgeCollisionSystem {
    fn process(&self, entity: @Components) -> () {
        match (entity.position, entity.vert_velocity) {
            (Some(pos), Some(vel)) => {
                if pos.y >= 4.0 || pos.y <= 0.0 {
                    vel.y *= -1.0;
                }
            },
            (_, _) => ()
        }
    }
}

struct PaddleCollisionSystem {
    left_paddle: @Components,
    right_paddle: @Components,
}

impl System for PaddleCollisionSystem {
    fn process(&self, entity: @Components) -> () {
        //TODO use a hitbox or something instead of sprite
        match (entity.position, entity.horiz_velocity, entity.sprite) {
            (Some(pos), Some(vel), Some(spr)) => {
                if (pos.x+(spr.x_size)/2.0) >= (self.right_paddle.position.unwrap().x-(self.right_paddle.sprite.unwrap().x_size)/2.0) {
                    if std::num::abs(pos.y - self.right_paddle.position.unwrap().y) < (self.right_paddle.sprite.unwrap().y_size/2.0) {
                        vel.x *= -1.0;
                    }
                }
                if (pos.x-(spr.x_size)/2.0) <= (self.left_paddle.position.unwrap().x+(self.left_paddle.sprite.unwrap().x_size)/2.0) {
                    if std::num::abs(pos.y - self.left_paddle.position.unwrap().y) < (self.left_paddle.sprite.unwrap().y_size/2.0) {
                        vel.x *= -1.0;
                    }
                }
            },
            (_, _, _) => ()
        }
    }
}

struct RenderSystem {
    program: GLuint,
    position_uniform: GLint,
    scale_uniform: GLint,
    color_uniform: GLint
}

impl System for RenderSystem {
    fn process(&self, entity: @Components) -> () {
        match (entity.position, entity.sprite) {
            (Some(pos), Some(sprite)) => {
                // Set uniforms
                gl::ProgramUniform2f(self.program, self.position_uniform, pos.x as f32, pos.y as f32);
                gl::ProgramUniform2f(self.program, self.scale_uniform, sprite.x_size as f32, sprite.y_size as f32);
                gl::ProgramUniform4f(self.program, self.color_uniform, sprite.color[0] as f32, sprite.color[1] as f32, sprite.color[2] as f32, sprite.color[3] as f32);
                // Draw a rect from the 4 vertices
                gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4);
            },
            (_, _) => ()
        }
    }
}

// WORLD DEFINITION
// We need to figure out how to integrate World with the main game loop
// in Artemis world has a `setDelta` method for timestep
struct World {
    entities: ~[@Components],
    systems: ~[@System]
}

impl World {
    fn new() -> World {
        return World {entities: ~[], systems: ~[]};
    }

    fn process(&self) {
        for system in self.systems.iter() {
            for entity in self.entities.iter() {
                system.process(*entity);
            }
        }
    }
}

//ENTITY CONSTRUCTORS
enum PaddleSide {
    RIGHT,
    LEFT
}

fn new_ball() -> @Components {
    @Components {
        position: Some(@mut Position { x: 2.0, y: 1.5 }),
        horiz_velocity: Some(@mut HorizVelocity { x: 1.0/60.0 }),
        vert_velocity: Some(@mut VertVelocity { y: 0.0 }),
        sprite: Some(@mut Sprite {
            x_size: 0.05,
            y_size: 0.05,
            color: [0.3, 0.3, 0.8, 1.0]
        })
    }
}

fn new_paddle(side: PaddleSide) -> @Components {
    let xpos = match side {
        RIGHT => 3.9,
        LEFT => 0.1
    };
    @Components {
        position: Some(@mut Position { x: xpos, y: 1.5 }),
        horiz_velocity: None,
        vert_velocity: Some(@mut VertVelocity { y: 0.0 }),
        sprite: Some(@mut Sprite {
            x_size: 0.1,
            y_size: 0.4,
            color: [xpos/4.0, 1.0-(xpos/4.0), 0.3, 1.0]
        })
    }
}

// OPENGL ETC STUFF

// Vertex data
static VERTEX_DATA: [GLfloat, ..8] = [
    -0.5,  0.5,
    -0.5, -0.5,
     0.5,  0.5,
     0.5, -0.5
];

#[start]
fn start(argc: int, argv: **u8) -> int {
    std::rt::start_on_main_thread(argc, argv, main)
}

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
    let shader = gl::CreateShader(ty);
    unsafe {
        // Attempt to compile the shader
        src.with_c_str(|ptr| gl::ShaderSource(shader, 1, &ptr, ptr::null()));
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::mut_null(), vec::raw::to_mut_ptr(buf) as *mut GLchar);
            fail!(str::raw::from_utf8(buf));
        }
    }
    shader
}

fn link_program(vs: GLuint, fs: GLuint, out_color: &str) -> GLuint {
    let program = gl::CreateProgram();
    gl::AttachShader(program, vs);
    gl::AttachShader(program, fs);
    // gl::BindFragDataLocation needs to be called before linking to have effect
    unsafe {
        out_color.with_c_str(|ptr| gl::BindFragDataLocation(program, 0, ptr));
    }
    gl::LinkProgram(program);
    unsafe {
        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = vec::from_elem(len as uint - 1, 0u8);     // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::mut_null(), vec::raw::to_mut_ptr(buf) as *mut GLchar);
            fail!(str::raw::from_utf8(buf));
        }
    }
    program
}

fn main() {
    do glfw::set_error_callback |_, description| {
        println!("GLFW Error: {}", description);
    }

    do glfw::start {
        // initialize game world
        let left_paddle: @Components = new_paddle(LEFT);
        let right_paddle: @Components = new_paddle(RIGHT);
        let ball: @Components = new_ball();
        let ms: @System = @MovementSystem as @System;
        let es: @System = @EdgeCollisionSystem as @System;
        let ps: @System = @PaddleCollisionSystem{ right_paddle: right_paddle, left_paddle: left_paddle } as @System;

        let mut world: World = World::new();
        world.entities.push(left_paddle);
        world.entities.push(right_paddle);
        world.entities.push(ball);
        world.systems.push(ms);
        world.systems.push(es);
        world.systems.push(ps);

        // Choose a GL profile that is compatible with OS X 10.7+
        glfw::window_hint::context_version(3, 2);
        glfw::window_hint::opengl_profile(glfw::OpenGlCoreProfile);
        glfw::window_hint::opengl_forward_compat(true);

        let window = glfw::Window::create(1024, 600, "Pong", glfw::Windowed).unwrap();
        window.set_key_callback(key_callback);
        window.make_context_current();

        // Load the OpenGL function pointers
        gl::load_with(glfw::get_proc_address);

        // Create GLSL shaders
        let vs_src = io::read_whole_file_str(&PosixPath("main.vs.glsl")).unwrap();
        let vs = compile_shader(vs_src, gl::VERTEX_SHADER);
        let fs_src = io::read_whole_file_str(&PosixPath("main.fs.glsl")).unwrap();
        let fs = compile_shader(fs_src, gl::FRAGMENT_SHADER);
        let program = link_program(vs, fs, "out_color");

        let mut vao = 0;
        let mut vbo = 0;

        let position_uniform: GLint;
        let scale_uniform: GLint;
        let color_uniform: GLint;

        unsafe {
            position_uniform = "position".with_c_str(|ptr| gl::GetUniformLocation(program, ptr));
            scale_uniform = "scale".with_c_str(|ptr| gl::GetUniformLocation(program, ptr));
            color_uniform = "color".with_c_str(|ptr| gl::GetUniformLocation(program, ptr));
            // Create Vertex Array Object
            gl::GenVertexArrays(1, &mut vao);
            gl::BindVertexArray(vao);

            // Create a Vertex Buffer Object and copy the vertex data to it
            gl::GenBuffers(1, &mut vbo);
            gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
            gl::BufferData(gl::ARRAY_BUFFER,
                           (VERTEX_DATA.len() * sys::size_of::<GLfloat>()) as GLsizeiptr,
                           cast::transmute(&VERTEX_DATA[0]),
                           gl::STATIC_DRAW);

            // Use shader program
            gl::UseProgram(program);

            // Specify the layout of the vertex data
            let vert_attr = "vertex".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
            gl::EnableVertexAttribArray(vert_attr as GLuint);
            gl::VertexAttribPointer(vert_attr as GLuint, 2, gl::FLOAT,
                                    gl::FALSE as GLboolean, 0, ptr::null());
        }

        let rs: @System = @RenderSystem {program: program, position_uniform: position_uniform, scale_uniform: scale_uniform, color_uniform: color_uniform} as @System;
        world.systems.push(rs);

        while !window.should_close() {
            // Poll events
            glfw::poll_events();

            // Clear the screen to black
            gl::ClearColor(0.8, 0.8, 0.8, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);

            // process game world
            world.process();

            // Swap buffers
            window.swap_buffers();
        }

        // Cleanup
        gl::DeleteProgram(program);
        gl::DeleteShader(fs);
        gl::DeleteShader(vs);
        unsafe {
            gl::DeleteBuffers(1, &vbo);
            gl::DeleteVertexArrays(1, &vao);
        }
    }
}

fn key_callback(window: &glfw::Window, key: glfw::Key, _: libc::c_int, action: glfw::Action, _: glfw::Modifiers) {
    if action == glfw::Press && key == glfw::KeyEscape {
        window.set_should_close(true);
    }
}
<|endoftext|>


<commit_before>struct Stack {
    content: Vec<i32>,
    digits: Vec<i32>,
}

impl Stack {
    fn push(&mut self, d: i32) -> Result<i32, &str> {
        self.content.push(d);
        Ok(d)
    }

    fn pop(&mut self) -> Option<i32> {
        self.content.pop()
    }

    fn consume_digit(&mut self, d: i32) {
        let i = self.digits.iter().position(|&i| i == d).expect("Cannot consume!");
        self.digits.remove(i);
    }

    fn valid_digit(&self, d: i32) -> bool {
        self.digits.contains(&d)
    }

    fn add_digit(&mut self, c: char) -> Result<i32, &str> {
        match c.to_digit(10) {
            Some(n) => match self.valid_digit(n as i32) {
                true => {
                    self.consume_digit(n as i32);
                    self.push(n as i32)
                },
                false => Err("Invalid or duplicate digit!"),
            },
            None => Err("Invalid character"),
        }
    }

    fn apply<F>(&mut self, f: F) -> Result<i32, &str>
        where F : Fn(i32, i32) -> i32 {

        let r = self.pop();
        let l = self.pop();

        match l {
            Some(n) => match r {
                Some(i) => self.push(f(n, i)),
                None => Err("Stack empty"),
            },
            None => Err("Stack empty"),
        }
    }
}

fn evaluate<'a>(program: Vec<char>, digits: Vec<i32>) -> Result<i32, &'a str> {
    let mut stack = Stack {
        content: vec![],
        digits: digits,
    };

    for c in program {
        let answer: Result<i32, &str> = match c {
            '*' => stack.apply(|l, r| l * r),
            '+' => stack.apply(|l, r| l + r),
            '-' => stack.apply(|l, r| l - r),
            '/' => stack.apply(|l, r| l / r),
            _ => stack.add_digit(c),
        };

        if answer.is_err() {
            // TODO: Fix this. Work out how to return "answer" without compiler error.
            println!("Actual: {}", answer.unwrap_err());
            return Err("Program error");
        }
    }

    match stack.content.len() {
        1 => Ok(stack.content[0]),
        _ => Err("Invalid formula"),
    }
}

fn main() {
    let program: Vec<char> = "3 2 * 4 * 1 /".chars().filter(|&c| c != ' ').collect();
    let goal: i32 = 24;
    let digits: Vec<i32> = vec![2, 3, 1, 4];

    match evaluate(program, digits) {
        Ok(n) => if n == goal {
            println!("Well done!");
        } else {
            println!("Nice try, but {} is not {}!", n, goal);
        },
        Err(s) => {
            println!("Oops: {}", s);
        },
    }
}
<commit_msg>TODO note about ensuring all digits were used<commit_after>struct Stack {
    content: Vec<i32>,
    digits: Vec<i32>,
}

impl Stack {
    fn push(&mut self, d: i32) -> Result<i32, &str> {
        self.content.push(d);
        Ok(d)
    }

    fn pop(&mut self) -> Option<i32> {
        self.content.pop()
    }

    fn consume_digit(&mut self, d: i32) {
        let i = self.digits.iter().position(|&i| i == d).expect("Cannot consume!");
        self.digits.remove(i);
    }

    fn valid_digit(&self, d: i32) -> bool {
        self.digits.contains(&d)
    }

    // TODO: Also check that digits.len() == 0
    //       And return a "Result".
    fn reveal(&self) -> usize {
        self.content.len()
    }

    fn add_digit(&mut self, c: char) -> Result<i32, &str> {
        match c.to_digit(10) {
            Some(n) => match self.valid_digit(n as i32) {
                true => {
                    self.consume_digit(n as i32);
                    self.push(n as i32)
                },
                false => Err("Invalid or duplicate digit!"),
            },
            None => Err("Invalid character"),
        }
    }

    fn apply<F>(&mut self, f: F) -> Result<i32, &str>
        where F : Fn(i32, i32) -> i32 {

        let r = self.pop();
        let l = self.pop();

        match l {
            Some(n) => match r {
                Some(i) => self.push(f(n, i)),
                None => Err("Stack empty"),
            },
            None => Err("Stack empty"),
        }
    }
}

fn evaluate<'a>(program: Vec<char>, digits: Vec<i32>) -> Result<i32, &'a str> {
    let mut stack = Stack {
        content: vec![],
        digits: digits,
    };

    for c in program {
        let answer: Result<i32, &str> = match c {
            '*' => stack.apply(|l, r| l * r),
            '+' => stack.apply(|l, r| l + r),
            '-' => stack.apply(|l, r| l - r),
            '/' => stack.apply(|l, r| l / r),
            _ => stack.add_digit(c),
        };

        if answer.is_err() {
            // TODO: Fix this. Work out how to return "answer" without compiler error.
            println!("Actual: {}", answer.unwrap_err());
            return Err("Program error");
        }
    }

    match stack.reveal() {
        1 => Ok(stack.content[0]),
        _ => Err("Invalid formula"),
    }
}

fn main() {
    let program: Vec<char> = "3 2 * 4 * 1 /".chars().filter(|&c| c != ' ').collect();
    let goal: i32 = 24;
    let digits: Vec<i32> = vec![2, 3, 1, 4];

    match evaluate(program, digits) {
        Ok(n) => if n == goal {
            println!("Well done!");
        } else {
            println!("Nice try, but {} is not {}!", n, goal);
        },
        Err(s) => {
            println!("Oops: {}", s);
        },
    }
}
<|endoftext|>


<commit_before>struct Stack {
    content: Vec<i32>,
    digits: Vec<i32>,
}

impl Stack {
    fn push(&mut self, d: i32) -> Result<i32, &str> {
        self.content.push(d);
        Ok(d)
    }

    fn pop(&mut self) -> Option<i32> {
        self.content.pop()
    }

    fn consume_digit(&mut self, d: i32) {
        self.digits.retain(|&n| n != d);
    }

    fn valid_digit(&self, d: i32) -> bool {
        self.digits.contains(&d)
    }

    fn add_digit(&mut self, c: char) -> Result<i32, &str> {
        match c.to_digit(10) {
            Some(n) => match self.valid_digit(n as i32) {
                true => {
                    self.consume_digit(n as i32);
                    self.push(n as i32)
                },
                false => Err("Invalid or duplicate digit!"),
            },
            None => Err("Invalid character"),
        }
    }

    fn apply<F>(&mut self, f: F) -> Result<i32, &str>
        where F : Fn(i32, i32) -> i32 {

        let r = self.pop();
        let l = self.pop();

        match l {
            Some(n) => match r {
                Some(i) => self.push(f(n, i)),
                None => Err("Stack empty"),
            },
            None => Err("Stack empty"),
        }
    }
}

fn evaluate<'a>(program: Vec<char>, digits: Vec<i32>) -> Result<i32, &'a str> {
    let mut stack = Stack {
        content: vec![],
        digits: digits,
    };

    for c in program {
        let answer: Result<i32, &str> = match c {
            '*' => stack.apply(|l, r| l * r),
            '+' => stack.apply(|l, r| l + r),
            '-' => stack.apply(|l, r| l - r),
            '/' => stack.apply(|l, r| l / r),
            _   => stack.add_digit(c),
        };

        if answer.is_err() {
            println!("Actual: {}", answer.unwrap_err());
            return Err("Ass");
        }
    }

    match stack.content.len() {
        1 => Ok(stack.content[0]),
        _ => Err("Invalid formula"),
    }
}

fn main() {
    let program: Vec<char> = "3 4 * 2 * 1 /".chars().filter(|&c| c != ' ').collect();
    let digits: Vec<i32> = vec![1, 2, 3, 4];

    match evaluate(program, digits) {
        Ok(n) => match n {
            24 => println!("Well done!"),
            _  => println!("Nice try, but {} is not 24!", n),
        },
        Err(s) => {
            println!("Oops: {}", s);
        },
    }
}
<commit_msg>TODO to fix lifetimes error<commit_after>struct Stack {
    content: Vec<i32>,
    digits: Vec<i32>,
}

impl Stack {
    fn push(&mut self, d: i32) -> Result<i32, &str> {
        self.content.push(d);
        Ok(d)
    }

    fn pop(&mut self) -> Option<i32> {
        self.content.pop()
    }

    fn consume_digit(&mut self, d: i32) {
        self.digits.retain(|&n| n != d);
    }

    fn valid_digit(&self, d: i32) -> bool {
        self.digits.contains(&d)
    }

    fn add_digit(&mut self, c: char) -> Result<i32, &str> {
        match c.to_digit(10) {
            Some(n) => match self.valid_digit(n as i32) {
                true => {
                    self.consume_digit(n as i32);
                    self.push(n as i32)
                },
                false => Err("Invalid or duplicate digit!"),
            },
            None => Err("Invalid character"),
        }
    }

    fn apply<F>(&mut self, f: F) -> Result<i32, &str>
        where F : Fn(i32, i32) -> i32 {

        let r = self.pop();
        let l = self.pop();

        match l {
            Some(n) => match r {
                Some(i) => self.push(f(n, i)),
                None => Err("Stack empty"),
            },
            None => Err("Stack empty"),
        }
    }
}

fn evaluate<'a>(program: Vec<char>, digits: Vec<i32>) -> Result<i32, &'a str> {
    let mut stack = Stack {
        content: vec![],
        digits: digits,
    };

    for c in program {
        let answer: Result<i32, &str> = match c {
            '*' => stack.apply(|l, r| l * r),
            '+' => stack.apply(|l, r| l + r),
            '-' => stack.apply(|l, r| l - r),
            '/' => stack.apply(|l, r| l / r),
            _   => stack.add_digit(c),
        };

        if answer.is_err() {
            // TODO: Fix this. Work out how to return "answer" without compiler error.
            // return answer;
            println!("Actual: {}", answer.unwrap_err());
            return Err("Program error");
        }
    }

    match stack.content.len() {
        1 => Ok(stack.content[0]),
        _ => Err("Invalid formula"),
    }
}

fn main() {
    let program: Vec<char> = "3 4 * 2 * 1 /".chars().filter(|&c| c != ' ').collect();
    let digits: Vec<i32> = vec![1, 2, 3, 4];

    match evaluate(program, digits) {
        Ok(n) => match n {
            24 => println!("Well done!"),
            _  => println!("Nice try, but {} is not 24!", n),
        },
        Err(s) => {
            println!("Oops: {}", s);
        },
    }
}
<|endoftext|>