<commit_before>// Copyright (c) 2017-2019 Linaro LTD
// Copyright (c) 2017-2019 JUUL Labs
// Copyright (c) 2019 Arm Limited
//
// SPDX-License-Identifier: Apache-2.0

use docopt::Docopt;
use log::{warn, error};
use std::{
    fmt,
    process,
};
use serde_derive::Deserialize;

mod caps;
mod depends;
mod image;
mod tlv;
pub mod testlog;

pub use crate::{
    depends::{
        DepTest,
        DepType,
        UpgradeInfo,
        NO_DEPS,
        REV_DEPS,
    },
    image::{
        ImagesBuilder,
        Images,
        show_sizes,
    },
};

const USAGE: &str = "
Mcuboot simulator

Usage:
  bootsim sizes
  bootsim run --device TYPE [--align SIZE]
  bootsim runall
  bootsim (--help | --version)

Options:
  -h, --help         Show this message
  --version          Version
  --device TYPE      MCU to simulate
                     Valid values: stm32f4, k64f
  --align SIZE       Flash write alignment
";

#[derive(Debug, Deserialize)]
struct Args {
    flag_help: bool,
    flag_version: bool,
    flag_device: Option<DeviceName>,
    flag_align: Option<AlignArg>,
    cmd_sizes: bool,
    cmd_run: bool,
    cmd_runall: bool,
}

#[derive(Copy, Clone, Debug, Deserialize)]
pub enum DeviceName {
    Stm32f4, K64f, K64fBig, K64fMulti, Nrf52840, Nrf52840SpiFlash,
    Nrf52840UnequalSlots,
}

pub static ALL_DEVICES: &[DeviceName] = &[
    DeviceName::Stm32f4,
    DeviceName::K64f,
    DeviceName::K64fBig,
    DeviceName::K64fMulti,
    DeviceName::Nrf52840,
    DeviceName::Nrf52840SpiFlash,
    DeviceName::Nrf52840UnequalSlots,
];

impl fmt::Display for DeviceName {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let name = match *self {
            DeviceName::Stm32f4 => "stm32f4",
            DeviceName::K64f => "k64f",
            DeviceName::K64fBig => "k64fbig",
            DeviceName::K64fMulti => "k64fmulti",
            DeviceName::Nrf52840 => "nrf52840",
            DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
            DeviceName::Nrf52840UnequalSlots => "Nrf52840UnequalSlots",
        };
        f.write_str(name)
    }
}

#[derive(Debug)]
struct AlignArg(usize);

struct AlignArgVisitor;

impl<'de> serde::de::Visitor<'de> for AlignArgVisitor {
    type Value = AlignArg;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("1, 2, 4 or 8")
    }

    fn visit_u32<E>(self, n: u32) -> Result<Self::Value, E>
        where E: serde::de::Error
    {
        Ok(match n {
            1 | 2 | 4 | 8 => AlignArg(n as usize),
            n => {
                let err = format!("Could not deserialize '{}' as alignment", n);
                return Err(E::custom(err));
            }
        })
    }
}

impl<'de> serde::de::Deserialize<'de> for AlignArg {
    fn deserialize<D>(d: D) -> Result<AlignArg, D::Error>
        where D: serde::de::Deserializer<'de>
    {
        d.deserialize_u8(AlignArgVisitor)
    }
}

pub fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());
    // println!("args: {:#?}", args);

    if args.cmd_sizes {
        show_sizes();
        return;
    }

    let mut status = RunStatus::new();
    if args.cmd_run {

        let align = args.flag_align.map(|x| x.0).unwrap_or(1);

        let device = match args.flag_device {
            None => panic!("Missing mandatory device argument"),
            Some(dev) => dev,
        };

        status.run_single(device, align, 0xff);
    }

    if args.cmd_runall {
        for &dev in ALL_DEVICES {
            for &align in &[1, 2, 4, 8] {
                for &erased_val in &[0, 0xff] {
                    status.run_single(dev, align, erased_val);
                }
            }
        }
    }

    if status.failures > 0 {
        error!("{} Tests ran with {} failures", status.failures + status.passes, status.failures);
        process::exit(1);
    } else {
        error!("{} Tests ran successfully", status.passes);
        process::exit(0);
    }
}

#[derive(Default)]
pub struct RunStatus {
    failures: usize,
    passes: usize,
}

impl RunStatus {
    pub fn new() -> RunStatus {
        RunStatus {
            failures: 0,
            passes: 0,
        }
    }

    pub fn run_single(&mut self, device: DeviceName, align: usize, erased_val: u8) {
        warn!("Running on device {} with alignment {}", device, align);

        let run = match ImagesBuilder::new(device, align, erased_val) {
            Ok(builder) => builder,
            Err(msg) => {
                warn!("Skipping {}: {}", device, msg);
                return;
            }
        };

        let mut failed = false;

        // Creates a badly signed image in the secondary slot to check that
        // it is not upgraded to
        let bad_secondary_slot_image = run.clone().make_bad_secondary_slot_image();

        failed |= bad_secondary_slot_image.run_signfail_upgrade();

        let images = run.clone().make_no_upgrade_image(&NO_DEPS);
        failed |= images.run_norevert_newimage();

        let images = run.make_image(&NO_DEPS, true);

        failed |= images.run_basic_revert();
        failed |= images.run_revert_with_fails();
        failed |= images.run_perm_with_fails();
        failed |= images.run_perm_with_random_fails(5);
        failed |= images.run_norevert();

        failed |= images.run_with_status_fails_complete();
        failed |= images.run_with_status_fails_with_reset();

        //show_flash(&flash);

        if failed {
            self.failures += 1;
        } else {
            self.passes += 1;
        }
    }

    pub fn failures(&self) -> usize {
        self.failures
    }
}
<commit_msg>sim: Remove unused variables<commit_after>// Copyright (c) 2017-2019 Linaro LTD
// Copyright (c) 2017-2019 JUUL Labs
// Copyright (c) 2019 Arm Limited
//
// SPDX-License-Identifier: Apache-2.0

use docopt::Docopt;
use log::{warn, error};
use std::{
    fmt,
    process,
};
use serde_derive::Deserialize;

mod caps;
mod depends;
mod image;
mod tlv;
pub mod testlog;

pub use crate::{
    depends::{
        DepTest,
        DepType,
        UpgradeInfo,
        NO_DEPS,
        REV_DEPS,
    },
    image::{
        ImagesBuilder,
        Images,
        show_sizes,
    },
};

const USAGE: &str = "
Mcuboot simulator

Usage:
  bootsim sizes
  bootsim run --device TYPE [--align SIZE]
  bootsim runall
  bootsim (--help | --version)

Options:
  -h, --help         Show this message
  --version          Version
  --device TYPE      MCU to simulate
                     Valid values: stm32f4, k64f
  --align SIZE       Flash write alignment
";

#[derive(Debug, Deserialize)]
struct Args {
    flag_device: Option<DeviceName>,
    flag_align: Option<AlignArg>,
    cmd_sizes: bool,
    cmd_run: bool,
    cmd_runall: bool,
}

#[derive(Copy, Clone, Debug, Deserialize)]
pub enum DeviceName {
    Stm32f4, K64f, K64fBig, K64fMulti, Nrf52840, Nrf52840SpiFlash,
    Nrf52840UnequalSlots,
}

pub static ALL_DEVICES: &[DeviceName] = &[
    DeviceName::Stm32f4,
    DeviceName::K64f,
    DeviceName::K64fBig,
    DeviceName::K64fMulti,
    DeviceName::Nrf52840,
    DeviceName::Nrf52840SpiFlash,
    DeviceName::Nrf52840UnequalSlots,
];

impl fmt::Display for DeviceName {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let name = match *self {
            DeviceName::Stm32f4 => "stm32f4",
            DeviceName::K64f => "k64f",
            DeviceName::K64fBig => "k64fbig",
            DeviceName::K64fMulti => "k64fmulti",
            DeviceName::Nrf52840 => "nrf52840",
            DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
            DeviceName::Nrf52840UnequalSlots => "Nrf52840UnequalSlots",
        };
        f.write_str(name)
    }
}

#[derive(Debug)]
struct AlignArg(usize);

struct AlignArgVisitor;

impl<'de> serde::de::Visitor<'de> for AlignArgVisitor {
    type Value = AlignArg;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("1, 2, 4 or 8")
    }

    fn visit_u32<E>(self, n: u32) -> Result<Self::Value, E>
        where E: serde::de::Error
    {
        Ok(match n {
            1 | 2 | 4 | 8 => AlignArg(n as usize),
            n => {
                let err = format!("Could not deserialize '{}' as alignment", n);
                return Err(E::custom(err));
            }
        })
    }
}

impl<'de> serde::de::Deserialize<'de> for AlignArg {
    fn deserialize<D>(d: D) -> Result<AlignArg, D::Error>
        where D: serde::de::Deserializer<'de>
    {
        d.deserialize_u8(AlignArgVisitor)
    }
}

pub fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());
    // println!("args: {:#?}", args);

    if args.cmd_sizes {
        show_sizes();
        return;
    }

    let mut status = RunStatus::new();
    if args.cmd_run {

        let align = args.flag_align.map(|x| x.0).unwrap_or(1);

        let device = match args.flag_device {
            None => panic!("Missing mandatory device argument"),
            Some(dev) => dev,
        };

        status.run_single(device, align, 0xff);
    }

    if args.cmd_runall {
        for &dev in ALL_DEVICES {
            for &align in &[1, 2, 4, 8] {
                for &erased_val in &[0, 0xff] {
                    status.run_single(dev, align, erased_val);
                }
            }
        }
    }

    if status.failures > 0 {
        error!("{} Tests ran with {} failures", status.failures + status.passes, status.failures);
        process::exit(1);
    } else {
        error!("{} Tests ran successfully", status.passes);
        process::exit(0);
    }
}

#[derive(Default)]
pub struct RunStatus {
    failures: usize,
    passes: usize,
}

impl RunStatus {
    pub fn new() -> RunStatus {
        RunStatus {
            failures: 0,
            passes: 0,
        }
    }

    pub fn run_single(&mut self, device: DeviceName, align: usize, erased_val: u8) {
        warn!("Running on device {} with alignment {}", device, align);

        let run = match ImagesBuilder::new(device, align, erased_val) {
            Ok(builder) => builder,
            Err(msg) => {
                warn!("Skipping {}: {}", device, msg);
                return;
            }
        };

        let mut failed = false;

        // Creates a badly signed image in the secondary slot to check that
        // it is not upgraded to
        let bad_secondary_slot_image = run.clone().make_bad_secondary_slot_image();

        failed |= bad_secondary_slot_image.run_signfail_upgrade();

        let images = run.clone().make_no_upgrade_image(&NO_DEPS);
        failed |= images.run_norevert_newimage();

        let images = run.make_image(&NO_DEPS, true);

        failed |= images.run_basic_revert();
        failed |= images.run_revert_with_fails();
        failed |= images.run_perm_with_fails();
        failed |= images.run_perm_with_random_fails(5);
        failed |= images.run_norevert();

        failed |= images.run_with_status_fails_complete();
        failed |= images.run_with_status_fails_with_reset();

        //show_flash(&flash);

        if failed {
            self.failures += 1;
        } else {
            self.passes += 1;
        }
    }

    pub fn failures(&self) -> usize {
        self.failures
    }
}
<|endoftext|>


<commit_before>use libc::{uint64_t, int64_t, c_void, c_char, c_double};
use std::ffi::CString;
use std::ptr;
use energy_reader::EnergyReader;

#[link(name = "hbt-acc-pow")]
extern {
    fn heartbeat_acc_pow_init(parent: *mut c_void,
                              window_size: uint64_t,
                              buffer_depth: uint64_t,
                              log_name: *const c_char,
                              num_energy_impls: uint64_t,
                              energy_impls: *mut c_void) -> *mut c_void;

    fn heartbeat_acc(hb: *mut c_void,
                     user_tag: uint64_t,
                     work: uint64_t,
                     accuracy: c_double,
                     hb_prev: *mut c_void) -> int64_t;

    fn heartbeat_finish(hb: *mut c_void);
}

pub struct Heartbeat {
    hb: *mut c_void,
}

impl Heartbeat {
    pub fn new(parent: Option<&mut Heartbeat>,
               window_size: u64,
               buffer_depth: u64,
               log_name: &str,
               energy_impl: &mut EnergyReader) -> Result<Heartbeat, String> {
        let parent = match parent {
            Some(p) => p.hb,
            None => ptr::null_mut(),
        };
        let heart = unsafe {
            heartbeat_acc_pow_init(parent, window_size, buffer_depth,
                                   CString::new(log_name).unwrap().as_ptr(),
                                   1, energy_impl.er)
        };
        if heart.is_null() {
            return Err("Failed to initialize heartbeat".to_string());
        }
        Ok(Heartbeat { hb: heart, })
    }

    pub fn heartbeat(&mut self,
                     tag: u64,
                     work: u64,
                     accuracy: f64,
                     hb_prev: Option<&Heartbeat>) -> i64 {
        let hb_prev = match hb_prev {
            Some(p) => p.hb,
            None => ptr::null_mut(),
        };
        unsafe {
            heartbeat_acc(self.hb, tag, work, accuracy, hb_prev)
        }
    }
}

impl Drop for Heartbeat {
    fn drop(&mut self) {
        unsafe {
            heartbeat_finish(self.hb);
        }
    }
}

<commit_msg>hb in struct must be pub<commit_after>use libc::{uint64_t, int64_t, c_void, c_char, c_double};
use std::ffi::CString;
use std::ptr;
use energy_reader::EnergyReader;

#[link(name = "hbt-acc-pow")]
extern {
    fn heartbeat_acc_pow_init(parent: *mut c_void,
                              window_size: uint64_t,
                              buffer_depth: uint64_t,
                              log_name: *const c_char,
                              num_energy_impls: uint64_t,
                              energy_impls: *mut c_void) -> *mut c_void;

    fn heartbeat_acc(hb: *mut c_void,
                     user_tag: uint64_t,
                     work: uint64_t,
                     accuracy: c_double,
                     hb_prev: *mut c_void) -> int64_t;

    fn heartbeat_finish(hb: *mut c_void);
}

pub struct Heartbeat {
    pub hb: *mut c_void,
}

impl Heartbeat {
    pub fn new(parent: Option<&mut Heartbeat>,
               window_size: u64,
               buffer_depth: u64,
               log_name: &str,
               energy_impl: &mut EnergyReader) -> Result<Heartbeat, String> {
        let parent = match parent {
            Some(p) => p.hb,
            None => ptr::null_mut(),
        };
        let heart = unsafe {
            heartbeat_acc_pow_init(parent, window_size, buffer_depth,
                                   CString::new(log_name).unwrap().as_ptr(),
                                   1, energy_impl.er)
        };
        if heart.is_null() {
            return Err("Failed to initialize heartbeat".to_string());
        }
        Ok(Heartbeat { hb: heart, })
    }

    pub fn heartbeat(&mut self,
                     tag: u64,
                     work: u64,
                     accuracy: f64,
                     hb_prev: Option<&Heartbeat>) -> i64 {
        let hb_prev = match hb_prev {
            Some(p) => p.hb,
            None => ptr::null_mut(),
        };
        unsafe {
            heartbeat_acc(self.hb, tag, work, accuracy, hb_prev)
        }
    }
}

impl Drop for Heartbeat {
    fn drop(&mut self) {
        unsafe {
            heartbeat_finish(self.hb);
        }
    }
}

<|endoftext|>


<commit_before>use std::net::SocketAddr;
use std::sync::{ Arc, RwLock };
use std::thread::{ JoinHandle, spawn };
use bytes::BytesMut;
use futures::future;
use futures::future::Either;
use tokio::prelude::{ Async, AsyncRead, Future, Poll, Stream };
use tokio::net::{ TcpStream, TcpListener };
use tokio::io;
use ::config::ServerConfig;
use ::state::State;

#[derive(Clone)]
pub struct Server {
    config: ServerConfig,
    state: Arc<RwLock<State>>
}

impl Server {
    pub fn new(config: ServerConfig, state: Arc<RwLock<State>>) -> Self {
        Self { config, state }
    }

    pub fn start(&mut self) {
        let addr = SocketAddr::new(self.config.listen_address, self.config.listen_port);

        if let Ok(listener) = TcpListener::bind(&addr) {
            let server = listener.incoming().for_each(move |socket| {
                println!("New connection: {:?}", socket.peer_addr().unwrap());

                let codec = ClientCodec::new(socket);

                // ---------------------------------
                let connection = codec.into_future()
                    .map_err(|(e, _)| e)
                    .and_then(|(first_event, events)| {
                        println!("First event: {:?}", first_event);

                        match first_event {
                            None => return Either::A(future::ok(())),
                            _ => ()
                        }

                        let client = Client::new(events);

                        Either::B(client)
                    })
                    .map_err(|_| ());
/*
                let connection = TestFuture::new(socket).then(|_| {
                    println!("Accepted and stuff");
                    Ok(())
                }).map_err(|_| ());
                */

                ::tokio::spawn(connection);

                Ok(())
            }).map_err(|err| println!("Accept error: {:?}", err));

            ::tokio::run(server);
        } else {
            println!("Failed to bind to address: {:?}", addr);
        }
    }

    pub fn start_detached(&mut self) -> JoinHandle<()> {
        let mut self_clone = self.clone();

        spawn(move || {
            self_clone.start();
        })
    }

    pub fn stop(self, handle: JoinHandle<()>) {
        match handle.join() {
            Ok(h) => println!("Server stopped {:?}", h),
            Err(err) => println!("Error while joining {:?}", err)
        }
    }
}

struct ClientCodec {
    stream: TcpStream,
    read_buffer: BytesMut,
    write_buffer: BytesMut
}

impl ClientCodec {
    pub fn new(stream: TcpStream) -> Self {
        Self {
            stream,
            read_buffer: BytesMut::new(),
            write_buffer: BytesMut::new()
        }
    }

    fn read_next_packet(&mut self) -> Poll<(), io::Error> {
        loop {
            self.read_buffer.reserve(1024);

            let n = try_ready!(self.stream.read_buf(&mut self.read_buffer));

            println!("Got value from try_ready: {}", n);

            if n == 0 {
                return Ok(Async::Ready(()))
            }
        }
    }
}

impl Stream for ClientCodec {

    type Item = ClientMessage;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let sock_closed = self.read_next_packet()?.is_ready();

        println!("- read next {:?} {:?}", sock_closed, self.read_buffer.len());

        if self.read_buffer.len() >= 10 {
            let msg_code = self.read_buffer.split_to(2);

            match &msg_code[..] {
                b"he" => println!("Hello request"),
                _ => println!("Unknown package")

            }

            return Ok(Async::Ready(Some(ClientMessage::Noop)))
        }

        if sock_closed {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::NotReady)
        }
    }
}

#[derive(Debug)]
enum ClientMessage {
    Noop
}

struct Client {
    codec: ClientCodec
}

impl Client {
    pub fn new(codec: ClientCodec) -> Self {
        Self { codec }
    }
}

impl Future for Client {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        while let Async::Ready(event) = self.codec.poll()? {
            println!("Got some event: {:?}", event);

            if let Some(msg) = event {
                println!("Processing message: {:?}", msg);
            } else {
                println!("No more messages, client has disconnected");
                return Ok(Async::Ready(()))
            }
        }

        Ok(Async::NotReady)
    }
}
/*
struct TestFuture {
    inner: Box<Future<Item=(), Error=()>>
}

impl TestFuture {
    pub fn new(stream: TcpStream) -> Self {
        Self {
            inner: Box::new(io::write_all(stream, "HELLO\n").map(|_| ()).map_err(|_| ()))
        }
    }
}

impl Future for TestFuture {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
        let v = try_ready!(self.inner.poll());
        Ok(Async::Ready(()))

        //try_ready!(self.inner.poll())
    }

}
*/

enum ClientState {
    NewConnection(TcpStream),
}

struct AcceptClient {
    state: ClientState,
}

impl AcceptClient {
    pub fn new(stream: TcpStream) -> AcceptClient {
        Self { state: ClientState::NewConnection(stream) }
    }
}

impl Future for AcceptClient {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
        /*
        match self.state {
            ClientState::NewConnection(ref mut stream) => {
                let mut a = io::write_all(stream, "HELLO\n")
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "ACK\n") })
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "KTHXBYE\n") })
                .map(|_| ());

                a.poll()
            }
        }
        */

        match self.state {
            ClientState::NewConnection(ref mut stream) => {
                let mut a = io::write_all(stream, "HELLO\n")
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "ACK\n") })
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "KTHXBYE\n") })
                .map(|_| ());

                loop {
                    let v = match a.poll() {
                        Ok(Async::Ready(t)) => t,
                        Ok(Async::NotReady) => return Ok(Async::NotReady),
                        Err(err) => return Err(err)
                    };

                    println!("Got result: {:?}", v);
                    break;
                };

                Ok(Async::Ready(()))
            }
        }
    }
}<commit_msg>Removed some unused code<commit_after>use std::net::SocketAddr;
use std::sync::{ Arc, RwLock };
use std::thread::{ JoinHandle, spawn };
use bytes::BytesMut;
use futures::future;
use futures::future::Either;
use tokio::prelude::{ Async, AsyncRead, Future, Poll, Stream };
use tokio::net::{ TcpStream, TcpListener };
use tokio::io;
use ::config::ServerConfig;
use ::state::State;

#[derive(Clone)]
pub struct Server {
    config: ServerConfig,
    state: Arc<RwLock<State>>
}

impl Server {
    pub fn new(config: ServerConfig, state: Arc<RwLock<State>>) -> Self {
        Self { config, state }
    }

    pub fn start(&mut self) {
        let addr = SocketAddr::new(self.config.listen_address, self.config.listen_port);

        if let Ok(listener) = TcpListener::bind(&addr) {
            let server = listener.incoming().for_each(move |socket| {
                println!("New connection: {:?}", socket.peer_addr().unwrap());

                let codec = ClientCodec::new(socket);

                // ---------------------------------
                let connection = codec.into_future()
                    .map_err(|(e, _)| e)
                    .and_then(|(first_event, events)| {
                        println!("First event: {:?}", first_event);

                        match first_event {
                            None => return Either::A(future::ok(())),
                            _ => ()
                        }

                        let client = Client::new(events);

                        Either::B(client)
                    })
                    .map_err(|_| ());
/*
                let connection = TestFuture::new(socket).then(|_| {
                    println!("Accepted and stuff");
                    Ok(())
                }).map_err(|_| ());
                */

                ::tokio::spawn(connection);

                Ok(())
            }).map_err(|err| println!("Accept error: {:?}", err));

            ::tokio::run(server);
        } else {
            println!("Failed to bind to address: {:?}", addr);
        }
    }

    pub fn start_detached(&mut self) -> JoinHandle<()> {
        let mut self_clone = self.clone();

        spawn(move || {
            self_clone.start();
        })
    }

    pub fn stop(self, handle: JoinHandle<()>) {
        match handle.join() {
            Ok(h) => println!("Server stopped {:?}", h),
            Err(err) => println!("Error while joining {:?}", err)
        }
    }
}

struct ClientCodec {
    stream: TcpStream,
    read_buffer: BytesMut,
    write_buffer: BytesMut
}

impl ClientCodec {
    pub fn new(stream: TcpStream) -> Self {
        Self {
            stream,
            read_buffer: BytesMut::new(),
            write_buffer: BytesMut::new()
        }
    }

    fn read_next_packet(&mut self) -> Poll<(), io::Error> {
        loop {
            self.read_buffer.reserve(1024);

            let n = try_ready!(self.stream.read_buf(&mut self.read_buffer));

            println!("Got value from try_ready: {}", n);

            if n == 0 {
                return Ok(Async::Ready(()))
            }
        }
    }
}

impl Stream for ClientCodec {

    type Item = ClientMessage;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let sock_closed = self.read_next_packet()?.is_ready();

        println!("- read next {:?} {:?}", sock_closed, self.read_buffer.len());

        if self.read_buffer.len() >= 10 {
            let msg_code = self.read_buffer.split_to(2);

            match &msg_code[..] {
                b"he" => println!("Hello request"),
                _ => println!("Unknown package")

            }

            return Ok(Async::Ready(Some(ClientMessage::Noop)))
        }

        if sock_closed {
            Ok(Async::Ready(None))
        } else {
            Ok(Async::NotReady)
        }
    }
}

#[derive(Debug)]
enum ClientMessage {
    Noop
}

struct Client {
    codec: ClientCodec
}

impl Client {
    pub fn new(codec: ClientCodec) -> Self {
        Self { codec }
    }
}

impl Future for Client {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<(), io::Error> {
        while let Async::Ready(event) = self.codec.poll()? {
            println!("Got some event: {:?}", event);

            if let Some(msg) = event {
                println!("Processing message: {:?}", msg);
            } else {
                println!("No more messages, client has disconnected");
                return Ok(Async::Ready(()))
            }
        }

        Ok(Async::NotReady)
    }
}

enum ClientState {
    NewConnection(TcpStream),
}

struct AcceptClient {
    state: ClientState,
}

impl AcceptClient {
    pub fn new(stream: TcpStream) -> AcceptClient {
        Self { state: ClientState::NewConnection(stream) }
    }
}

impl Future for AcceptClient {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {

        match self.state {
            ClientState::NewConnection(ref mut stream) => {
                let mut a = io::write_all(stream, "HELLO\n")
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "ACK\n") })
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "KTHXBYE\n") })
                .map(|_| ());

                loop {
                    let v = match a.poll() {
                        Ok(Async::Ready(t)) => t,
                        Ok(Async::NotReady) => return Ok(Async::NotReady),
                        Err(err) => return Err(err)
                    };

                    println!("Got result: {:?}", v);
                    break;
                };

                Ok(Async::Ready(()))
            }
        }
    }
}<|endoftext|>


<commit_before><commit_msg>cal func hash<commit_after><|endoftext|>


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

use base::ShareContext;
use context::GraphicsContextMethods;

use sync::Arc;
use geom::size::Size2D;
use io_surface::{IOSurface, kIOSurfaceBytesPerElement, kIOSurfaceBytesPerRow};
use io_surface::{kIOSurfaceHeight, kIOSurfaceIsGlobal, kIOSurfaceWidth};
use opengles::cgl::{CGLChoosePixelFormat, CGLContextObj, CGLCreateContext};
use opengles::cgl::{CGLSetCurrentContext, CGLTexImageIOSurface2D, kCGLNoError, kCGLPFACompliant};
use opengles::cgl::{kCGLPFADoubleBuffer};
use opengles::gl2::{BGRA, CLAMP_TO_EDGE, COLOR_ATTACHMENT0, FRAMEBUFFER};
use opengles::gl2::{FRAMEBUFFER_COMPLETE, GLenum, GLint, GLsizei, GLuint, LINEAR};
use opengles::gl2::{NEAREST, RGBA, TEXTURE_MAG_FILTER, TEXTURE_MIN_FILTER};
use opengles::gl2::{TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_S, TEXTURE_WRAP_T};
use opengles::gl2::{UNSIGNED_INT_8_8_8_8_REV};
use opengles::gl2;

use std::cast;
use std::ptr;

/// Mac-specific interface to 3D graphics contexts.
pub struct GraphicsContext {
    cgl_context: Arc<CGLContextObj>,
}

impl GraphicsContext {
    /// Returns a new context, possibly shared with another context.
    fn new_possibly_shared(share_context: Option<GraphicsContext>) -> GraphicsContext {
        unsafe {
            // Choose a pixel format.
            let attributes = [ kCGLPFADoubleBuffer, kCGLPFACompliant, 0 ];
            let mut pixel_format = ptr::null();
            let mut pixel_format_count = 1;
            let gl_error = CGLChoosePixelFormat(cast::transmute(&attributes[0]),
                                                &mut pixel_format,
                                                &mut pixel_format_count);
            assert!(gl_error == kCGLNoError);

            // Create the context.
            let cgl_context = ptr::null();
            let gl_error = match share_context {
                None => CGLCreateContext(pixel_format, ptr::null(), &cgl_context),
                Some(ref share_context) => {
                    let native = share_context.native();
                    CGLCreateContext(pixel_format, *native.get(), &cgl_context)
                }
            };
            assert!(gl_error == kCGLNoError);

            GraphicsContextMethods::wrap(Arc::new(cgl_context))
        }
    }
}

impl GraphicsContextMethods<CGLContextObj> for GraphicsContext {
    /// Wraps the given instance of the native Core OpenGL graphics context.
    fn wrap(instance: Arc<CGLContextObj>) -> GraphicsContext {
        GraphicsContext {
            cgl_context: instance
        }
    }

    /// Returns the underlying native 3D context without modifying its reference count.
    fn native(&self) -> Arc<CGLContextObj> {
        self.cgl_context.clone()
    }

    /// Creates a new offscreen 3D graphics context.
    fn new() -> GraphicsContext {
        GraphicsContext::new_possibly_shared(None)
    }

    /// Creates a new offscreen 3D graphics context shared with the given context.
    fn new_shared(share_context: GraphicsContext) -> GraphicsContext {
        GraphicsContext::new_possibly_shared(Some(share_context))
    }

    /// Makes this context the current context.
    fn make_current(&self) {
        unsafe {
            let gl_error = CGLSetCurrentContext(*self.cgl_context.get());
            assert!(gl_error == kCGLNoError)
        }
    }
}

impl Clone for GraphicsContext {
    fn clone(&self) -> GraphicsContext {
        GraphicsContextMethods::wrap(self.native())
    }
}

pub struct Context {
    surface: IOSurface,
    framebuffer: GLuint,
    texture: GLuint

    // FIXME: Needs drop.
}

pub fn init_cgl() -> GraphicsContext {
    let context: GraphicsContext = GraphicsContextMethods::new();
    context.make_current();
    context
}

pub fn init_surface(size: Size2D<int>) -> IOSurface {
    use core_foundation::boolean::CFBoolean;
    use core_foundation::string::CFString;
    use core_foundation::number::CFNumber;
    use core_foundation::dictionary::CFDictionary;
    use core_foundation::base::{CFType, TCFType};
    use io_surface;

    // TODO: dictionary constructor should be less ridiculous.
    // Or, we could add bindings for mutable dictionaries.
    let k_width: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceWidth) };
    let v_width: CFNumber = FromPrimitive::from_i32(size.width as i32).unwrap();

    let k_height: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceHeight) };
    let v_height: CFNumber = FromPrimitive::from_i32(size.height as i32).unwrap();

    let k_bytes_per_row: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceBytesPerRow) };
    let v_bytes_per_row: CFNumber = FromPrimitive::from_i32(size.width as i32 * 4).unwrap();

    let k_bytes_per_elem: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceBytesPerElement) };
    let v_bytes_per_elem: CFNumber = FromPrimitive::from_i32(4i32).unwrap();

    let k_is_global: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceIsGlobal) };
    let v_is_global = CFBoolean::true_value();

    let pairs: ~[(CFType, CFType)] = ~[
        (k_width.as_CFType(), v_width.as_CFType()),
        (k_height.as_CFType(), v_height.as_CFType()),
        (k_bytes_per_row.as_CFType(), v_bytes_per_row.as_CFType()),
        (k_bytes_per_elem.as_CFType(), v_bytes_per_elem.as_CFType()),
        (k_is_global.as_CFType(), v_is_global.as_CFType()),
    ];

    io_surface::new(&CFDictionary::from_CFType_pairs(pairs))
}

pub fn init_texture() -> GLuint {
    gl2::enable(TEXTURE_RECTANGLE_ARB);

    let texture = gl2::gen_textures(1)[0];
    gl2::bind_texture(TEXTURE_RECTANGLE_ARB, texture);
    gl2::tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_S, CLAMP_TO_EDGE as GLint);
    gl2::tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_T, CLAMP_TO_EDGE as GLint);
    gl2::tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_MAG_FILTER, LINEAR as GLint);
    gl2::tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_MIN_FILTER, NEAREST as GLint);
    return texture;
}

// Assumes the texture is already bound via gl2::bind_texture().
pub fn bind_surface_to_texture(context: &GraphicsContext, surface: &IOSurface, size: Size2D<int>) {
    use core_foundation::base::TCFType;
    // FIXME: There should be safe wrappers for this.
    unsafe {
        let native = context.native();
        let gl_error = CGLTexImageIOSurface2D(*native.get(),
                                              TEXTURE_RECTANGLE_ARB,
                                              RGBA as GLenum,
                                              size.width as GLsizei,
                                              size.height as GLsizei,
                                              BGRA as GLenum,
                                              UNSIGNED_INT_8_8_8_8_REV,
                                              cast::transmute(surface.as_concrete_TypeRef()),
                                              0);
        assert!(gl_error == kCGLNoError);
    }
}

pub fn bind_texture_to_framebuffer(texture: GLuint) {
    gl2::bind_texture(TEXTURE_RECTANGLE_ARB, 0);
    gl2::framebuffer_texture_2d(FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_RECTANGLE_ARB, texture, 0);
    assert!(gl2::check_framebuffer_status(FRAMEBUFFER) == FRAMEBUFFER_COMPLETE);
}

impl ShareContext for Context {
    fn new(size: Size2D<int>) -> Context {
        // Initialize CGL.
        let context = init_cgl();

        // Create the surface.
        let surface = init_surface(size.clone());

        // Create a framebuffer.
        let framebuffer = gl2::gen_framebuffers(1)[0];
        gl2::bind_framebuffer(FRAMEBUFFER, framebuffer);

        // Create and bind to the texture.
        let texture = init_texture();
        bind_surface_to_texture(&context, &surface, size);

        // Bind the texture to the framebuffer.
        bind_texture_to_framebuffer(texture);

        Context {
            surface: surface,
            framebuffer: framebuffer,
            texture: texture
        }
    }

    fn flush(&self) {
        gl2::finish();
    }

    fn id(&self) -> int {
        self.surface.get_id() as int
    }
}

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

use base::ShareContext;
use context::GraphicsContextMethods;

use sync::Arc;
use geom::size::Size2D;
use io_surface::{IOSurface, kIOSurfaceBytesPerElement, kIOSurfaceBytesPerRow};
use io_surface::{kIOSurfaceHeight, kIOSurfaceIsGlobal, kIOSurfaceWidth};
use opengles::cgl::{CGLChoosePixelFormat, CGLContextObj, CGLCreateContext};
use opengles::cgl::{CGLSetCurrentContext, CGLTexImageIOSurface2D, kCGLNoError, kCGLPFACompliant};
use opengles::cgl::{kCGLPFADoubleBuffer};
use opengles::gl2::{BGRA, CLAMP_TO_EDGE, COLOR_ATTACHMENT0, FRAMEBUFFER};
use opengles::gl2::{FRAMEBUFFER_COMPLETE, GLenum, GLint, GLsizei, GLuint, LINEAR};
use opengles::gl2::{NEAREST, RGBA, TEXTURE_MAG_FILTER, TEXTURE_MIN_FILTER};
use opengles::gl2::{TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_S, TEXTURE_WRAP_T};
use opengles::gl2::{UNSIGNED_INT_8_8_8_8_REV};
use opengles::gl2;

use std::cast;
use std::ptr;

/// Mac-specific interface to 3D graphics contexts.
pub struct GraphicsContext {
    cgl_context: Arc<CGLContextObj>,
}

impl GraphicsContext {
    /// Returns a new context, possibly shared with another context.
    fn new_possibly_shared(share_context: Option<GraphicsContext>) -> GraphicsContext {
        unsafe {
            // Choose a pixel format.
            let attributes = [ kCGLPFADoubleBuffer, kCGLPFACompliant, 0 ];
            let mut pixel_format = ptr::null();
            let mut pixel_format_count = 1;
            let gl_error = CGLChoosePixelFormat(cast::transmute(&attributes[0]),
                                                &mut pixel_format,
                                                &mut pixel_format_count);
            assert!(gl_error == kCGLNoError);

            // Create the context.
            let cgl_context = ptr::null();
            let gl_error = match share_context {
                None => CGLCreateContext(pixel_format, ptr::null(), &cgl_context),
                Some(ref share_context) => {
                    let native = share_context.native();
                    CGLCreateContext(pixel_format, *native, &cgl_context)
                }
            };
            assert!(gl_error == kCGLNoError);

            GraphicsContextMethods::wrap(Arc::new(cgl_context))
        }
    }
}

impl GraphicsContextMethods<CGLContextObj> for GraphicsContext {
    /// Wraps the given instance of the native Core OpenGL graphics context.
    fn wrap(instance: Arc<CGLContextObj>) -> GraphicsContext {
        GraphicsContext {
            cgl_context: instance
        }
    }

    /// Returns the underlying native 3D context without modifying its reference count.
    fn native(&self) -> Arc<CGLContextObj> {
        self.cgl_context.clone()
    }

    /// Creates a new offscreen 3D graphics context.
    fn new() -> GraphicsContext {
        GraphicsContext::new_possibly_shared(None)
    }

    /// Creates a new offscreen 3D graphics context shared with the given context.
    fn new_shared(share_context: GraphicsContext) -> GraphicsContext {
        GraphicsContext::new_possibly_shared(Some(share_context))
    }

    /// Makes this context the current context.
    fn make_current(&self) {
        unsafe {
            let gl_error = CGLSetCurrentContext(*self.cgl_context);
            assert!(gl_error == kCGLNoError)
        }
    }
}

impl Clone for GraphicsContext {
    fn clone(&self) -> GraphicsContext {
        GraphicsContextMethods::wrap(self.native())
    }
}

pub struct Context {
    surface: IOSurface,
    framebuffer: GLuint,
    texture: GLuint

    // FIXME: Needs drop.
}

pub fn init_cgl() -> GraphicsContext {
    let context: GraphicsContext = GraphicsContextMethods::new();
    context.make_current();
    context
}

pub fn init_surface(size: Size2D<int>) -> IOSurface {
    use core_foundation::boolean::CFBoolean;
    use core_foundation::string::CFString;
    use core_foundation::number::CFNumber;
    use core_foundation::dictionary::CFDictionary;
    use core_foundation::base::{CFType, TCFType};
    use io_surface;

    // TODO: dictionary constructor should be less ridiculous.
    // Or, we could add bindings for mutable dictionaries.
    let k_width: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceWidth) };
    let v_width: CFNumber = FromPrimitive::from_i32(size.width as i32).unwrap();

    let k_height: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceHeight) };
    let v_height: CFNumber = FromPrimitive::from_i32(size.height as i32).unwrap();

    let k_bytes_per_row: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceBytesPerRow) };
    let v_bytes_per_row: CFNumber = FromPrimitive::from_i32(size.width as i32 * 4).unwrap();

    let k_bytes_per_elem: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceBytesPerElement) };
    let v_bytes_per_elem: CFNumber = FromPrimitive::from_i32(4i32).unwrap();

    let k_is_global: CFString = unsafe { TCFType::wrap_under_get_rule(kIOSurfaceIsGlobal) };
    let v_is_global = CFBoolean::true_value();

    let pairs: ~[(CFType, CFType)] = ~[
        (k_width.as_CFType(), v_width.as_CFType()),
        (k_height.as_CFType(), v_height.as_CFType()),
        (k_bytes_per_row.as_CFType(), v_bytes_per_row.as_CFType()),
        (k_bytes_per_elem.as_CFType(), v_bytes_per_elem.as_CFType()),
        (k_is_global.as_CFType(), v_is_global.as_CFType()),
    ];

    io_surface::new(&CFDictionary::from_CFType_pairs(pairs))
}

pub fn init_texture() -> GLuint {
    gl2::enable(TEXTURE_RECTANGLE_ARB);

    let texture = gl2::gen_textures(1)[0];
    gl2::bind_texture(TEXTURE_RECTANGLE_ARB, texture);
    gl2::tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_S, CLAMP_TO_EDGE as GLint);
    gl2::tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_WRAP_T, CLAMP_TO_EDGE as GLint);
    gl2::tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_MAG_FILTER, LINEAR as GLint);
    gl2::tex_parameter_i(TEXTURE_RECTANGLE_ARB, TEXTURE_MIN_FILTER, NEAREST as GLint);
    return texture;
}

// Assumes the texture is already bound via gl2::bind_texture().
pub fn bind_surface_to_texture(context: &GraphicsContext, surface: &IOSurface, size: Size2D<int>) {
    use core_foundation::base::TCFType;
    // FIXME: There should be safe wrappers for this.
    unsafe {
        let native = context.native();
        let gl_error = CGLTexImageIOSurface2D(*native,
                                              TEXTURE_RECTANGLE_ARB,
                                              RGBA as GLenum,
                                              size.width as GLsizei,
                                              size.height as GLsizei,
                                              BGRA as GLenum,
                                              UNSIGNED_INT_8_8_8_8_REV,
                                              cast::transmute(surface.as_concrete_TypeRef()),
                                              0);
        assert!(gl_error == kCGLNoError);
    }
}

pub fn bind_texture_to_framebuffer(texture: GLuint) {
    gl2::bind_texture(TEXTURE_RECTANGLE_ARB, 0);
    gl2::framebuffer_texture_2d(FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_RECTANGLE_ARB, texture, 0);
    assert!(gl2::check_framebuffer_status(FRAMEBUFFER) == FRAMEBUFFER_COMPLETE);
}

impl ShareContext for Context {
    fn new(size: Size2D<int>) -> Context {
        // Initialize CGL.
        let context = init_cgl();

        // Create the surface.
        let surface = init_surface(size.clone());

        // Create a framebuffer.
        let framebuffer = gl2::gen_framebuffers(1)[0];
        gl2::bind_framebuffer(FRAMEBUFFER, framebuffer);

        // Create and bind to the texture.
        let texture = init_texture();
        bind_surface_to_texture(&context, &surface, size);

        // Bind the texture to the framebuffer.
        bind_texture_to_framebuffer(texture);

        Context {
            surface: surface,
            framebuffer: framebuffer,
            texture: texture
        }
    }

    fn flush(&self) {
        gl2::finish();
    }

    fn id(&self) -> int {
        self.surface.get_id() as int
    }
}

<|endoftext|>


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

macro_rules! id {
    ($e:expr) => { $e }
}

fn main() {
    id!(x?);  //~ error: the `?` operator is not stable (see issue #31436)
    //~^ help: add #![feature(question_mark)] to the crate attributes to enable
    y?;  //~ error: the `?` operator is not stable (see issue #31436)
    //~^ help: add #![feature(question_mark)] to the crate attributes to enable
}
<commit_msg>Rollup merge of #32894 - brson:fixbeta, r=alexcrichton<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

macro_rules! id {
    ($e:expr) => { $e }
}

fn main() {
    id!(x?);  //~ error: the `?` operator is not stable (see issue #31436)
    y?;  //~ error: the `?` operator is not stable (see issue #31436)
}
<|endoftext|>


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

const i: int = 42; //~ ERROR expected item, found `const`
<commit_msg>tests: remove old compile-fail test asserting the removal of `const`.<commit_after><|endoftext|>


<commit_before>use syntax::ast;
use syntax::codemap;
use syntax::ext::base;
use syntax::parse::token;
use syntax::parse::parser::Parser;

use syntax::codemap::Pos;

use html::HtmlState;

/// Trait that means something can be parsed with a configuration.
pub trait Parse<Cfg> {
    /// Parse Self from a Parser and a configuration object.
    fn parse(&mut Parser, Cfg) -> Self;
}

static TEMPLATE:      &'static str = "template";

///
fn parse_start_template(state: &mut HtmlState, parser: &mut Parser) {

    match (
        parser.bump_and_get(),
        parser.parse_ident(),
        parser.parse_ident(),
        parser.parse_fn_decl(true),
        parser.bump_and_get(),
        parser.bump_and_get()
    ) {
        (
            token::BINOP(token::PERCENT),
            ident,
            functioname,
            function,
            token::BINOP(token::PERCENT),
            token::GT
        ) => { println!("found template beginning")},

        (one, two, three, four, five, six) => {
            parser.fatal(format!(
                "Expected `<% template xxx() %>`, found {}{}{}{}{}{}",
                one,
                two,
                three,
                four,
                five,
                six
            ).as_slice());
        }
    };
}

fn parse_end_template(state: &mut HtmlState, parser: &mut Parser) {
    match (
        parser.bump_and_get(),
        parser.parse_ident(),
        parser.parse_ident(),
        parser.bump_and_get(),
        parser.bump_and_get()
    ) {
        (
            token::BINOP(token::PERCENT),
            end,
            template,
            token::BINOP(token::PERCENT),
            token::GT
        ) => { println!("found end template")},

        (one, two, three, four, five) => {
            parser.fatal(format!(
                "Expected `<% end template %>`, found {}{}{}{}{}",
                one,
                two,
                three,
                four,
                five,
            ).as_slice());
        }
    };

}

fn is_template_tag_start (parser: &Parser) -> bool {

    if (parser.token != token::BINOP(token::PERCENT)) {
        return true;
    }

    match parser.last_token {
        None => return false,
        Some(ref last_token) => {
            return **last_token == token::LT
        }
    }

}

///
///
///
impl<'a, 'b> Parse<(
    codemap::Span,
    &'a mut base::ExtCtxt<'b>,
    Option<ast::Ident>
)> for HtmlState {

    ///
    ///
    ///
    fn parse(
        parser: &mut Parser,
        (_, _, name): (codemap::Span, &'a mut base::ExtCtxt, Option<ast::Ident>)
    ) -> HtmlState {

        let mut state = HtmlState::new(name);

        println!("parser");

        // try to find a <%
        while
            is_template_tag_start(parser) &&
            parser.token != token::EOF
        {
            parser.bump();
        }
        parse_start_template(&mut state, parser);
        //TODO handle token::LE (see how they've done for brain_fuck macro
        // try to find a <%
        while
            is_template_tag_start(parser) &&
            parser.token != token::EOF
        {
            parser.bump();
        }
        parse_end_template(&mut state, parser);
        state
    }
}
<commit_msg>now we look specifically for the ident template in the tag <% template ... %><commit_after>use syntax::ast;
use syntax::codemap;
use syntax::ext::base;
use syntax::parse::token;
use syntax::parse::parser::Parser;

use syntax::codemap::Pos;

use html::HtmlState;

/// Trait that means something can be parsed with a configuration.
pub trait Parse<Cfg> {
    /// Parse Self from a Parser and a configuration object.
    fn parse(&mut Parser, Cfg) -> Self;
}

static TEMPLATE:      &'static str = "template";
static END:           &'static str = "end";

///
fn parse_start_template(state: &mut HtmlState, parser: &mut Parser) {

    match (
        parser.bump_and_get(),
        parser.parse_ident().as_str(),
        parser.parse_ident(),
        parser.parse_fn_decl(true),
        parser.bump_and_get(),
        parser.bump_and_get()
    ) {
        (
            token::BINOP(token::PERCENT),
            block_name,
            functioname,
            ref function,
            token::BINOP(token::PERCENT),
            token::GT
        ) if block_name == TEMPLATE => { println!("found template beginning")},

        (one, two, three, four, five, six) => {
            parser.fatal(format!(
                "Expected `<% template xxx() %>`, found {}{}{}{}{}{}",
                one,
                two,
                three,
                four,
                five,
                six
            ).as_slice());
        }
    };
}

fn parse_end_template(state: &mut HtmlState, parser: &mut Parser) {
    match (
        parser.bump_and_get(),
        parser.parse_ident().as_str(),
        parser.parse_ident().as_str(),
        parser.bump_and_get(),
        parser.bump_and_get()
    ) {
        (
            token::BINOP(token::PERCENT),
            end,
            template,
            token::BINOP(token::PERCENT),
            token::GT
        ) if end == END && template == TEMPLATE => { println!("found end template")},

        (one, two, three, four, five) => {
            parser.fatal(format!(
                "Expected `<% end template %>`, found <{} {} {} {}{}",
                Parser::token_to_string(&one),
                two,
                three,
                Parser::token_to_string(&four),
                Parser::token_to_string(&five),
            ).as_slice());
        }
    };

}

fn is_template_tag_start (parser: &Parser) -> bool {

    if (parser.token != token::BINOP(token::PERCENT)) {
        return true;
    }

    match parser.last_token {
        None => return false,
        Some(ref last_token) => {
            return **last_token == token::LT
        }
    }

}

///
///
///
impl<'a, 'b> Parse<(
    codemap::Span,
    &'a mut base::ExtCtxt<'b>,
    Option<ast::Ident>
)> for HtmlState {

    ///
    ///
    ///
    fn parse(
        parser: &mut Parser,
        (_, _, name): (codemap::Span, &'a mut base::ExtCtxt, Option<ast::Ident>)
    ) -> HtmlState {

        let mut state = HtmlState::new(name);

        println!("parser");

        // try to find a <%
        while
            is_template_tag_start(parser) &&
            parser.token != token::EOF
        {
            parser.bump();
        }
        parse_start_template(&mut state, parser);
        //TODO handle token::LE (see how they've done for brain_fuck macro
        // try to find a <%
        while
            is_template_tag_start(parser) &&
            parser.token != token::EOF
        {
            parser.bump();
        }
        parse_end_template(&mut state, parser);
        state
    }
}
<|endoftext|>


<commit_before>use crate::text_utils::process_highlights;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct SessionPromptInfo {
    pub hp: i16,
    pub mp: i16,
}

#[derive(Debug, PartialEq)]
pub enum SessionOutput {
    None,
    Str(&'static str),
    String(String),
    JSON(serde_json::Value),
    Prompt(SessionPromptInfo),
    Aggregate(Vec<SessionOutput>),
}

impl SessionOutput {
    pub fn combine(mut outputs: Vec<Self>) -> Self {
        if outputs.len() == 0 {
            Self::None
        } else if outputs.len() == 1 {
            outputs.remove(0)
        } else if outputs.len() == 2 {
            if outputs[0] == Self::None {
                outputs.remove(1)
            } else if outputs[1] == Self::None {
                outputs.remove(0)
            } else {
                Self::Aggregate(outputs)
            }
        } else {
            let mut filtered_outputs = outputs
                .into_iter()
                .filter(|output| *output != Self::None)
                .collect::<Vec<Self>>();

            if filtered_outputs.len() == 0 {
                Self::None
            } else if filtered_outputs.len() == 1 {
                filtered_outputs.remove(0)
            } else {
                Self::Aggregate(filtered_outputs)
            }
        }
    }

    pub fn process_highlights(self) -> Self {
        match self {
            Self::Str(string) => Self::String(process_highlights(string)),
            Self::String(string) => Self::String(process_highlights(&string)),
            Self::Aggregate(outputs) => Self::Aggregate(
                outputs
                    .into_iter()
                    .map(|output| output.process_highlights())
                    .collect(),
            ),
            other => other,
        }
    }

    pub fn with(self, other: Self) -> Self {
        if self == Self::None {
            other
        } else if other == Self::None {
            self
        } else {
            // FIXME: Prevent nested aggregates where possible
            Self::Aggregate(vec![self, other])
        }
    }
}
<commit_msg>Avoid unnecessary aggregates<commit_after>use crate::text_utils::process_highlights;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct SessionPromptInfo {
    pub hp: i16,
    pub mp: i16,
}

#[derive(Debug, PartialEq)]
pub enum SessionOutput {
    None,
    Str(&'static str),
    String(String),
    JSON(serde_json::Value),
    Prompt(SessionPromptInfo),
    Aggregate(Vec<SessionOutput>),
}

impl SessionOutput {
    pub fn combine(mut outputs: Vec<Self>) -> Self {
        if outputs.len() == 0 {
            Self::None
        } else if outputs.len() == 1 {
            outputs.remove(0)
        } else if outputs.len() == 2 {
            if outputs[0] == Self::None {
                outputs.remove(1)
            } else if outputs[1] == Self::None {
                outputs.remove(0)
            } else {
                Self::Aggregate(outputs)
            }
        } else {
            let mut filtered_outputs = outputs
                .into_iter()
                .filter(|output| *output != Self::None)
                .collect::<Vec<Self>>();

            if filtered_outputs.len() == 0 {
                Self::None
            } else if filtered_outputs.len() == 1 {
                filtered_outputs.remove(0)
            } else {
                Self::Aggregate(filtered_outputs)
            }
        }
    }

    pub fn process_highlights(self) -> Self {
        match self {
            Self::Str(string) => Self::String(process_highlights(string)),
            Self::String(string) => Self::String(process_highlights(&string)),
            Self::Aggregate(outputs) => Self::Aggregate(
                outputs
                    .into_iter()
                    .map(|output| output.process_highlights())
                    .collect(),
            ),
            other => other,
        }
    }

    pub fn with(self, other: Self) -> Self {
        if self == Self::None {
            other
        } else if other == Self::None {
            self
        } else if let Self::Aggregate(mut outputs) = self {
            if let Self::Aggregate(others) = other {
                for other in others.into_iter() {
                    outputs.push(other);
                }
            } else {
                outputs.push(other);
            }
            Self::Aggregate(outputs)
        } else if let Self::Aggregate(others) = other {
            let mut outputs = vec![self];
            for other in others.into_iter() {
                outputs.push(other);
            }
            Self::Aggregate(outputs)
        } else {
            Self::Aggregate(vec![self, other])
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::from_str::FromStr;

use super::rfc5322::Rfc5322Parser;
use super::header::FromHeader;

/// Represents an RFC 5322 Address
#[deriving(PartialEq, Eq)]
pub enum Address {
    /// A "regular" email address
    AddressMailbox(Mailbox),
    /// A named group of mailboxes
    AddressGroup(String, Vec<Mailbox>),
}

impl Address {
    /// Shortcut function to make a new Mailbox with the given address
    pub fn mailbox(address: String) -> Address {
        AddressMailbox(Mailbox::new(address))
    }

    /// Shortcut function to make a new Mailbox with the address and given-name
    pub fn mailbox_with_name(name: String, address: String) -> Address {
        AddressMailbox(Mailbox::new_with_name(name, address))
    }

    pub fn group(name: String, mailboxes: Vec<Mailbox>) -> Address {
        AddressGroup(name, mailboxes)
    }
}

impl fmt::Show for Address {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            AddressMailbox(ref mbox) => mbox.fmt(fmt),
            AddressGroup(ref name, ref mboxes) => {
                let mut mailbox_list = String::new();
                for mbox in mboxes.iter() {
                    if mailbox_list.len() > 0 {
                        // Insert the separator if there's already things in this list
                        mailbox_list.push_str(", ");
                    }
                    mailbox_list.push_str(mbox.to_string().as_slice());
                }
                write!(fmt, "{}: {}", name, mailbox_list)
            }
        }
    }
}

/// Represents an RFC 5322 mailbox
#[deriving(PartialEq, Eq)]
pub struct Mailbox {
    /// The given name for this address
    pub name: Option<String>,
    /// The mailbox address
    pub address: String,
}

impl Mailbox {
    /// Create a new Mailbox without a display name
    pub fn new(address: String) -> Mailbox {
        Mailbox {
            name: None,
            address: address
        }
    }

    /// Create a new Mailbox with a display name
    pub fn new_with_name(name: String, address: String) -> Mailbox {
        Mailbox {
            name: Some(name),
            address: address
        }
    }
}

impl fmt::Show for Mailbox {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.name {
            Some(ref name) => write!(fmt, "\"{}\" <{}>", name, self.address),
            None => write!(fmt, "<{}>", self.address),
        }
    }
}

impl FromStr for Mailbox {
    fn from_str(s: &str) -> Option<Mailbox> {
        AddressParser::new(s).parse_mailbox()
    }
}

impl FromHeader for Vec<Address> {
    fn from_header(value: String) -> Option<Vec<Address>> {
        Some(AddressParser::new(value.as_slice()).parse_address_list())
    }
}

pub struct AddressParser<'s> {
    p: Rfc5322Parser<'s>,
}

impl<'s> AddressParser<'s> {
    pub fn new(s: &str) -> AddressParser {
        AddressParser {
            p: Rfc5322Parser::new(s)
        }
    }

    pub fn parse_address_list(&mut self) -> Vec<Address> {
        let mut result = Vec::new();

        while !self.p.eof() {
            match self.parse_mailbox() {
                Some(mailbox) => result.push(AddressMailbox(mailbox)),
                None => {},
            }

            self.p.consume_linear_whitespace();
            if !self.p.eof() && self.p.peek() == ',' {
                // Clear the separator
                self.p.consume_char();
            }
        }

        result
    }

    pub fn parse_mailbox(&mut self) -> Option<Mailbox> {
        // Push the current position of the parser so we can back out later
        self.p.push_position();
        let mut result = self.parse_name_addr();
        if result.is_none() {
            // Revert back to our original position to try to parse an addr-spec
            self.p.pop_position();

            let addr_spec = self.parse_addr_spec();
            if addr_spec.is_some() {
                result = Some(Mailbox::new(addr_spec.unwrap()));
            }
        }

        result
    }

    fn parse_name_addr(&mut self) -> Option<Mailbox> {
        // Find display-name
        let display_name = self.p.consume_phrase(false);
        self.p.consume_linear_whitespace();
        // Find angle-addr
        if !self.p.eof() && self.p.peek() == '<' {
            self.p.consume_char();
            let addr = self.parse_addr_spec();
            if self.p.consume_char() != '>' {
                // Fail because we should have a closing RANGLE here (to match the opening one)
                None
            } else {
                match (display_name, addr) {
                    (Some(name), Some(addr)) => Some(Mailbox::new_with_name(name, addr)),
                    (None, Some(addr)) => Some(Mailbox::new(addr)),
                    (_, _) => None,
                }
            }
        } else {
            None
        }
    }

    fn parse_addr_spec(&mut self) -> Option<String> {
        // local-part is a phrase, but allows dots in atoms
        let local_part = self.p.consume_phrase(true);
        if self.p.eof() || self.p.consume_char() != '@' {
            None
        } else {
            let domain = self.parse_domain();
            if local_part.is_some() && domain.is_some() {
                Some(format!("{}@{}", local_part.unwrap(), domain.unwrap()))
            } else {
                None
            }
        }
    }

    fn parse_domain(&mut self) -> Option<String> {
        // TODO: support domain-literal
        self.p.consume_atom(true)
    }
}

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

    use super::super::header::Header;

    #[test]
    fn test_address_to_string() {
        let addr = Mailbox::new("foo@example.org".to_string());
        assert_eq!(addr.to_string(), "<foo@example.org>".to_string());

        let name_addr = Mailbox::new_with_name("Joe Blogs".to_string(), "foo@example.org".to_string());
        assert_eq!(name_addr.to_string(), "\"Joe Blogs\" <foo@example.org>".to_string());
    }

    #[test]
    fn test_address_from_string() {
        let addr = from_str::<Mailbox>("\"Joe Blogs\" <joe@example.org>").unwrap();
        assert_eq!(addr.name.unwrap(), "Joe Blogs".to_string());
        assert_eq!(addr.address, "joe@example.org".to_string());

        assert!(from_str::<Mailbox>("Not an address").is_none());
    }

    #[test]
    fn test_address_parsing() {
        let mut parser = AddressParser::new("\"Joe Blogs\" <joe@example.org>");
        let mut addr = parser.parse_mailbox().unwrap();
        assert_eq!(addr.name.unwrap(), "Joe Blogs".to_string());
        assert_eq!(addr.address, "joe@example.org".to_string());

        parser = AddressParser::new("joe@example.org");
        addr = parser.parse_mailbox().unwrap();
        assert_eq!(addr.name, None);
        assert_eq!(addr.address, "joe@example.org".to_string());
    }

    #[test]
    fn test_address_list_parsing() {
        let mut parser = AddressParser::new("\"Joe Blogs\" <joe@example.org>, \"John Doe\" <john@example.org>");
        assert_eq!(parser.parse_address_list(), vec![
            Address::mailbox_with_name("Joe Blogs".to_string(), "joe@example.org".to_string()),
            Address::mailbox_with_name("John Doe".to_string(), "john@example.org".to_string()),
        ]);
    }

    #[test]
    fn test_from_header_parsing() {
        let header = Header::new(
            "From:".to_string(),
            "\"Joe Blogs\" <joe@example.org>, \"John Doe\" <john@example.org>".to_string());
        let addresses: Vec<Address> = header.get_value().unwrap();
        assert_eq!(addresses, vec![
            Address::mailbox_with_name("Joe Blogs".to_string(), "joe@example.org".to_string()),
            Address::mailbox_with_name("John Doe".to_string(), "john@example.org".to_string()),
        ]);
    }

    #[test]
    fn test_address_group_to_string() {
        let addr = Address::group("undisclosed recipients".to_string(), vec![]);
        assert_eq!(addr.to_string(), "undisclosed recipients: ".to_string());

        let addr = Address::group("group test".to_string(), vec![
            Mailbox::new("joe@example.org".to_string()),
            Mailbox::new_with_name("John Doe".to_string(), "john@example.org".to_string()),
        ]);
        assert_eq!(addr.to_string(), "group test: <joe@example.org>, \"John Doe\" <john@example.org>".to_string());
    }
}
<commit_msg>Support parsing of group addresses.<commit_after>use std::fmt;
use std::from_str::FromStr;

use super::rfc5322::Rfc5322Parser;
use super::header::FromHeader;

/// Represents an RFC 5322 Address
#[deriving(PartialEq, Eq)]
pub enum Address {
    /// A "regular" email address
    AddressMailbox(Mailbox),
    /// A named group of mailboxes
    AddressGroup(String, Vec<Mailbox>),
}

impl Address {
    /// Shortcut function to make a new Mailbox with the given address
    pub fn mailbox(address: String) -> Address {
        AddressMailbox(Mailbox::new(address))
    }

    /// Shortcut function to make a new Mailbox with the address and given-name
    pub fn mailbox_with_name(name: String, address: String) -> Address {
        AddressMailbox(Mailbox::new_with_name(name, address))
    }

    pub fn group(name: String, mailboxes: Vec<Mailbox>) -> Address {
        AddressGroup(name, mailboxes)
    }
}

impl fmt::Show for Address {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            AddressMailbox(ref mbox) => mbox.fmt(fmt),
            AddressGroup(ref name, ref mboxes) => {
                let mut mailbox_list = String::new();
                for mbox in mboxes.iter() {
                    if mailbox_list.len() > 0 {
                        // Insert the separator if there's already things in this list
                        mailbox_list.push_str(", ");
                    }
                    mailbox_list.push_str(mbox.to_string().as_slice());
                }
                write!(fmt, "{}: {}", name, mailbox_list)
            }
        }
    }
}

/// Represents an RFC 5322 mailbox
#[deriving(PartialEq, Eq)]
pub struct Mailbox {
    /// The given name for this address
    pub name: Option<String>,
    /// The mailbox address
    pub address: String,
}

impl Mailbox {
    /// Create a new Mailbox without a display name
    pub fn new(address: String) -> Mailbox {
        Mailbox {
            name: None,
            address: address
        }
    }

    /// Create a new Mailbox with a display name
    pub fn new_with_name(name: String, address: String) -> Mailbox {
        Mailbox {
            name: Some(name),
            address: address
        }
    }
}

impl fmt::Show for Mailbox {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self.name {
            Some(ref name) => write!(fmt, "\"{}\" <{}>", name, self.address),
            None => write!(fmt, "<{}>", self.address),
        }
    }
}

impl FromStr for Mailbox {
    fn from_str(s: &str) -> Option<Mailbox> {
        AddressParser::new(s).parse_mailbox()
    }
}

impl FromHeader for Vec<Address> {
    fn from_header(value: String) -> Option<Vec<Address>> {
        Some(AddressParser::new(value.as_slice()).parse_address_list())
    }
}

pub struct AddressParser<'s> {
    p: Rfc5322Parser<'s>,
}

impl<'s> AddressParser<'s> {
    pub fn new(s: &str) -> AddressParser {
        AddressParser {
            p: Rfc5322Parser::new(s)
        }
    }

    pub fn parse_address_list(&mut self) -> Vec<Address> {
        let mut result = Vec::new();

        while !self.p.eof() {
            self.p.push_position();

            let mut entry = self.parse_group();

            if entry.is_none() {
                // If we failed to parse as group, try again as mailbox
                self.p.pop_position();

                entry = match self.parse_mailbox() {
                    Some(mailbox) => Some(AddressMailbox(mailbox)),
                    None => None,
                }
            }

            if entry.is_some() {
                result.push(entry.unwrap());
            }

            self.p.consume_linear_whitespace();
            if !self.p.eof() && self.p.peek() == ',' {
                // Clear the separator
                self.p.consume_char();
            }
        }

        result
    }

    pub fn parse_group(&mut self) -> Option<Address> {
        let mut mailboxes = Vec::new();
        let name = self.p.consume_phrase(false);

        if name.is_some() {
            if !self.p.eof() && self.p.peek() != ':' {
                None
            } else {
                self.p.consume_char();
                while !self.p.eof() && self.p.peek() != ';' {
                    match self.parse_mailbox() {
                        Some(mbox) => mailboxes.push(mbox),
                        None => {},
                    }

                    if !self.p.eof() && self.p.peek() == ',' {
                        self.p.consume_char();
                    }
                }

                Some(AddressGroup(name.unwrap(), mailboxes))
            }
        } else {
            None
        }
    }

    pub fn parse_mailbox(&mut self) -> Option<Mailbox> {
        // Push the current position of the parser so we can back out later
        self.p.push_position();
        let mut result = self.parse_name_addr();
        if result.is_none() {
            // Revert back to our original position to try to parse an addr-spec
            self.p.pop_position();

            let addr_spec = self.parse_addr_spec();
            if addr_spec.is_some() {
                result = Some(Mailbox::new(addr_spec.unwrap()));
            }
        }

        result
    }

    fn parse_name_addr(&mut self) -> Option<Mailbox> {
        // Find display-name
        let display_name = self.p.consume_phrase(false);
        self.p.consume_linear_whitespace();
        // Find angle-addr
        if !self.p.eof() && self.p.peek() == '<' {
            self.p.consume_char();
            let addr = self.parse_addr_spec();
            if self.p.consume_char() != '>' {
                // Fail because we should have a closing RANGLE here (to match the opening one)
                None
            } else {
                match (display_name, addr) {
                    (Some(name), Some(addr)) => Some(Mailbox::new_with_name(name, addr)),
                    (None, Some(addr)) => Some(Mailbox::new(addr)),
                    (_, _) => None,
                }
            }
        } else {
            None
        }
    }

    fn parse_addr_spec(&mut self) -> Option<String> {
        // local-part is a phrase, but allows dots in atoms
        let local_part = self.p.consume_phrase(true);
        if self.p.eof() || self.p.consume_char() != '@' {
            None
        } else {
            let domain = self.parse_domain();
            if local_part.is_some() && domain.is_some() {
                Some(format!("{}@{}", local_part.unwrap(), domain.unwrap()))
            } else {
                None
            }
        }
    }

    fn parse_domain(&mut self) -> Option<String> {
        // TODO: support domain-literal
        self.p.consume_atom(true)
    }
}

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

    use super::super::header::Header;

    #[test]
    fn test_address_to_string() {
        let addr = Mailbox::new("foo@example.org".to_string());
        assert_eq!(addr.to_string(), "<foo@example.org>".to_string());

        let name_addr = Mailbox::new_with_name("Joe Blogs".to_string(), "foo@example.org".to_string());
        assert_eq!(name_addr.to_string(), "\"Joe Blogs\" <foo@example.org>".to_string());
    }

    #[test]
    fn test_address_from_string() {
        let addr = from_str::<Mailbox>("\"Joe Blogs\" <joe@example.org>").unwrap();
        assert_eq!(addr.name.unwrap(), "Joe Blogs".to_string());
        assert_eq!(addr.address, "joe@example.org".to_string());

        assert!(from_str::<Mailbox>("Not an address").is_none());
    }

    #[test]
    fn test_address_parsing() {
        let mut parser = AddressParser::new("\"Joe Blogs\" <joe@example.org>");
        let mut addr = parser.parse_mailbox().unwrap();
        assert_eq!(addr.name.unwrap(), "Joe Blogs".to_string());
        assert_eq!(addr.address, "joe@example.org".to_string());

        parser = AddressParser::new("joe@example.org");
        addr = parser.parse_mailbox().unwrap();
        assert_eq!(addr.name, None);
        assert_eq!(addr.address, "joe@example.org".to_string());
    }

    #[test]
    fn test_address_group_to_string() {
        let addr = Address::group("undisclosed recipients".to_string(), vec![]);
        assert_eq!(addr.to_string(), "undisclosed recipients: ".to_string());

        let addr = Address::group("group test".to_string(), vec![
            Mailbox::new("joe@example.org".to_string()),
            Mailbox::new_with_name("John Doe".to_string(), "john@example.org".to_string()),
        ]);
        assert_eq!(addr.to_string(), "group test: <joe@example.org>, \"John Doe\" <john@example.org>".to_string());
    }

    #[test]
    fn test_address_group_parsing() {
        let mut parser = AddressParser::new("A Group:\"Joe Blogs\" <joe@example.org>,john@example.org;");
        let addr = parser.parse_group().unwrap();
        match addr {
            AddressGroup(name, mboxes) => {
                assert_eq!(name, "A Group".to_string());
                assert_eq!(mboxes, vec![
                    Mailbox::new_with_name("Joe Blogs".to_string(), "joe@example.org".to_string()),
                    Mailbox::new("john@example.org".to_string()),
                ]);
            },
            _ => assert!(false),
        }
    }

    #[test]
    fn test_address_list_parsing() {
        let mut parser = AddressParser::new("\"Joe Blogs\" <joe@example.org>, \"John Doe\" <john@example.org>");
        assert_eq!(parser.parse_address_list(), vec![
            Address::mailbox_with_name("Joe Blogs".to_string(), "joe@example.org".to_string()),
            Address::mailbox_with_name("John Doe".to_string(), "john@example.org".to_string()),
        ]);

        let mut parser = AddressParser::new("A Group:\"Joe Blogs\" <joe@example.org>, \"John Doe\" <john@example.org>; <third@example.org>, <fourth@example.org>");
        assert_eq!(parser.parse_address_list(), vec![
            Address::group("A Group".to_string(), vec![
                    Mailbox::new_with_name("Joe Blogs".to_string(), "joe@example.org".to_string()),
                    Mailbox::new_with_name("John Doe".to_string(), "john@example.org".to_string()),
            ]),
            Address::mailbox("third@example.org".to_string()),
            Address::mailbox("fourth@example.org".to_string()),
        ]);
    }

    #[test]
    fn test_from_header_parsing() {
        let header = Header::new(
            "From:".to_string(),
            "\"Joe Blogs\" <joe@example.org>, \"John Doe\" <john@example.org>".to_string());
        let addresses: Vec<Address> = header.get_value().unwrap();
        assert_eq!(addresses, vec![
            Address::mailbox_with_name("Joe Blogs".to_string(), "joe@example.org".to_string()),
            Address::mailbox_with_name("John Doe".to_string(), "john@example.org".to_string()),
        ]);
    }

}
<|endoftext|>


<commit_before>extern crate primus_polygoni;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate image;
extern crate time;

use std::env;
use std::f32::consts::PI;
use primus_polygoni::rand;
use primus_polygoni::rand::distributions::{IndependentSample, Range};
use primus_polygoni::gfx;
use primus_polygoni::nalgebra::{self, Vector2, Vector3, UnitQuaternion};
use time::precise_time_s;

use primus_polygoni::{Vertex, Instance, Locals, Camera, ColorFormat, DepthFormat};
use gfx::traits::FactoryExt;
use gfx::{Factory, Device};

fn fill_instances<R, C>(sphere_count: usize,
                        scene_radius: f32,
                        encoder: &mut gfx::Encoder<R, C>,
                        instances: &gfx::handle::Buffer<R, Instance>)
    where R: gfx::Resources, C: gfx::CommandBuffer<R>
{
    let mut vec = Vec::with_capacity(sphere_count);
    let mut rng = rand::thread_rng();

    for i in 0..sphere_count {
        let angle = i as f32 / sphere_count as f32 * (2.0 * PI);
        let position = Vector3::new(
            angle.cos() * scene_radius,
            0.0,
            angle.sin() * scene_radius);

        let radius = Range::new(0.5, 1.5).ind_sample(&mut rng);
        let remaining = 2.0 - radius;

        let range = Range::new(-remaining, remaining);
        let displacement = Vector3::new(
            range.ind_sample(&mut rng),
            range.ind_sample(&mut rng),
            range.ind_sample(&mut rng),
        );

        let transform = nalgebra::Similarity3::from_parts(
            nalgebra::Translation3::from_vector(position + displacement),
            nalgebra::one(),
            radius).to_homogeneous();
        let transform = transform.as_slice();

        let line = |l: &[f32]| [l[0], l[1], l[2], l[3]];

        vec.push(Instance {
            t1: line(&transform[0..4]),
            t2: line(&transform[4..8]),
            t3: line(&transform[8..12]),
            t4: line(&transform[12..16]),
        });
    }
    encoder.update_buffer(instances, &vec[..], 0).unwrap();
}

fn main() {
    let mut args = env::args().skip(1);

    let sphere_count: usize = args.next()
        .map(|s| s.parse().expect("expected number of spheres")).unwrap_or(64);
    let scene_radius: f32 = (sphere_count as f32 * 4.0) / (2.0 * PI);

    let texture_size: usize = args.next()
        .map(|s| s.parse().expect("expected texture size")).unwrap_or(256);

    let gl_version = glutin::GlRequest::GlThenGles {
        opengl_version: (3, 2),
        opengles_version: (2, 0)
    };
    let wb = glutin::WindowBuilder::new()
        .with_gl(gl_version)
        .with_title("Primus Polygoni");
    let (window, mut device, mut factory, main_color, main_depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(wb);
    let (width, height) = window.get_inner_size_points().unwrap();
    let mut aspect_ratio = width as f32 / height as f32;

    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
    let pso = primus_polygoni::create_pipeline(&mut factory);

    let (vertex_data, index_data) = primus_polygoni::generate_icosphere(4);
    let (vertices, mut slice) = factory
        .create_vertex_buffer_with_slice(&vertex_data[..], &index_data[..]);
    slice.instances = Some((sphere_count as u32, 0));

    let instances = factory.create_buffer(sphere_count,
                                          gfx::buffer::Role::Vertex,
                                          gfx::memory::Usage::Dynamic,
                                          gfx::Bind::empty()).unwrap();
    fill_instances(sphere_count, scene_radius, &mut encoder, &instances);

    let (w, h) = (texture_size * 2, texture_size);
    let mut texels: Vec<_> = (0..(w * h * sphere_count)).map(|_| [0; 4]).collect();
    let mut textures = Vec::with_capacity(sphere_count);

    for s in texels.chunks_mut(w *h) {
        primus_polygoni::generate_texture(s, texture_size);
        textures.push(s as &[_]);
    }

    let (_, texture_view) =
        factory.create_texture_immutable::<gfx::format::Rgba8>(
            gfx::texture::Kind::D2Array(w as gfx::texture::Size,
                                        h as gfx::texture::Size,
                                        sphere_count as gfx::texture::Size,
                                        gfx::texture::AaMode::Single),
            &textures[..]
        ).expect("could not create texture");

    let sinfo = gfx::texture::SamplerInfo::new(
        gfx::texture::FilterMethod::Bilinear,
        gfx::texture::WrapMode::Clamp);

    let mut data = primus_polygoni::pipe::Data {
        vertices: vertices,
        instances: instances,
        locals: factory.create_constant_buffer(1),
        color: (texture_view, factory.create_sampler(sinfo)),
        color_target: main_color,
        depth_target: main_depth,
    };

    let mut camera = Camera::new(scene_radius);

    let mut mouse = Vector2::new(0., 0.);
    let mut head_spinning = false;
    let mut going_left = false;
    let mut going_right = false;

    let mut marker = precise_time_s() as f32;
    let mut fps_counter = primus_polygoni::FpsCounter::new(1.0);
    'main: loop {
        for event in window.poll_events() {
            use glutin::Event::*;
            use glutin::ElementState::*;
            use glutin::MouseButton::*;
            match event {
                Closed => break 'main,
                Resized(w, h) => {
                    aspect_ratio = w as f32 / h as f32;
                    gfx_window_glutin::update_views(
                        &window, &mut data.color_target, &mut data.depth_target);
                }
                KeyboardInput(state, _, Some(key)) => {
                    use glutin::VirtualKeyCode::*;
                    match key {
                        Q | Left => going_left = state == Pressed,
                        D | Right => going_right = state == Pressed,
                        _ => {}
                    }
                },
                MouseMoved(x, y) => {
                    let (w, h, _, _) = data.color_target.get_dimensions();
                    mouse = Vector2::new((x as f32 / w as f32) - 0.5,
                                         0.5 - (y as f32 / h as f32));
                }
                MouseInput(state, Left) => head_spinning = state == Pressed,
                _ => {}
            }
        }

        let now = precise_time_s() as f32;
        let delta = now - marker;
        fps_counter.update(delta).map(|fps| println!("{} fps", fps));
        marker = now;

        if head_spinning {
            let max_rotation = 2.0 * PI * delta;
            camera.rotate(UnitQuaternion::new(
                Vector3::y() * (-mouse.x * max_rotation)
            ));
            camera.pitch(mouse.y * max_rotation);
        }

        let speed = 0.5 * PI;
        if going_left { camera.move_left(speed * delta); }
        if going_right { camera.move_right(speed * delta); }

        camera.update(aspect_ratio);
        encoder.update_constant_buffer(&data.locals, &Locals {
            transform: camera.gpu_transform()
        });

        encoder.clear(&data.color_target, [0.1, 0.2, 0.3, 1.0]);
        encoder.clear_depth(&data.depth_target, 1.0);
        encoder.draw(&slice, &pso, &data);
        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<commit_msg>dynamic texture generation<commit_after>extern crate primus_polygoni;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate image;
extern crate time;

use std::env;
use std::f32::consts::PI;
use primus_polygoni::rand;
use primus_polygoni::rand::distributions::{IndependentSample, Range};
use primus_polygoni::gfx;
use primus_polygoni::nalgebra::{self, Vector2, Vector3, UnitQuaternion};
use time::precise_time_s;

use primus_polygoni::{Vertex, Instance, Locals, Camera, ColorFormat, DepthFormat};
use gfx::traits::FactoryExt;
use gfx::{Factory, Device};

fn fill_instances<R, C>(sphere_count: usize,
                        scene_radius: f32,
                        encoder: &mut gfx::Encoder<R, C>,
                        instances: &gfx::handle::Buffer<R, Instance>)
    where R: gfx::Resources, C: gfx::CommandBuffer<R>
{
    let mut vec = Vec::with_capacity(sphere_count);
    let mut rng = rand::thread_rng();

    for i in 0..sphere_count {
        let angle = i as f32 / sphere_count as f32 * (2.0 * PI);
        let position = Vector3::new(
            angle.cos() * scene_radius,
            0.0,
            angle.sin() * scene_radius);

        let radius = Range::new(0.5, 1.5).ind_sample(&mut rng);
        let remaining = 2.0 - radius;

        let range = Range::new(-remaining, remaining);
        let displacement = Vector3::new(
            range.ind_sample(&mut rng),
            range.ind_sample(&mut rng),
            range.ind_sample(&mut rng),
        );

        let transform = nalgebra::Similarity3::from_parts(
            nalgebra::Translation3::from_vector(position + displacement),
            nalgebra::one(),
            radius).to_homogeneous();
        let transform = transform.as_slice();

        let line = |l: &[f32]| [l[0], l[1], l[2], l[3]];

        vec.push(Instance {
            t1: line(&transform[0..4]),
            t2: line(&transform[4..8]),
            t3: line(&transform[8..12]),
            t4: line(&transform[12..16]),
        });
    }
    encoder.update_buffer(instances, &vec[..], 0).unwrap();
}

fn generate_textures<R, C>(sphere_count: usize,
                           texture_size: usize,
                           encoder: &mut gfx::Encoder<R, C>,
                           texture: &gfx::handle::Texture<R, gfx::format::R8_G8_B8_A8>)
    where R: gfx::Resources, C: gfx::CommandBuffer<R>
{
    println!("Generating textures");
    let (w, h) = (texture_size * 2, texture_size);
    let mut texels: Vec<_> = (0..(w * h)).map(|_| [0; 4]).collect();
    let mut info = gfx::texture::ImageInfoCommon {
        xoffset: 0,
        yoffset: 0,
        zoffset: 0,
        width: w as gfx::texture::Size,
        height: h as gfx::texture::Size,
        depth: 1,
        format: (),
        mipmap: 0
    };

    for i in 0..sphere_count {
        primus_polygoni::generate_texture(&mut texels[..], texture_size);
        info.zoffset = i as gfx::texture::Size;
        encoder.update_texture::<_, gfx::format::Rgba8>(texture, None, info, &texels[..])
            .unwrap();
    }
}

fn main() {
    let mut args = env::args().skip(1);

    let sphere_count: usize = args.next()
        .map(|s| s.parse().expect("expected number of spheres")).unwrap_or(64);
    let scene_radius: f32 = (sphere_count as f32 * 4.0) / (2.0 * PI);

    let texture_size: usize = args.next()
        .map(|s| s.parse().expect("expected texture size")).unwrap_or(256);

    let gl_version = glutin::GlRequest::GlThenGles {
        opengl_version: (3, 2),
        opengles_version: (2, 0)
    };
    let wb = glutin::WindowBuilder::new()
        .with_gl(gl_version)
        .with_title("Primus Polygoni");
    let (window, mut device, mut factory, main_color, main_depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(wb);
    let (width, height) = window.get_inner_size_points().unwrap();
    let mut aspect_ratio = width as f32 / height as f32;

    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
    let pso = primus_polygoni::create_pipeline(&mut factory);

    let (vertex_data, index_data) = primus_polygoni::generate_icosphere(4);
    let (vertices, mut slice) = factory
        .create_vertex_buffer_with_slice(&vertex_data[..], &index_data[..]);
    slice.instances = Some((sphere_count as u32, 0));

    let instances = factory.create_buffer(sphere_count,
                                          gfx::buffer::Role::Vertex,
                                          gfx::memory::Usage::Dynamic,
                                          gfx::Bind::empty()).unwrap();
    fill_instances(sphere_count, scene_radius, &mut encoder, &instances);

    let (w, h) = (texture_size * 2, texture_size);
    let texture =
        factory.create_texture(
            gfx::texture::Kind::D2Array(w as gfx::texture::Size,
                                        h as gfx::texture::Size,
                                        sphere_count as gfx::texture::Size,
                                        gfx::texture::AaMode::Single),
            1,
            gfx::memory::SHADER_RESOURCE,
            gfx::memory::Usage::Dynamic,
            Some(gfx::format::ChannelType::Unorm)
        ).expect("could not create texture");
    let texture_view = factory
        .view_texture_as_shader_resource::<gfx::format::Rgba8>(&texture, (0, 0), gfx::format::Swizzle::new())
        .expect("could not create texture view");

    let sinfo = gfx::texture::SamplerInfo::new(
        gfx::texture::FilterMethod::Bilinear,
        gfx::texture::WrapMode::Clamp);

    let mut data = primus_polygoni::pipe::Data {
        vertices: vertices,
        instances: instances,
        locals: factory.create_constant_buffer(1),
        color: (texture_view, factory.create_sampler(sinfo)),
        color_target: main_color,
        depth_target: main_depth,
    };

    let mut camera = Camera::new(scene_radius);

    let mut mouse = Vector2::new(0., 0.);
    let mut head_spinning = false;
    let mut going_left = false;
    let mut going_right = false;
    let mut toggled = false;
    let mut reset = true;

    let mut marker = precise_time_s() as f32;
    let mut fps_counter = primus_polygoni::FpsCounter::new(1.0);
    'main: loop {
        for event in window.poll_events() {
            use glutin::Event::*;
            use glutin::ElementState::*;
            use glutin::MouseButton::*;
            match event {
                Closed => break 'main,
                Resized(w, h) => {
                    aspect_ratio = w as f32 / h as f32;
                    gfx_window_glutin::update_views(
                        &window, &mut data.color_target, &mut data.depth_target);
                }
                KeyboardInput(state, _, Some(key)) => {
                    use glutin::VirtualKeyCode::*;
                    match key {
                        Q | Left => going_left = state == Pressed,
                        D | Right => going_right = state == Pressed,
                        T if state == Released => toggled = !toggled,
                        R if state == Released => reset = true,
                        _ => {}
                    }
                },
                MouseMoved(x, y) => {
                    let (w, h, _, _) = data.color_target.get_dimensions();
                    mouse = Vector2::new((x as f32 / w as f32) - 0.5,
                                         0.5 - (y as f32 / h as f32));
                }
                MouseInput(state, Left) => head_spinning = state == Pressed,
                _ => {}
            }
        }

        let now = precise_time_s() as f32;
        let delta = now - marker;
        fps_counter.update(delta).map(|fps| println!("{} fps", fps));
        marker = now;

        if head_spinning {
            let max_rotation = 2.0 * PI * delta;
            camera.rotate(UnitQuaternion::new(
                Vector3::y() * (-mouse.x * max_rotation)
            ));
            camera.pitch(mouse.y * max_rotation);
        }

        let speed = 0.5 * PI;
        if going_left { camera.move_left(speed * delta); }
        if going_right { camera.move_right(speed * delta); }
        if toggled { unimplemented!() }
        if reset {
            generate_textures(sphere_count, texture_size, &mut encoder, &texture);
            reset = false;
        }

        camera.update(aspect_ratio);
        encoder.update_constant_buffer(&data.locals, &Locals {
            transform: camera.gpu_transform()
        });

        encoder.clear(&data.color_target, [0.1, 0.2, 0.3, 1.0]);
        encoder.clear_depth(&data.depth_target, 1.0);
        encoder.draw(&slice, &pso, &data);
        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<|endoftext|>