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

/*!
MCU initialication and clock configuration.

This module includes code for setting up the clock, flash, access time and
performing initial peripheral configuration.
*/

use hal::mem_init::init_data;
use hal::stack;

#[path="../../lib/ioreg.rs"] mod ioreg;
#[path="../../lib/wait_for.rs"] mod wait_for;

extern {
  static _eglobals: u32;
}

/// PLL clock source.
pub enum ClockSource {
  /// Internal resonator, 4MHz.
  Internal,
  /// External crystal with configurable frequency.
  Main(u32),
  /// Internal RTC resonator, 32KHz.
  RTC,
}

/// PLL0 configuration options.
///
/// Frequency is calculated as
///
/// ```
/// Fcco = (2 * m * Fin) / n
/// Fcpu = Fcco / divisor
/// ```
pub struct PLL0 {
  /// Specifies if PLL0 should be connected on boot.
  pub enabled: bool,
  /// PLL multiplier.
  pub m: u8,
  /// PLL divisor.
  pub n: u8,
  /// PLL output divisor.
  pub divisor: u8,
}

/// MCU clock configuration.
pub struct Clock {
  /// Clocking source.
  pub source: ClockSource,
  /// PLL configuration.
  pub pll: PLL0,
}

/// MCU configuration.
pub struct SysConf {
  /// Clock configuration.
  pub clock: Clock,
}

// TODO(farcaller): move to peripheral_clock?
static mut SystemClock: u32 = 0;

/// Returns system clock frequency according to configuration.
#[inline(always)]
pub fn system_clock() -> u32 {
  unsafe { SystemClock }
}

/// Performs the MCU initialization.
impl SysConf {
  pub fn setup(&self) {
    init_stack();
    init_data();
    init_clock(&self.clock);
  }
}

#[inline(always)]
fn init_stack() {
  stack::set_stack_limit((&_eglobals as *u32) as u32);
}

#[inline(always)]
fn init_clock(clock: &Clock) {
  let src_clock: u32 = match clock.source {
    Internal =>   4_000_000,
    Main(freq) => freq,
    RTC =>        32_000,
  };
  let dst_clock: u32;

  if clock.pll.enabled {
    match clock.source {
      Main(freq) => init_main_oscillator(freq),
      _ => (),
    }
    dst_clock = (src_clock * clock.pll.m as u32 * 2) / clock.pll.n as u32 / clock.pll.divisor as u32;
    init_flash_access(dst_clock);
    init_pll(&clock.pll, clock.source);
  } else {
    dst_clock = src_clock;
  }

  unsafe { SystemClock = dst_clock };
}

#[inline(always)]
fn init_main_oscillator(freq: u32) {
  let val: u32 = if freq > 15_000_000 { 1 << 4 } else { 0 } |
                 (1 << 5);

  reg::SCS.set_value(val);

  wait_for!(reg::SCS.value() & (1 << 6) == (1 << 6));
}

#[inline(always)]
fn init_flash_access(freq: u32) {
  let num_clocks: u32 = if freq > 100_000_000 { 6 } else
                        if freq > 80_000_000 { 5 } else
                        if freq > 60_000_000 { 4 } else
                        if freq > 40_000_000 { 3 } else
                        if freq > 40_000_000 { 2 } else
                        { 1 };
  let val = (num_clocks - 1) << 12;
  reg::FLASHCFG.set_value(val);
}

#[inline(always)]
fn wait_for_pll0stat_bit(bit: u32) {
  wait_for!(reg::PLL0STAT.value() & (1 << bit) == (1 << bit));
}

#[inline(always)]
fn write_pll0_changes() {
  reg::PLL0FEED.set_value(0xaa);
  reg::PLL0FEED.set_value(0x55);
}

#[inline(always)]
fn init_pll(pll: &PLL0, source: ClockSource) {
  match source {
    Internal => reg::CLKSRCSEL.set_value(0),
    Main(_)  => reg::CLKSRCSEL.set_value(1),
    RTC =>      reg::CLKSRCSEL.set_value(2),
  }

  let val: u32 = ((pll.n as u32 - 1) << 16) | ((pll.m as u32 - 1) << 0);
  reg::PLL0CFG.set_value(val);
  write_pll0_changes();
  reg::PLL0CON.set_value(1);
  write_pll0_changes();
  wait_for_pll0stat_bit(24);
  reg::CCLKCFG.set_value((pll.divisor - 1) as u32);
  wait_for_pll0stat_bit(26);
  reg::PLL0CON.set_value(3);
  write_pll0_changes();
  wait_for_pll0stat_bit(25);
}

mod reg {
  use lib::volatile_cell::VolatileCell;

  ioreg!(SCS: value)
  reg_rw!(SCS, value, set_value, value)
  ioreg!(FLASHCFG: value)
  reg_w!(FLASHCFG, set_value, value)
  ioreg!(PLL0CFG: value)
  reg_w!(PLL0CFG, set_value, value)
  ioreg!(PLL0CON: value)
  reg_w!(PLL0CON, set_value, value)
  ioreg!(PLL0FEED: value)
  reg_w!(PLL0FEED, set_value, value)
  ioreg!(PLL0STAT: value)
  reg_r!(PLL0STAT, value, value)
  ioreg!(CCLKCFG: value)
  reg_w!(CCLKCFG, set_value, value)
  ioreg!(CLKSRCSEL: value)
  reg_w!(CLKSRCSEL, set_value, value)

  extern {
    #[link_name="iomem_SCS"] pub static SCS: SCS;
    #[link_name="iomem_FLASHCFG"] pub static FLASHCFG: FLASHCFG;
    #[link_name="iomem_PLL0CFG"] pub static PLL0CFG: PLL0CFG;
    #[link_name="iomem_PLL0CON"] pub static PLL0CON: PLL0CON;
    #[link_name="iomem_CCLKCFG"] pub static CCLKCFG: CCLKCFG;
    #[link_name="iomem_PLL0FEED"] pub static PLL0FEED: PLL0FEED;
    #[link_name="iomem_CLKSRCSEL"] pub static CLKSRCSEL: CLKSRCSEL;
    #[link_name="iomem_PLL0STAT"] pub static PLL0STAT: PLL0STAT;
  }
}
<commit_msg>hal::lpc17xx::init::init_clock is now public.<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
MCU initialication and clock configuration.

This module includes code for setting up the clock, flash, access time and
performing initial peripheral configuration.
*/

use hal::mem_init::init_data;
use hal::stack;

#[path="../../lib/ioreg.rs"] mod ioreg;
#[path="../../lib/wait_for.rs"] mod wait_for;

extern {
  static _eglobals: u32;
}

/// PLL clock source.
pub enum ClockSource {
  /// Internal resonator, 4MHz.
  Internal,
  /// External crystal with configurable frequency.
  Main(u32),
  /// Internal RTC resonator, 32KHz.
  RTC,
}

/// PLL0 configuration options.
///
/// Frequency is calculated as
///
/// ```
/// Fcco = (2 * m * Fin) / n
/// Fcpu = Fcco / divisor
/// ```
pub struct PLL0 {
  /// Specifies if PLL0 should be connected on boot.
  pub enabled: bool,
  /// PLL multiplier.
  pub m: u8,
  /// PLL divisor.
  pub n: u8,
  /// PLL output divisor.
  pub divisor: u8,
}

/// MCU clock configuration.
pub struct Clock {
  /// Clocking source.
  pub source: ClockSource,
  /// PLL configuration.
  pub pll: PLL0,
}

/// MCU configuration.
pub struct SysConf {
  /// Clock configuration.
  pub clock: Clock,
}

// TODO(farcaller): move to peripheral_clock?
static mut SystemClock: u32 = 0;

/// Returns system clock frequency according to configuration.
#[inline(always)]
pub fn system_clock() -> u32 {
  unsafe { SystemClock }
}

/// Performs the MCU initialization.
impl SysConf {
  pub fn setup(&self) {
    init_stack();
    init_data();
    init_clock(&self.clock);
  }
}

#[inline(always)]
fn init_stack() {
  stack::set_stack_limit((&_eglobals as *u32) as u32);
}

#[inline(always)]
pub fn init_clock(clock: &Clock) {
  let src_clock: u32 = match clock.source {
    Internal =>   4_000_000,
    Main(freq) => freq,
    RTC =>        32_000,
  };
  let dst_clock: u32;

  if clock.pll.enabled {
    match clock.source {
      Main(freq) => init_main_oscillator(freq),
      _ => (),
    }
    dst_clock = (src_clock * clock.pll.m as u32 * 2) / clock.pll.n as u32 / clock.pll.divisor as u32;
    init_flash_access(dst_clock);
    init_pll(&clock.pll, clock.source);
  } else {
    dst_clock = src_clock;
  }

  unsafe { SystemClock = dst_clock };
}

#[inline(always)]
fn init_main_oscillator(freq: u32) {
  let val: u32 = if freq > 15_000_000 { 1 << 4 } else { 0 } |
                 (1 << 5);

  reg::SCS.set_value(val);

  wait_for!(reg::SCS.value() & (1 << 6) == (1 << 6));
}

#[inline(always)]
fn init_flash_access(freq: u32) {
  let num_clocks: u32 = if freq > 100_000_000 { 6 } else
                        if freq > 80_000_000 { 5 } else
                        if freq > 60_000_000 { 4 } else
                        if freq > 40_000_000 { 3 } else
                        if freq > 40_000_000 { 2 } else
                        { 1 };
  let val = (num_clocks - 1) << 12;
  reg::FLASHCFG.set_value(val);
}

#[inline(always)]
fn wait_for_pll0stat_bit(bit: u32) {
  wait_for!(reg::PLL0STAT.value() & (1 << bit) == (1 << bit));
}

#[inline(always)]
fn write_pll0_changes() {
  reg::PLL0FEED.set_value(0xaa);
  reg::PLL0FEED.set_value(0x55);
}

#[inline(always)]
fn init_pll(pll: &PLL0, source: ClockSource) {
  match source {
    Internal => reg::CLKSRCSEL.set_value(0),
    Main(_)  => reg::CLKSRCSEL.set_value(1),
    RTC =>      reg::CLKSRCSEL.set_value(2),
  }

  let val: u32 = ((pll.n as u32 - 1) << 16) | ((pll.m as u32 - 1) << 0);
  reg::PLL0CFG.set_value(val);
  write_pll0_changes();
  reg::PLL0CON.set_value(1);
  write_pll0_changes();
  wait_for_pll0stat_bit(24);
  reg::CCLKCFG.set_value((pll.divisor - 1) as u32);
  wait_for_pll0stat_bit(26);
  reg::PLL0CON.set_value(3);
  write_pll0_changes();
  wait_for_pll0stat_bit(25);
}

mod reg {
  use lib::volatile_cell::VolatileCell;

  ioreg!(SCS: value)
  reg_rw!(SCS, value, set_value, value)
  ioreg!(FLASHCFG: value)
  reg_w!(FLASHCFG, set_value, value)
  ioreg!(PLL0CFG: value)
  reg_w!(PLL0CFG, set_value, value)
  ioreg!(PLL0CON: value)
  reg_w!(PLL0CON, set_value, value)
  ioreg!(PLL0FEED: value)
  reg_w!(PLL0FEED, set_value, value)
  ioreg!(PLL0STAT: value)
  reg_r!(PLL0STAT, value, value)
  ioreg!(CCLKCFG: value)
  reg_w!(CCLKCFG, set_value, value)
  ioreg!(CLKSRCSEL: value)
  reg_w!(CLKSRCSEL, set_value, value)

  extern {
    #[link_name="iomem_SCS"] pub static SCS: SCS;
    #[link_name="iomem_FLASHCFG"] pub static FLASHCFG: FLASHCFG;
    #[link_name="iomem_PLL0CFG"] pub static PLL0CFG: PLL0CFG;
    #[link_name="iomem_PLL0CON"] pub static PLL0CON: PLL0CON;
    #[link_name="iomem_CCLKCFG"] pub static CCLKCFG: CCLKCFG;
    #[link_name="iomem_PLL0FEED"] pub static PLL0FEED: PLL0FEED;
    #[link_name="iomem_CLKSRCSEL"] pub static CLKSRCSEL: CLKSRCSEL;
    #[link_name="iomem_PLL0STAT"] pub static PLL0STAT: PLL0STAT;
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Mark Lee
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! A cryptographic hash generator dependent upon OSX's `CommonCrypto`.

use libc::{c_int, c_uint, c_ulong, c_ulonglong};
use std::io;
use super::Algorithm;

macro_rules! unsafe_guard {
    ($e: expr) => {
        unsafe {
            let r = $e;
            assert_eq!(r, 1);
        }
    }
}

const MD5_CBLOCK: usize = 64;
const MD5_LBLOCK: usize = MD5_CBLOCK / 4;
const MD5_DIGEST_LENGTH: usize = 16;

const SHA_LBLOCK: usize = 16;
const SHA256_DIGEST_LENGTH: usize = 32;
const SHA512_DIGEST_LENGTH: usize = 64;

#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone, Debug, PartialEq)]
#[repr(C)]
struct CC_MD5_CTX {
    A: c_uint,
    B: c_uint,
    C: c_uint,
    D: c_uint,
    Nl: c_uint,
    Nh: c_uint,
    data: [c_uint; MD5_LBLOCK],
    num: c_uint,
}

impl CC_MD5_CTX {
    fn new() -> CC_MD5_CTX {
        CC_MD5_CTX {
            A: 0,
            B: 0,
            C: 0,
            D: 0,
            Nl: 0,
            Nh: 0,
            data: [0 as c_uint; MD5_LBLOCK],
            num: 0,
        }
    }
}

#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone, Debug, PartialEq)]
#[repr(C)]
struct CC_SHA256_CTX {
    h: [c_ulong; 8],
    Nl: c_ulong,
    Nh: c_ulong,
    data: [c_ulong; SHA_LBLOCK],
    num: c_uint,
    md_len: c_uint,
}

impl CC_SHA256_CTX {
    fn new() -> CC_SHA256_CTX {
        CC_SHA256_CTX {
            h: [0 as c_ulong; 8],
            Nl: 0,
            Nh: 0,
            data: [0 as c_ulong; SHA_LBLOCK],
            num: 0,
            md_len: 0,
        }
    }
}

#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone, Debug, PartialEq)]
#[repr(C)]
struct CC_SHA512_CTX {
    h: [c_ulonglong; 8],
    Nl: c_ulonglong,
    Nh: c_ulonglong,
    data: [c_ulonglong; SHA_LBLOCK],
    num: c_uint,
    md_len: c_uint,
}

impl CC_SHA512_CTX {
    fn new() -> CC_SHA512_CTX {
        CC_SHA512_CTX {
            h: [0 as c_ulonglong; 8],
            Nl: 0,
            Nh: 0,
            data: [0 as c_ulonglong; SHA_LBLOCK],
            num: 0,
            md_len: 0,
        }
    }
}

#[derive(Debug)]
enum DigestContext {
    MD5(CC_MD5_CTX),
    SHA256(CC_SHA256_CTX),
    SHA512(CC_SHA512_CTX),
}

extern "C" {
    fn CC_MD5_Init(ctx: *mut CC_MD5_CTX) -> c_int;
    fn CC_MD5_Update(ctx: *mut CC_MD5_CTX, data: *const u8, n: usize) -> c_int;
    fn CC_MD5_Final(md: *mut u8, ctx: *mut CC_MD5_CTX) -> c_int;
    fn CC_SHA256_Init(ctx: *mut CC_SHA256_CTX) -> c_int;
    fn CC_SHA256_Update(ctx: *mut CC_SHA256_CTX, data: *const u8, n: usize) -> c_int;
    fn CC_SHA256_Final(md: *mut u8, ctx: *mut CC_SHA256_CTX) -> c_int;
    fn CC_SHA512_Init(ctx: *mut CC_SHA512_CTX) -> c_int;
    fn CC_SHA512_Update(ctx: *mut CC_SHA512_CTX, data: *const u8, n: usize) -> c_int;
    fn CC_SHA512_Final(md: *mut u8, ctx: *mut CC_SHA512_CTX) -> c_int;
}

#[derive(PartialEq, Copy, Clone, Debug)]
enum State {
    Reset,
    Updated,
    Finalized,
}

/// Generator of digests using a cryptographic hash function.
///
/// # Examples
///
/// ```rust
/// use crypto_hash::{Algorithm, Hasher};
/// use std::io::Write;
///
/// let mut hasher = Hasher::new(Algorithm::SHA256);
/// hasher.write_all(b"crypto");
/// hasher.write_all(b"-");
/// hasher.write_all(b"hash");
/// let result = hasher.finish();
/// let expected = b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'".to_vec();
/// assert_eq!(expected, result)
/// ```
#[derive(Debug)]
pub struct Hasher {
    context: DigestContext,
    state: State,
}

fn md5_new() -> CC_MD5_CTX {
    let mut ctx: CC_MD5_CTX = CC_MD5_CTX::new();
    md5_init(&mut ctx);
    ctx
}

fn md5_init(ctx: &mut CC_MD5_CTX) {
    unsafe_guard!(CC_MD5_Init(ctx));
    assert!(!(ctx as *mut CC_MD5_CTX).is_null());
}

fn md5_write(ctx: &mut CC_MD5_CTX, buf: &[u8]) {
    unsafe_guard!(CC_MD5_Update(ctx, buf.as_ptr(), buf.len()));
}

fn md5_finish(ctx: &mut CC_MD5_CTX) -> Vec<u8> {
    let mut md = [0u8; MD5_DIGEST_LENGTH];
    unsafe_guard!(CC_MD5_Final(md.as_mut_ptr(), ctx));
    md.to_vec()
}

fn sha256_new() -> CC_SHA256_CTX {
    let mut ctx: CC_SHA256_CTX = CC_SHA256_CTX::new();
    sha256_init(&mut ctx);
    ctx
}

fn sha512_new() -> CC_SHA512_CTX {
    let mut ctx: CC_SHA512_CTX = CC_SHA512_CTX::new();
    sha512_init(&mut ctx);
    ctx
}

fn sha256_init(ctx: &mut CC_SHA256_CTX) {
    unsafe_guard!(CC_SHA256_Init(ctx));
    assert!(!(ctx as *mut CC_SHA256_CTX).is_null());
}

fn sha512_init(ctx: &mut CC_SHA512_CTX) {
    unsafe_guard!(CC_SHA512_Init(ctx));
    assert!(!(ctx as *mut CC_SHA512_CTX).is_null());
}

fn sha256_write(ctx: &mut CC_SHA256_CTX, buf: &[u8]) {
    unsafe_guard!(CC_SHA256_Update(ctx, buf.as_ptr(), buf.len()));
}

fn sha512_write(ctx: &mut CC_SHA512_CTX, buf: &[u8]) {
    unsafe_guard!(CC_SHA512_Update(ctx, buf.as_ptr(), buf.len()));
}

fn sha256_finish(ctx: &mut CC_SHA256_CTX) -> Vec<u8> {
    let mut md = [0u8; SHA256_DIGEST_LENGTH];
    unsafe_guard!(CC_SHA256_Final(md.as_mut_ptr(), ctx));
    md.to_vec()
}

fn sha512_finish(ctx: &mut CC_SHA512_CTX) -> Vec<u8> {
    let mut md = [0u8; SHA512_DIGEST_LENGTH];
    unsafe_guard!(CC_SHA512_Final(md.as_mut_ptr(), ctx));
    md.to_vec()
}

impl Hasher {
    /// Create a new `Hasher` for the given `Algorithm`.
    pub fn new(algorithm: Algorithm) -> Hasher {
        let context = match algorithm {
            Algorithm::MD5 => DigestContext::MD5(md5_new()),
            Algorithm::SHA256 => DigestContext::SHA256(sha256_new()),
            Algorithm::SHA512 => DigestContext::SHA512(sha512_new()),
        };

        Hasher {
            context: context,
            state: State::Reset,
        }
    }

    fn init(&mut self) {
        match self.state {
            State::Reset => return,
            State::Updated => {
                self.finish();
            }
            State::Finalized => (),
        }
        match self.context {
            DigestContext::MD5(ref mut ctx) => md5_init(ctx),
            DigestContext::SHA256(ref mut ctx) => sha256_init(ctx),
            DigestContext::SHA512(ref mut ctx) => sha512_init(ctx),
        }
        self.state = State::Reset;
    }

    /// Generate a digest from the data written to the `Hasher`.
    pub fn finish(&mut self) -> Vec<u8> {
        if self.state == State::Finalized {
            self.init();
        }
        let result = match self.context {
            DigestContext::MD5(ref mut ctx) => md5_finish(ctx),
            DigestContext::SHA256(ref mut ctx) => sha256_finish(ctx),
            DigestContext::SHA512(ref mut ctx) => sha512_finish(ctx),
        };
        self.state = State::Finalized;

        result
    }
}

impl io::Write for Hasher {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if self.state == State::Finalized {
            self.init();
        }
        match self.context {
            DigestContext::MD5(ref mut ctx) => md5_write(ctx, buf),
            DigestContext::SHA256(ref mut ctx) => sha256_write(ctx, buf),
            DigestContext::SHA512(ref mut ctx) => sha512_write(ctx, buf),
        }
        self.state = State::Updated;
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Drop for Hasher {
    fn drop(&mut self) {
        if self.state != State::Finalized {
            self.finish();
        }
    }
}
<commit_msg>commoncrypto: use a macro to generate helper algorithm functions<commit_after>// Copyright (c) 2016 Mark Lee
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! A cryptographic hash generator dependent upon OSX's `CommonCrypto`.

use libc::{c_int, c_uint, c_ulong, c_ulonglong};
use std::io;
use super::Algorithm;

macro_rules! unsafe_guard {
    ($e: expr) => {
        unsafe {
            let r = $e;
            assert_eq!(r, 1);
        }
    }
}

macro_rules! algorithm_helpers {
    (
        $ctx_ty: ident,
        $init_binding: ident,
        $write_binding: ident,
        $finish_binding: ident,
        $new_name: ident,
        $init_name: ident,
        $write_name: ident,
        $finish_name: ident,
        $digest_len: ident
    ) => {
        fn $new_name() -> $ctx_ty {
            let mut ctx: $ctx_ty = $ctx_ty::new();
            $init_name(&mut ctx);
            ctx
        }

        fn $init_name(ctx: &mut $ctx_ty) {
            unsafe_guard!($init_binding(ctx));
            assert!(!(ctx as *mut $ctx_ty).is_null());
        }

        fn $write_name(ctx: &mut $ctx_ty, buf: &[u8]) {
            unsafe_guard!($write_binding(ctx, buf.as_ptr(), buf.len()));
        }

        fn $finish_name(ctx: &mut $ctx_ty) -> Vec<u8> {
            let mut md = [0u8; $digest_len];
            unsafe_guard!($finish_binding(md.as_mut_ptr(), ctx));
            md.to_vec()
        }
    }
}

const MD5_CBLOCK: usize = 64;
const MD5_LBLOCK: usize = MD5_CBLOCK / 4;
const MD5_DIGEST_LENGTH: usize = 16;

const SHA_LBLOCK: usize = 16;
const SHA256_DIGEST_LENGTH: usize = 32;
const SHA512_DIGEST_LENGTH: usize = 64;

#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone, Debug, PartialEq)]
#[repr(C)]
struct CC_MD5_CTX {
    A: c_uint,
    B: c_uint,
    C: c_uint,
    D: c_uint,
    Nl: c_uint,
    Nh: c_uint,
    data: [c_uint; MD5_LBLOCK],
    num: c_uint,
}

impl CC_MD5_CTX {
    fn new() -> CC_MD5_CTX {
        CC_MD5_CTX {
            A: 0,
            B: 0,
            C: 0,
            D: 0,
            Nl: 0,
            Nh: 0,
            data: [0 as c_uint; MD5_LBLOCK],
            num: 0,
        }
    }
}

#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone, Debug, PartialEq)]
#[repr(C)]
struct CC_SHA256_CTX {
    h: [c_ulong; 8],
    Nl: c_ulong,
    Nh: c_ulong,
    data: [c_ulong; SHA_LBLOCK],
    num: c_uint,
    md_len: c_uint,
}

impl CC_SHA256_CTX {
    fn new() -> CC_SHA256_CTX {
        CC_SHA256_CTX {
            h: [0 as c_ulong; 8],
            Nl: 0,
            Nh: 0,
            data: [0 as c_ulong; SHA_LBLOCK],
            num: 0,
            md_len: 0,
        }
    }
}

#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone, Debug, PartialEq)]
#[repr(C)]
struct CC_SHA512_CTX {
    h: [c_ulonglong; 8],
    Nl: c_ulonglong,
    Nh: c_ulonglong,
    data: [c_ulonglong; SHA_LBLOCK],
    num: c_uint,
    md_len: c_uint,
}

impl CC_SHA512_CTX {
    fn new() -> CC_SHA512_CTX {
        CC_SHA512_CTX {
            h: [0 as c_ulonglong; 8],
            Nl: 0,
            Nh: 0,
            data: [0 as c_ulonglong; SHA_LBLOCK],
            num: 0,
            md_len: 0,
        }
    }
}

#[derive(Debug)]
enum DigestContext {
    MD5(CC_MD5_CTX),
    SHA256(CC_SHA256_CTX),
    SHA512(CC_SHA512_CTX),
}

extern "C" {
    fn CC_MD5_Init(ctx: *mut CC_MD5_CTX) -> c_int;
    fn CC_MD5_Update(ctx: *mut CC_MD5_CTX, data: *const u8, n: usize) -> c_int;
    fn CC_MD5_Final(md: *mut u8, ctx: *mut CC_MD5_CTX) -> c_int;
    fn CC_SHA256_Init(ctx: *mut CC_SHA256_CTX) -> c_int;
    fn CC_SHA256_Update(ctx: *mut CC_SHA256_CTX, data: *const u8, n: usize) -> c_int;
    fn CC_SHA256_Final(md: *mut u8, ctx: *mut CC_SHA256_CTX) -> c_int;
    fn CC_SHA512_Init(ctx: *mut CC_SHA512_CTX) -> c_int;
    fn CC_SHA512_Update(ctx: *mut CC_SHA512_CTX, data: *const u8, n: usize) -> c_int;
    fn CC_SHA512_Final(md: *mut u8, ctx: *mut CC_SHA512_CTX) -> c_int;
}

#[derive(PartialEq, Copy, Clone, Debug)]
enum State {
    Reset,
    Updated,
    Finalized,
}

/// Generator of digests using a cryptographic hash function.
///
/// # Examples
///
/// ```rust
/// use crypto_hash::{Algorithm, Hasher};
/// use std::io::Write;
///
/// let mut hasher = Hasher::new(Algorithm::SHA256);
/// hasher.write_all(b"crypto");
/// hasher.write_all(b"-");
/// hasher.write_all(b"hash");
/// let result = hasher.finish();
/// let expected = b"\xfd\x1a\xfb`\"\xcdMG\xc8\x90\x96\x1cS9(\xea\xcf\xe8!\x9f\x1b%$\xf7\xfb*a\x84}\xdf\x8c'".to_vec();
/// assert_eq!(expected, result)
/// ```
#[derive(Debug)]
pub struct Hasher {
    context: DigestContext,
    state: State,
}

algorithm_helpers!(CC_MD5_CTX,
                   CC_MD5_Init,
                   CC_MD5_Update,
                   CC_MD5_Final,
                   md5_new,
                   md5_init,
                   md5_write,
                   md5_finish,
                   MD5_DIGEST_LENGTH);
algorithm_helpers!(CC_SHA256_CTX,
                   CC_SHA256_Init,
                   CC_SHA256_Update,
                   CC_SHA256_Final,
                   sha256_new,
                   sha256_init,
                   sha256_write,
                   sha256_finish,
                   SHA256_DIGEST_LENGTH);
algorithm_helpers!(CC_SHA512_CTX,
                   CC_SHA512_Init,
                   CC_SHA512_Update,
                   CC_SHA512_Final,
                   sha512_new,
                   sha512_init,
                   sha512_write,
                   sha512_finish,
                   SHA512_DIGEST_LENGTH);

impl Hasher {
    /// Create a new `Hasher` for the given `Algorithm`.
    pub fn new(algorithm: Algorithm) -> Hasher {
        let context = match algorithm {
            Algorithm::MD5 => DigestContext::MD5(md5_new()),
            Algorithm::SHA256 => DigestContext::SHA256(sha256_new()),
            Algorithm::SHA512 => DigestContext::SHA512(sha512_new()),
        };

        Hasher {
            context: context,
            state: State::Reset,
        }
    }

    fn init(&mut self) {
        match self.state {
            State::Reset => return,
            State::Updated => {
                self.finish();
            }
            State::Finalized => (),
        }
        match self.context {
            DigestContext::MD5(ref mut ctx) => md5_init(ctx),
            DigestContext::SHA256(ref mut ctx) => sha256_init(ctx),
            DigestContext::SHA512(ref mut ctx) => sha512_init(ctx),
        }
        self.state = State::Reset;
    }

    /// Generate a digest from the data written to the `Hasher`.
    pub fn finish(&mut self) -> Vec<u8> {
        if self.state == State::Finalized {
            self.init();
        }
        let result = match self.context {
            DigestContext::MD5(ref mut ctx) => md5_finish(ctx),
            DigestContext::SHA256(ref mut ctx) => sha256_finish(ctx),
            DigestContext::SHA512(ref mut ctx) => sha512_finish(ctx),
        };
        self.state = State::Finalized;

        result
    }
}

impl io::Write for Hasher {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if self.state == State::Finalized {
            self.init();
        }
        match self.context {
            DigestContext::MD5(ref mut ctx) => md5_write(ctx, buf),
            DigestContext::SHA256(ref mut ctx) => sha256_write(ctx, buf),
            DigestContext::SHA512(ref mut ctx) => sha512_write(ctx, buf),
        }
        self.state = State::Updated;
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl Drop for Hasher {
    fn drop(&mut self) {
        if self.state != State::Finalized {
            self.finish();
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 by SiegeLord
//
// All rights reserved. Distributed under ZLib. For full terms see the file LICENSE.

use libc::*;
use std::option::Some;
use std::mem;
use std::c_str::CString;

use internal::bitmap::*;
use internal::bitmap_like::*;
use internal::color::*;
use internal::core::*;
use internal::events::*;
use rust_util::Flag;

use ffi::*;

pub use rust_util::c_bool;

flag_type!(
	DisplayFlags
	{
		WINDOWED                  = ALLEGRO_WINDOWED,
		FULLSCREEN                = ALLEGRO_FULLSCREEN,
		OPENGL                    = ALLEGRO_OPENGL,
		DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
		RESIZABLE                 = ALLEGRO_RESIZABLE,
		FRAMELESS                 = ALLEGRO_FRAMELESS,
		GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
		OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
		OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
		FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
		MINIMIZED                 = ALLEGRO_MINIMIZED
	}
)

#[repr(u32)]
pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

#[repr(u32)]
pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

#[repr(u32)]
pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct Display
{
	allegro_display: *mut ALLEGRO_DISPLAY,
	backbuffer: Bitmap,
	event_source: EventSource,
}

impl Display
{
	fn new(w: i32, h: i32) -> Result<Display, String>
	{
		unsafe
		{
			if !al_get_current_display().is_null()
			{
				Err("Only one display is allowed per thread.".to_string())
			}
			else
			{
				let d = al_create_display(w as c_int, h as c_int);
				if d.is_null()
				{
					Err("Could not create the display".to_string())
				}
				else
				{
					Ok
					(
						Display
						{
							allegro_display: d,
							backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
							event_source: new_event_source_ref(al_get_display_event_source(d)),
						}
					)
				}
			}
		}
	}

	pub fn get_width(&self) -> i32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as i32
		}
	}

	pub fn get_height(&self) -> i32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as i32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			mem::transmute(al_get_display_format(self.allegro_display) as u32)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_acknowledge_resize(self.allegro_display) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> Result<(), ()>
	{
		unsafe
		{
			if al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_bitmap());
		}
	}

	pub fn set_icons<T: BitmapLike, U: Iterator<T>>(&self, icons: U)
	{
		let mut c_icons: Vec<_> = icons.map(|ref b| b.get_bitmap()).collect();
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, c_icons.as_mut_ptr());
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			al_set_window_title(self.allegro_display, title.as_ptr());
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn convert_bitmap<T: BitmapLike>(&self, bmp: &T) -> Result<Bitmap, ()>
	{
		clone_bitmap(bmp.get_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}

	pub fn flip(&self)
	{
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_wait_for_vsync() != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}
}

// Not Send just because of the marker in the event source
#[unsafe_destructor]
impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			/* If it's a video bitmap, it's about to be reset, so we fall back to the dummy target */
			if al_get_bitmap_flags(al_get_target_bitmap()) & (ALLEGRO_VIDEO_BITMAP as i32) != 0
			{
				al_set_target_bitmap(dummy_target);
			}
			al_destroy_display(self.allegro_display);
		}
	}
}

impl ::internal::core::Core
{
	pub fn set_new_display_flags(&self, flags: DisplayFlags)
	{
		unsafe
		{
			al_set_new_display_flags(flags.get() as c_int);
		}
	}

	pub fn get_new_display_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_new_display_flags())
		}
	}

	pub fn set_new_display_refresh_rate(&self, rate: i32)
	{
		unsafe
		{
			al_set_new_display_refresh_rate(rate as c_int);
		}
	}

	pub fn get_new_display_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_new_display_refresh_rate() as i32
		}
	}

	pub fn set_new_display_adapter(&self, adapter: i32)
	{
		unsafe
		{
			al_set_new_display_adapter(adapter as c_int);
		}
	}

	pub fn get_new_display_adapter(&self) -> i32
	{
		unsafe
		{
			al_get_new_display_adapter() as i32
		}
	}

	pub fn set_new_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_new_window_position(x as c_int, y as c_int);
		}
	}

	pub fn get_new_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			use std::mem::uninitialized;

			let mut x: c_int = uninitialized();
			let mut y: c_int = uninitialized();
			al_get_new_window_position(&mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn reset_new_display_options(&self)
	{
		unsafe
		{
			al_reset_new_display_options();
		}
	}

	pub fn set_new_display_option(&self, option: DisplayOption, value: i32, importance: DisplayOptionImportance)
	{
		unsafe
		{
			al_set_new_display_option(option as c_int, value as c_int, importance as c_int);
		}
	}

	pub fn get_new_display_option(&self, option: DisplayOption) -> (i32, DisplayOptionImportance)
	{
		unsafe
		{
			use std::mem::uninitialized;

			let mut imp: c_int = uninitialized();

			let val = al_get_new_display_option(option as c_int, &mut imp);
			(val as i32, mem::transmute(imp))
		}
	}

	pub fn create_display(&self, w: i32, h: i32) -> Result<Display, String>
	{
		Display::new(w, h)
	}
}
<commit_msg>Switch set_icons to an array of trait objects for heterogeneus support<commit_after>// Copyright (c) 2014 by SiegeLord
//
// All rights reserved. Distributed under ZLib. For full terms see the file LICENSE.

use libc::*;
use std::option::Some;
use std::mem;
use std::c_str::CString;

use internal::bitmap::*;
use internal::bitmap_like::*;
use internal::color::*;
use internal::core::*;
use internal::events::*;
use rust_util::Flag;

use ffi::*;

pub use rust_util::c_bool;

flag_type!(
	DisplayFlags
	{
		WINDOWED                  = ALLEGRO_WINDOWED,
		FULLSCREEN                = ALLEGRO_FULLSCREEN,
		OPENGL                    = ALLEGRO_OPENGL,
		DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
		RESIZABLE                 = ALLEGRO_RESIZABLE,
		FRAMELESS                 = ALLEGRO_FRAMELESS,
		GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
		OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
		OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
		FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
		MINIMIZED                 = ALLEGRO_MINIMIZED
	}
)

#[repr(u32)]
pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

#[repr(u32)]
pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

#[repr(u32)]
pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct Display
{
	allegro_display: *mut ALLEGRO_DISPLAY,
	backbuffer: Bitmap,
	event_source: EventSource,
}

impl Display
{
	fn new(w: i32, h: i32) -> Result<Display, String>
	{
		unsafe
		{
			if !al_get_current_display().is_null()
			{
				Err("Only one display is allowed per thread.".to_string())
			}
			else
			{
				let d = al_create_display(w as c_int, h as c_int);
				if d.is_null()
				{
					Err("Could not create the display".to_string())
				}
				else
				{
					Ok
					(
						Display
						{
							allegro_display: d,
							backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
							event_source: new_event_source_ref(al_get_display_event_source(d)),
						}
					)
				}
			}
		}
	}

	pub fn get_width(&self) -> i32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as i32
		}
	}

	pub fn get_height(&self) -> i32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as i32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			mem::transmute(al_get_display_format(self.allegro_display) as u32)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_acknowledge_resize(self.allegro_display) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> Result<(), ()>
	{
		unsafe
		{
			if al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_bitmap());
		}
	}

	pub fn set_icons<'l, U: Iterator<&'l BitmapLike>>(&self, icons: U)
	{
		let mut c_icons: Vec<_> = icons.map(|b| b.get_bitmap()).collect();
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, c_icons.as_mut_ptr());
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			al_set_window_title(self.allegro_display, title.as_ptr());
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn convert_bitmap<T: BitmapLike>(&self, bmp: &T) -> Result<Bitmap, ()>
	{
		clone_bitmap(bmp.get_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}

	pub fn flip(&self)
	{
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_wait_for_vsync() != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}
}

// Not Send just because of the marker in the event source
#[unsafe_destructor]
impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			/* If it's a video bitmap, it's about to be reset, so we fall back to the dummy target */
			if al_get_bitmap_flags(al_get_target_bitmap()) & (ALLEGRO_VIDEO_BITMAP as i32) != 0
			{
				al_set_target_bitmap(dummy_target);
			}
			al_destroy_display(self.allegro_display);
		}
	}
}

impl ::internal::core::Core
{
	pub fn set_new_display_flags(&self, flags: DisplayFlags)
	{
		unsafe
		{
			al_set_new_display_flags(flags.get() as c_int);
		}
	}

	pub fn get_new_display_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_new_display_flags())
		}
	}

	pub fn set_new_display_refresh_rate(&self, rate: i32)
	{
		unsafe
		{
			al_set_new_display_refresh_rate(rate as c_int);
		}
	}

	pub fn get_new_display_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_new_display_refresh_rate() as i32
		}
	}

	pub fn set_new_display_adapter(&self, adapter: i32)
	{
		unsafe
		{
			al_set_new_display_adapter(adapter as c_int);
		}
	}

	pub fn get_new_display_adapter(&self) -> i32
	{
		unsafe
		{
			al_get_new_display_adapter() as i32
		}
	}

	pub fn set_new_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_new_window_position(x as c_int, y as c_int);
		}
	}

	pub fn get_new_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			use std::mem::uninitialized;

			let mut x: c_int = uninitialized();
			let mut y: c_int = uninitialized();
			al_get_new_window_position(&mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn reset_new_display_options(&self)
	{
		unsafe
		{
			al_reset_new_display_options();
		}
	}

	pub fn set_new_display_option(&self, option: DisplayOption, value: i32, importance: DisplayOptionImportance)
	{
		unsafe
		{
			al_set_new_display_option(option as c_int, value as c_int, importance as c_int);
		}
	}

	pub fn get_new_display_option(&self, option: DisplayOption) -> (i32, DisplayOptionImportance)
	{
		unsafe
		{
			use std::mem::uninitialized;

			let mut imp: c_int = uninitialized();

			let val = al_get_new_display_option(option as c_int, &mut imp);
			(val as i32, mem::transmute(imp))
		}
	}

	pub fn create_display(&self, w: i32, h: i32) -> Result<Display, String>
	{
		Display::new(w, h)
	}
}
<|endoftext|>


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

/// See docs of the `procedural-masquerade` crate.
define_invoke_proc_macro!(cssparser_internal__invoke_proc_macro);

/// Expands to a `match` expression with string patterns,
/// matching case-insensitively in the ASCII range.
///
/// The patterns must not contain ASCII upper case letters. (They must be already be lower-cased.)
///
/// # Example
///
/// ```rust
/// #[macro_use] extern crate cssparser;
///
/// # fn main() {}  // Make doctest not wrap everythig in its own main
/// # fn dummy(function_name: &String) { let _ =
/// match_ignore_ascii_case! { &function_name,
///     "rgb" => parse_rgb(..),
///     "rgba" => parse_rgba(..),
///     "hsl" => parse_hsl(..),
///     "hsla" => parse_hsla(..),
///     name @ _ => Err(format!("unknown function: {}", name))
/// }
/// # ;}
/// # use std::ops::RangeFull;
/// # fn parse_rgb(_: RangeFull) -> Result<(), String> { Ok(()) }
/// # fn parse_rgba(_: RangeFull) -> Result<(), String> { Ok(()) }
/// # fn parse_hsl(_: RangeFull) -> Result<(), String> { Ok(()) }
/// # fn parse_hsla(_: RangeFull) -> Result<(), String> { Ok(()) }
/// ```
#[macro_export]
macro_rules! match_ignore_ascii_case {
    ( $input:expr, $( $match_body:tt )* ) => {
        {
            cssparser_internal__invoke_proc_macro! {
                cssparser_internal__assert_ascii_lowercase__max_len!( $( $match_body )* )
            }

            {
                // MAX_LENGTH is generated by cssparser_internal__assert_ascii_lowercase__max_len
                cssparser_internal__to_lowercase!($input, MAX_LENGTH => lowercase);
                // "A" is a short string that we know is different for every string pattern,
                // since we’ve verified that none of them include ASCII upper case letters.
                match lowercase.unwrap_or("A") {
                    $( $match_body )*
                }
            }
        }
    };
}

/// Define a function `$name(&str) -> Option<&'static $ValueType>`
///
/// The function finds a match for the input string
/// in a [`phf` map](https://github.com/sfackler/rust-phf)
/// and returns a reference to the corresponding value.
/// Matching is case-insensitive in the ASCII range.
///
/// ## Example:
///
/// ```rust
/// #[macro_use] extern crate cssparser;
///
/// # fn main() {}  // Make doctest not wrap everything in its own main
///
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
///     ascii_case_insensitive_phf_map! {
///         keyword -> (u8, u8, u8) = {
///             "red" => (255, 0, 0),
///             "green" => (0, 255, 0),
///             "blue" => (0, 0, 255),
///         }
///     }
///     keyword(input).cloned()
/// }
#[macro_export]
macro_rules! ascii_case_insensitive_phf_map {
    ($name: ident -> $ValueType: ty = { $( $key: expr => $value: expr, )* }) => {
        fn $name(input: &str) -> Option<&'static $ValueType> {
            cssparser_internal__invoke_proc_macro! {
                cssparser_internal__phf_map!( ($ValueType) $( $key ($value) )+ )
            }

            {
                cssparser_internal__invoke_proc_macro! {
                    cssparser_internal__max_len!( $( $key )+ )
                }
                // MAX_LENGTH is generated by cssparser_internal__max_len
                cssparser_internal__to_lowercase!(input, MAX_LENGTH => lowercase);
                lowercase.and_then(|s| MAP.get(s))
            }
        }
    }
}

/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
///
/// **This macro is not part of the public API. It can change or be removed between any versions.**
///
/// Define a local variable named `$output`
/// and assign it the result of calling `_internal__to_lowercase`
/// with a stack-allocated buffer of length `$BUFFER_SIZE`.
#[macro_export]
#[doc(hidden)]
macro_rules! cssparser_internal__to_lowercase {
    ($input: expr, $BUFFER_SIZE: expr => $output: ident) => {
        // mem::uninitialized() is ok because `buffer` is only used in `_internal__to_lowercase`,
        // which initializes with `copy_from_slice` the part of the buffer it uses,
        // before it uses it.
        #[allow(unsafe_code)]
        let mut buffer: [u8; $BUFFER_SIZE] = unsafe {
            ::std::mem::uninitialized()
        };
        let input: &str = $input;
        let $output = $crate::_internal__to_lowercase(&mut buffer, input);
    }
}

/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
///
/// **This function is not part of the public API. It can change or be removed between any verisons.**
///
/// If `input` is larger than buffer, return `None`.
/// Otherwise, return `input` ASCII-lowercased, using `buffer` as temporary space if necessary.
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn _internal__to_lowercase<'a>(buffer: &'a mut [u8], input: &'a str) -> Option<&'a str> {
    if let Some(buffer) = buffer.get_mut(..input.len()) {
        if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'...b'Z')) {
            buffer.copy_from_slice(input.as_bytes());
            ::std::ascii::AsciiExt::make_ascii_lowercase(&mut buffer[first_uppercase..]);
            // `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
            // then lowercased (which preserves UTF-8 well-formedness)
            unsafe {
                Some(::std::str::from_utf8_unchecked(buffer))
            }
        } else {
            // Input is already lower-case
            Some(input)
        }
    } else {
        // Input is longer than buffer, which has the length of the longest expected string:
        // none of the expected strings would match.
        None
    }
}

#[cfg(feature = "dummy_match_byte")]
macro_rules! match_byte {
    ($value:expr, $($rest:tt)* ) => {
        match $value {
            $(
                $rest
            )+
        }
    };
}
<commit_msg>ascii_case_insensitive_phf_map: accept k/v pairs without a trailing comma<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/// See docs of the `procedural-masquerade` crate.
define_invoke_proc_macro!(cssparser_internal__invoke_proc_macro);

/// Expands to a `match` expression with string patterns,
/// matching case-insensitively in the ASCII range.
///
/// The patterns must not contain ASCII upper case letters. (They must be already be lower-cased.)
///
/// # Example
///
/// ```rust
/// #[macro_use] extern crate cssparser;
///
/// # fn main() {}  // Make doctest not wrap everythig in its own main
/// # fn dummy(function_name: &String) { let _ =
/// match_ignore_ascii_case! { &function_name,
///     "rgb" => parse_rgb(..),
///     "rgba" => parse_rgba(..),
///     "hsl" => parse_hsl(..),
///     "hsla" => parse_hsla(..),
///     name @ _ => Err(format!("unknown function: {}", name))
/// }
/// # ;}
/// # use std::ops::RangeFull;
/// # fn parse_rgb(_: RangeFull) -> Result<(), String> { Ok(()) }
/// # fn parse_rgba(_: RangeFull) -> Result<(), String> { Ok(()) }
/// # fn parse_hsl(_: RangeFull) -> Result<(), String> { Ok(()) }
/// # fn parse_hsla(_: RangeFull) -> Result<(), String> { Ok(()) }
/// ```
#[macro_export]
macro_rules! match_ignore_ascii_case {
    ( $input:expr, $( $match_body:tt )* ) => {
        {
            cssparser_internal__invoke_proc_macro! {
                cssparser_internal__assert_ascii_lowercase__max_len!( $( $match_body )* )
            }

            {
                // MAX_LENGTH is generated by cssparser_internal__assert_ascii_lowercase__max_len
                cssparser_internal__to_lowercase!($input, MAX_LENGTH => lowercase);
                // "A" is a short string that we know is different for every string pattern,
                // since we’ve verified that none of them include ASCII upper case letters.
                match lowercase.unwrap_or("A") {
                    $( $match_body )*
                }
            }
        }
    };
}

/// Define a function `$name(&str) -> Option<&'static $ValueType>`
///
/// The function finds a match for the input string
/// in a [`phf` map](https://github.com/sfackler/rust-phf)
/// and returns a reference to the corresponding value.
/// Matching is case-insensitive in the ASCII range.
///
/// ## Example:
///
/// ```rust
/// #[macro_use] extern crate cssparser;
///
/// # fn main() {}  // Make doctest not wrap everything in its own main
///
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
///     ascii_case_insensitive_phf_map! {
///         keyword -> (u8, u8, u8) = {
///             "red" => (255, 0, 0),
///             "green" => (0, 255, 0),
///             "blue" => (0, 0, 255),
///         }
///     }
///     keyword(input).cloned()
/// }
#[macro_export]
macro_rules! ascii_case_insensitive_phf_map {
    ($name: ident -> $ValueType: ty = { $( $key: expr => $value: expr ),* }) => {
        ascii_case_insensitive_phf_map!($name -> $ValueType = { $( $key => $value, )* })
    };
    ($name: ident -> $ValueType: ty = { $( $key: expr => $value: expr, )* }) => {
        fn $name(input: &str) -> Option<&'static $ValueType> {
            cssparser_internal__invoke_proc_macro! {
                cssparser_internal__phf_map!( ($ValueType) $( $key ($value) )+ )
            }

            {
                cssparser_internal__invoke_proc_macro! {
                    cssparser_internal__max_len!( $( $key )+ )
                }
                // MAX_LENGTH is generated by cssparser_internal__max_len
                cssparser_internal__to_lowercase!(input, MAX_LENGTH => lowercase);
                lowercase.and_then(|s| MAP.get(s))
            }
        }
    }
}

/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
///
/// **This macro is not part of the public API. It can change or be removed between any versions.**
///
/// Define a local variable named `$output`
/// and assign it the result of calling `_internal__to_lowercase`
/// with a stack-allocated buffer of length `$BUFFER_SIZE`.
#[macro_export]
#[doc(hidden)]
macro_rules! cssparser_internal__to_lowercase {
    ($input: expr, $BUFFER_SIZE: expr => $output: ident) => {
        // mem::uninitialized() is ok because `buffer` is only used in `_internal__to_lowercase`,
        // which initializes with `copy_from_slice` the part of the buffer it uses,
        // before it uses it.
        #[allow(unsafe_code)]
        let mut buffer: [u8; $BUFFER_SIZE] = unsafe {
            ::std::mem::uninitialized()
        };
        let input: &str = $input;
        let $output = $crate::_internal__to_lowercase(&mut buffer, input);
    }
}

/// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
///
/// **This function is not part of the public API. It can change or be removed between any verisons.**
///
/// If `input` is larger than buffer, return `None`.
/// Otherwise, return `input` ASCII-lowercased, using `buffer` as temporary space if necessary.
#[doc(hidden)]
#[allow(non_snake_case)]
pub fn _internal__to_lowercase<'a>(buffer: &'a mut [u8], input: &'a str) -> Option<&'a str> {
    if let Some(buffer) = buffer.get_mut(..input.len()) {
        if let Some(first_uppercase) = input.bytes().position(|byte| matches!(byte, b'A'...b'Z')) {
            buffer.copy_from_slice(input.as_bytes());
            ::std::ascii::AsciiExt::make_ascii_lowercase(&mut buffer[first_uppercase..]);
            // `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
            // then lowercased (which preserves UTF-8 well-formedness)
            unsafe {
                Some(::std::str::from_utf8_unchecked(buffer))
            }
        } else {
            // Input is already lower-case
            Some(input)
        }
    } else {
        // Input is longer than buffer, which has the length of the longest expected string:
        // none of the expected strings would match.
        None
    }
}

#[cfg(feature = "dummy_match_byte")]
macro_rules! match_byte {
    ($value:expr, $($rest:tt)* ) => {
        match $value {
            $(
                $rest
            )+
        }
    };
}
<|endoftext|>


<commit_before>//! Helper macros. Note that these are relatively new and may change in a later version.
//!
//! The idea is to use `itry` for internal server operations which can't be recovered from, and
//! `iexpect` for validating user input. Note that this kind of usage is completely non-normative.
//! Feedback about actual usability and usage is appreciated.

/// Like `try!()`, but wraps the error value in `IronError`. To be used in
/// request handlers.
///
/// The second (optional) parameter is any [modifier](modifiers/index.html).
/// The default modifier is `status::InternalServerError`.
///
///
/// ```ignore
/// let f = itry!(fs::File::create("foo.txt"), status::BadRequest);
/// let f = itry!(fs::File::create("foo.txt"), (status::NotFound, "Not Found"));
/// let f = itry!(fs::File::create("foo.txt"));  // HTTP 500
/// ```
///
#[macro_export]
macro_rules! itry {
    ($result:expr) => (itry!($result, $crate::status::InternalServerError));

    ($result:expr, $modifier:expr) => (match $result {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err(err) => return ::std::result::Result::Err(
            $crate::IronError::new(err, $modifier))
    })
}

/// Unwrap the given `Option` or return a `Ok(Response::new())` with the given
/// modifier. The default modifier is `status::BadRequest.
#[macro_export]
macro_rules! iexpect {
    ($option:expr) => (iexpect!($option, $crate::status::BadRequest));
    ($option:expr, $modifier:expr) => (match $option {
        ::std::option::Option::Some(x) => x,
        ::std::option::Option::None => return ::std::result::Result::Ok(
            $crate::response::Response::with($modifier))
    })
}
<commit_msg>(fix) Formatting<commit_after>//! Helper macros. Note that these are relatively new and may change in a later version.
//!
//! The idea is to use `itry` for internal server operations which can't be recovered from, and
//! `iexpect` for validating user input. Note that this kind of usage is completely non-normative.
//! Feedback about actual usability and usage is appreciated.

/// Like `try!()`, but wraps the error value in `IronError`. To be used in
/// request handlers.
///
/// The second (optional) parameter is any [modifier](modifiers/index.html).
/// The default modifier is `status::InternalServerError`.
///
///
/// ```ignore
/// let f = itry!(fs::File::create("foo.txt"), status::BadRequest);
/// let f = itry!(fs::File::create("foo.txt"), (status::NotFound, "Not Found"));
/// let f = itry!(fs::File::create("foo.txt"));  // HTTP 500
/// ```
///
#[macro_export]
macro_rules! itry {
    ($result:expr) => (itry!($result, $crate::status::InternalServerError));

    ($result:expr, $modifier:expr) => (match $result {
        ::std::result::Result::Ok(val) => val,
        ::std::result::Result::Err(err) => return ::std::result::Result::Err(
            $crate::IronError::new(err, $modifier))
    })
}

/// Unwrap the given `Option` or return a `Ok(Response::new())` with the given
/// modifier. The default modifier is `status::BadRequest`.
#[macro_export]
macro_rules! iexpect {
    ($option:expr) => (iexpect!($option, $crate::status::BadRequest));
    ($option:expr, $modifier:expr) => (match $option {
        ::std::option::Option::Some(x) => x,
        ::std::option::Option::None => return ::std::result::Result::Ok(
            $crate::response::Response::with($modifier))
    })
}
<|endoftext|>


<commit_before>use std::io;
use std::mem;

use bytes::{BufMut, Bytes, BytesMut};
use nom::{self, Needed};
use tokio_util::codec::{Decoder, Encoder};

use imap_proto::types::{Request, RequestId, Response};

pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl Default for ImapCodec {
    fn default() -> Self {
        Self {
            decode_need_message_bytes: 0,
        }
    }
}

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let (response, rsp_len) = match imap_proto::Response::from_bytes(buf) {
            Ok((remaining, response)) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                (response, buf.len() - remaining.len())
            }
            Err(nom::Err::Incomplete(Needed::Size(min))) => {
                self.decode_need_message_bytes = min;
                return Ok(None);
            }
            Err(nom::Err::Incomplete(_)) => {
                return Ok(None);
            }
            Err(nom::Err::Error((_input, err_kind)))
            | Err(nom::Err::Failure((_input, err_kind))) => {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("{:?} during parsing of {:?}", err_kind, buf),
                ));
            }
        };
        let raw = buf.split_to(rsp_len).freeze();
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl<'a> Encoder<&'a Request<'a>> for ImapCodec {
    type Error = io::Error;
    fn encode(&mut self, msg: &Request, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(msg.0);
        dst.put_u8(b' ');
        dst.put_slice(msg.1);
        dst.put_slice(b"\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: Bytes,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    //
    // `raw` is never mutated during the lifetime of `ResponseData`,
    // and `Response` does not not implement any specific drop glue.
    response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done { ref tag, .. } => Some(tag),
            _ => None,
        }
    }
    pub fn parsed<'a>(&'a self) -> &'a Response<'a> {
        &self.response
    }
}
<commit_msg>Derive Default for ImapCodec<commit_after>use std::io;
use std::mem;

use bytes::{BufMut, Bytes, BytesMut};
use nom::{self, Needed};
use tokio_util::codec::{Decoder, Encoder};

use imap_proto::types::{Request, RequestId, Response};

#[derive(Default)]
pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let (response, rsp_len) = match imap_proto::Response::from_bytes(buf) {
            Ok((remaining, response)) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                (response, buf.len() - remaining.len())
            }
            Err(nom::Err::Incomplete(Needed::Size(min))) => {
                self.decode_need_message_bytes = min;
                return Ok(None);
            }
            Err(nom::Err::Incomplete(_)) => {
                return Ok(None);
            }
            Err(nom::Err::Error((_input, err_kind)))
            | Err(nom::Err::Failure((_input, err_kind))) => {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("{:?} during parsing of {:?}", err_kind, buf),
                ));
            }
        };
        let raw = buf.split_to(rsp_len).freeze();
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl<'a> Encoder<&'a Request<'a>> for ImapCodec {
    type Error = io::Error;
    fn encode(&mut self, msg: &Request, dst: &mut BytesMut) -> Result<(), io::Error> {
        dst.put(msg.0);
        dst.put_u8(b' ');
        dst.put_slice(msg.1);
        dst.put_slice(b"\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: Bytes,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    //
    // `raw` is never mutated during the lifetime of `ResponseData`,
    // and `Response` does not not implement any specific drop glue.
    response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done { ref tag, .. } => Some(tag),
            _ => None,
        }
    }
    pub fn parsed<'a>(&'a self) -> &'a Response<'a> {
        &self.response
    }
}
<|endoftext|>


<commit_before>use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

pub struct T<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

pub fn new<'a, 'b:'a>(gl: &'a GLContext) -> T<'b> {
  let components = vec!(
    (gl::VERTEX_SHADER, "
      #version 330 core

      void main() {
        if (gl_VertexID == 0) {
          gl_Position = vec4(1, -1, 0, 1);
        } else if (gl_VertexID == 1) {
          gl_Position = vec4(1, 1, 0, 1);
        } else if (gl_VertexID == 2) {
          gl_Position = vec4(-1, -1, 0, 1);
        } else if (gl_VertexID == 3) {
          gl_Position = vec4(-1, 1, 0, 1);
        }
      }".to_owned()),
    (gl::FRAGMENT_SHADER,
      format!(r#"
        #version 330 core

        const float CLOUD_HEIGHT = 1000;

        uniform vec2 window_size;
        uniform vec3 sun_color;

        uniform mat4 projection_matrix;
        uniform vec3 eye_position;

        out vec4 frag_color;

        // include depth fog
        {}

        // include cnoise
        {}

        vec3 pixel_direction(vec2 pixel) {{
          // Scale to [0, 1]
          pixel /= window_size;
          // Scale to [-1, 1]
          pixel = 2*pixel - 1;
          vec4 p = inverse(projection_matrix) * vec4(pixel, -1, 1);
          return normalize(vec3(p / p.w) - eye_position);
        }}

        void main() {{
          vec3 direction = pixel_direction(gl_FragCoord.xy);
          float dist = CLOUD_HEIGHT;
          vec3 seed = (eye_position + dist * direction) / CLOUD_HEIGHT * vec3(1, 4, 1);
          float f = cnoise(seed);
          f = sign(f) * pow(abs(f), 15.0/16);
          f = f / 2 + 0.5;
          f = f * f;
          vec4 sky_color = vec4(mix(sun_color, vec3(1, 1, 1), f), 1);
          vec4 fog_color = vec4(sun_color, 1);
          frag_color = apply_fog(sky_color, fog_color, dist / 768);
        }}"#,
        ::shaders::depth_fog::to_string(),
        ::shaders::noise::cnoise(),
      )
    ),
  );
  T {
    shader: Shader::new(gl, components.into_iter()),
  }
}
<commit_msg>tweaking clouds<commit_after>use gl;
use yaglw::gl_context::GLContext;
use yaglw::shader::Shader;

pub struct T<'a> {
  #[allow(missing_docs)]
  pub shader: Shader<'a>,
}

pub fn new<'a, 'b:'a>(gl: &'a GLContext) -> T<'b> {
  let components = vec!(
    (gl::VERTEX_SHADER, "
      #version 330 core

      void main() {
        if (gl_VertexID == 0) {
          gl_Position = vec4(1, -1, 0, 1);
        } else if (gl_VertexID == 1) {
          gl_Position = vec4(1, 1, 0, 1);
        } else if (gl_VertexID == 2) {
          gl_Position = vec4(-1, -1, 0, 1);
        } else if (gl_VertexID == 3) {
          gl_Position = vec4(-1, 1, 0, 1);
        }
      }".to_owned()),
    (gl::FRAGMENT_SHADER,
      format!(r#"
        #version 330 core

        const float CLOUD_HEIGHT = 1000;

        uniform vec2 window_size;
        uniform vec3 sun_color;

        uniform mat4 projection_matrix;
        uniform vec3 eye_position;

        out vec4 frag_color;

        // include depth fog
        {}

        // include cnoise
        {}

        vec3 pixel_direction(vec2 pixel) {{
          // Scale to [0, 1]
          pixel /= window_size;
          // Scale to [-1, 1]
          pixel = 2*pixel - 1;
          vec4 p = inverse(projection_matrix) * vec4(pixel, -1, 1);
          return normalize(vec3(p / p.w) - eye_position);
        }}

        void main() {{
          vec3 direction = pixel_direction(gl_FragCoord.xy);
          float dist = (CLOUD_HEIGHT - eye_position.y) / direction.y;
          vec4 fog_color = vec4(sun_color, 1);
          if (dist <= 0 || dist > 1000000) {{
            frag_color = fog_color;
          }} else {{
            vec3 seed = (eye_position + dist * direction) / CLOUD_HEIGHT * vec3(1, 4, 1);
            float f = cnoise(seed);
            // squish away from 0
            f = sign(f) * pow(abs(f), 12.0/16);
            // to [0, 1]
            f = f / 2 + 0.5;
            // squish towards 0
            f = pow(f, 4);
            vec4 sky_color = vec4(mix(sun_color, vec3(1, 1, 1), f), 1);
            frag_color = apply_fog(sky_color, fog_color, dist / 32);
          }}
        }}"#,
        ::shaders::depth_fog::to_string(),
        ::shaders::noise::cnoise(),
      )
    ),
  );
  T {
    shader: Shader::new(gl, components.into_iter()),
  }
}
<|endoftext|>


<commit_before><commit_msg>Update demo<commit_after><|endoftext|>


<commit_before>pub mod responses {

    use std::fmt;

    use serde;
    use serde_json as json;

    #[derive(Deserialize, Debug)]
    pub struct AuthResponse {
        pub session: SessionResponse,
    }

    #[derive(Deserialize, Debug, Clone)]
    pub struct SessionResponse {
        pub key: String,
        pub subscriber: i64,
        pub name: String,
    }

    #[derive(Deserialize)]
    pub struct NowPlayingResponseWrapper {
        pub nowplaying: NowPlayingResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct NowPlayingResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize)]
    pub struct ScrobbleResponseWrapper {
        pub scrobbles: Scrobbles,
    }

    #[derive(Deserialize)]
    pub struct Scrobbles {
        pub scrobble: ScrobbleResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct ScrobbleResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize, Debug)]
    pub struct CorrectableString {
        #[serde(deserialize_with="CorrectableString::deserialize_corrected_field")]
        pub corrected: bool,
        #[serde(rename="#text", default)]
        pub text: String,
    }

    impl CorrectableString {
        fn deserialize_corrected_field<D>(de: D) -> Result<bool, D::Error>
            where D: serde::Deserializer
        {
            let deser_result: json::Value = try!(serde::Deserialize::deserialize(de));
            match deser_result {
                json::Value::String(ref s) if &*s == "1" => Ok(true),
                json::Value::String(ref s) if &*s == "0" => Ok(false),
                _ => Err(serde::de::Error::custom("Unexpected value")),
            }
        }
    }

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

}
<commit_msg>Fix missing lifetime for custom deserialiser in models.rs (was missed when rebasing old branch)<commit_after>pub mod responses {

    use std::fmt;

    use serde;
    use serde_json as json;

    #[derive(Deserialize, Debug)]
    pub struct AuthResponse {
        pub session: SessionResponse,
    }

    #[derive(Deserialize, Debug, Clone)]
    pub struct SessionResponse {
        pub key: String,
        pub subscriber: i64,
        pub name: String,
    }

    #[derive(Deserialize)]
    pub struct NowPlayingResponseWrapper {
        pub nowplaying: NowPlayingResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct NowPlayingResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize)]
    pub struct ScrobbleResponseWrapper {
        pub scrobbles: Scrobbles,
    }

    #[derive(Deserialize)]
    pub struct Scrobbles {
        pub scrobble: ScrobbleResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct ScrobbleResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize, Debug)]
    pub struct CorrectableString {
        #[serde(deserialize_with="CorrectableString::deserialize_corrected_field")]
        pub corrected: bool,
        #[serde(rename="#text", default)]
        pub text: String,
    }

    impl CorrectableString {
        fn deserialize_corrected_field<'de, D>(de: D) -> Result<bool, D::Error>
            where D: serde::Deserializer<'de>
        {
            let deser_result: json::Value = try!(serde::Deserialize::deserialize(de));
            match deser_result {
                json::Value::String(ref s) if &*s == "1" => Ok(true),
                json::Value::String(ref s) if &*s == "0" => Ok(false),
                _ => Err(serde::de::Error::custom("Unexpected value")),
            }
        }
    }

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

}
<|endoftext|>


<commit_before>

use error::QuicError;
use error::Result;

use std::io::Cursor;
use std::io::Read;

use byteorder::{ReadBytesExt, BigEndian};

use header::QuicHeader;
use header::ShortHeader;
use header::LongHeader;

use frames::QuicFrame;

bitflags! {
    pub flags ShortPacketType: u8 {
        const ONE_BYTE = 0x01,
        const TWO_BYTES = 0x02,
        const FOUR_BYTES = 0x03,
    }
}

bitflags! {
    pub flags PacketType: u8 {
        const VERSION_NEGOTIATION = 0x01,
        const CLIENT_CLEARTEXT = 0x02,
        const NON_FINAL_CLEARTEXT = 0x03,
        const FINAL_SERVER_CLEAR_TEXT = 0x04,
        const RTT0_ENCRYPTED = 0x05,
        const RTT1_ENCRYPTED_PHASE0 = 0x06,
        const RTT1_ENCRYPTED_PHASE1 = 0x07,
        const PUBLIC_RESET = 0x08,
    }
}

#[derive(Debug)]
pub struct QuicPacket {
    pub header: QuicHeader,
    pub payload: Option<Vec<QuicFrame>>,
}

impl QuicPacket {
    pub fn from_bytes(buf: &Vec<u8>) -> Result<QuicPacket> {
        let mut reader = Cursor::new(buf);
        let first_byte = reader.read_uint::<BigEndian>(1)? as u8;

        if first_byte & 0x80 != 0 { // Long Header
            let packet_type = match PacketType::from_bits(first_byte & 0x7f) {
                Some(pt) => pt,
                None => return Err(QuicError::ParseError)
            };

            let connection_id = reader.read_u64::<BigEndian>()?;
            let packet_number = reader.read_u32::<BigEndian>()?;
            let version = reader.read_u32::<BigEndian>()?;

            if version == 0 {
                return Err(QuicError::ParseError)
            }

            let mut payload_bytes = Vec::new();
            let _ = reader.read_to_end(&mut payload_bytes);

            let frames = QuicPacket::parse_decrypted_payload(payload_bytes.as_slice())?;

            return Ok(QuicPacket {
                header: QuicHeader::Long(LongHeader {
                    packet_type: packet_type,
                    connection_id: connection_id,
                    packet_number: packet_number,
                    version: version,
                }),
                payload: Some(frames)
            })
        } else { // ShortHeader
            let conn_id_flag = first_byte & 0x40 != 0;
            let key_phase_bit = first_byte & 0x20 != 0;
            let packet_type = ShortPacketType::from_bits_truncate(first_byte & 0x1f);

            let mut connection_id: Option<u64> = None;

            if conn_id_flag {
                connection_id = Some(reader.read_u64::<BigEndian>()?);
            }

            let packet_number_size = match packet_type {
                ONE_BYTE => Some(1u8),
                TWO_BYTES => Some(2u8),
                FOUR_BYTES => Some(4u8),
                _ => return Err(QuicError::ParseError)
            }.unwrap();

            let packet_number = match packet_number_size {
                1 => reader.read_uint::<BigEndian>(1)? as u64,
                2 => reader.read_uint::<BigEndian>(2)? as u64,
                4 => reader.read_uint::<BigEndian>(4)? as u64,
                _ => return Err(QuicError::ParseError),
            };

            let mut payload = Vec::new();
            let _ = reader.read_to_end(&mut payload);

//            return Ok(QuicPacket {
//                header: QuicHeader::Short(ShortHeader {
//                    key_phase_bit: key_phase_bit,
//                    connection_id: connection_id,
//                    packet_number: packet_number,
//                    conn_id_bit: conn_id_flag,
//                    packet_type: packet_type
//                }),
//                payload: payload
//            })

            // TODO: Decrypt frames and return the payloads.
            Err(QuicError::ParseError)
        }
    }

    pub fn as_bytes(&self) -> Result<Vec<u8>> {
        let header_bytes = match self.header {
            QuicHeader::Short(ref header) => header.as_bytes(),
            QuicHeader::Long(ref header) => header.as_bytes(),
        };

        let packet_bytes;

        if let Some(ref payload) = self.payload {
            let payload_bytes = payload.iter().map(|ref frame| {
                frame.as_bytes()
            })
                .collect::<Vec<_>>()
                .concat();

            packet_bytes = [header_bytes, payload_bytes].concat();
        } else {
            packet_bytes = header_bytes;
        }

        if packet_bytes.len() > 1232 {
            return Err(QuicError::PacketTooLarge);
        }

        Ok(packet_bytes)
    }

    pub fn parse_decrypted_payload(buf: &[u8]) -> Result<Vec<QuicFrame>> {
        let mut frames: Vec<QuicFrame> = Vec::new();

        let mut position = 0;
        loop {
            let frame_len = QuicFrame::frame_length(&buf[position..])?;
            let frame_end = position + frame_len;

            let frame = QuicFrame::from_bytes(&buf[position..frame_end])?;

            position += frame_len;

            frames.push(frame);

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

        Ok(frames)
    }
}

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

    #[test]
    fn parse_decrypted_payload_1() {
        let reason = "Terrible connection!";
        let frames = vec![
            QuicFrame::ConnectionClose(frames::connection_close_frame::ConnectionCloseFrame {
                error_code: 29,
                reason_length: reason.len() as u16,
                reason_phrase: Some(reason.to_string()),
            }),
            QuicFrame::MaxStreamData(frames::max_stream_data_frame::MaxStreamDataFrame {
                stream_id: 20099 as u32,
                max_stream_data: 290 as u64,
            }),
        ];

        let mut bytes = Vec::new();

        for frame in &frames {
            let frame_bytes = frame.as_bytes();
            bytes.extend(frame_bytes);
        }

        let parsed_frames = QuicPacket::parse_decrypted_payload(&bytes).unwrap();

        assert_eq!(&frames, &parsed_frames);
    }
}

<commit_msg>QuicPacket::from_bytes on short headers no longer returns an error, but the packet with an empty payload.<commit_after>

use error::QuicError;
use error::Result;

use std::io::Cursor;
use std::io::Read;

use byteorder::{ReadBytesExt, BigEndian};

use header::QuicHeader;
use header::ShortHeader;
use header::LongHeader;

use frames::QuicFrame;

bitflags! {
    pub flags ShortPacketType: u8 {
        const ONE_BYTE = 0x01,
        const TWO_BYTES = 0x02,
        const FOUR_BYTES = 0x03,
    }
}

bitflags! {
    pub flags PacketType: u8 {
        const VERSION_NEGOTIATION = 0x01,
        const CLIENT_CLEARTEXT = 0x02,
        const NON_FINAL_CLEARTEXT = 0x03,
        const FINAL_SERVER_CLEAR_TEXT = 0x04,
        const RTT0_ENCRYPTED = 0x05,
        const RTT1_ENCRYPTED_PHASE0 = 0x06,
        const RTT1_ENCRYPTED_PHASE1 = 0x07,
        const PUBLIC_RESET = 0x08,
    }
}

#[derive(Debug)]
pub struct QuicPacket {
    pub header: QuicHeader,
    pub payload: Option<Vec<QuicFrame>>,
}

impl QuicPacket {
    pub fn from_bytes(buf: &Vec<u8>) -> Result<QuicPacket> {
        let mut reader = Cursor::new(buf);
        let first_byte = reader.read_uint::<BigEndian>(1)? as u8;

        if first_byte & 0x80 != 0 { // Long Header
            let packet_type = match PacketType::from_bits(first_byte & 0x7f) {
                Some(pt) => pt,
                None => return Err(QuicError::ParseError)
            };

            let connection_id = reader.read_u64::<BigEndian>()?;
            let packet_number = reader.read_u32::<BigEndian>()?;
            let version = reader.read_u32::<BigEndian>()?;

            if version == 0 {
                return Err(QuicError::ParseError)
            }

            let mut payload_bytes = Vec::new();
            let _ = reader.read_to_end(&mut payload_bytes);

            let frames = QuicPacket::parse_decrypted_payload(payload_bytes.as_slice())?;

            return Ok(QuicPacket {
                header: QuicHeader::Long(LongHeader {
                    packet_type: packet_type,
                    connection_id: connection_id,
                    packet_number: packet_number,
                    version: version,
                }),
                payload: Some(frames)
            })
        } else { // ShortHeader
            let conn_id_flag = first_byte & 0x40 != 0;
            let key_phase_bit = first_byte & 0x20 != 0;
            let packet_type = ShortPacketType::from_bits_truncate(first_byte & 0x1f);

            let mut connection_id: Option<u64> = None;

            if conn_id_flag {
                connection_id = Some(reader.read_u64::<BigEndian>()?);
            }

            let packet_number_size = match packet_type {
                ONE_BYTE => Some(1u8),
                TWO_BYTES => Some(2u8),
                FOUR_BYTES => Some(4u8),
                _ => return Err(QuicError::ParseError)
            }.unwrap();

            let packet_number = match packet_number_size {
                1 => reader.read_uint::<BigEndian>(1)? as u64,
                2 => reader.read_uint::<BigEndian>(2)? as u64,
                4 => reader.read_uint::<BigEndian>(4)? as u64,
                _ => return Err(QuicError::ParseError),
            };

//            let mut payload = Vec::new();
//            let _ = reader.read_to_end(&mut payload);

            // TODO: Decrypt frames and return the payloads.

            return Ok(QuicPacket {
                header: QuicHeader::Short(ShortHeader {
                    key_phase_bit: key_phase_bit,
                    connection_id: connection_id,
                    packet_number: packet_number,
                    conn_id_bit: conn_id_flag,
                    packet_type: packet_type
                }),
                payload: None
            })
        }
    }

    pub fn as_bytes(&self) -> Result<Vec<u8>> {
        let header_bytes = match self.header {
            QuicHeader::Short(ref header) => header.as_bytes(),
            QuicHeader::Long(ref header) => header.as_bytes(),
        };

        let packet_bytes;

        if let Some(ref payload) = self.payload {
            let payload_bytes = payload.iter().map(|ref frame| {
                frame.as_bytes()
            })
                .collect::<Vec<_>>()
                .concat();

            packet_bytes = [header_bytes, payload_bytes].concat();
        } else {
            packet_bytes = header_bytes;
        }

        if packet_bytes.len() > 1232 {
            return Err(QuicError::PacketTooLarge);
        }

        Ok(packet_bytes)
    }

    pub fn parse_decrypted_payload(buf: &[u8]) -> Result<Vec<QuicFrame>> {
        let mut frames: Vec<QuicFrame> = Vec::new();

        let mut position = 0;
        loop {
            let frame_len = QuicFrame::frame_length(&buf[position..])?;
            let frame_end = position + frame_len;

            let frame = QuicFrame::from_bytes(&buf[position..frame_end])?;

            position += frame_len;

            frames.push(frame);

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

        Ok(frames)
    }
}

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

    #[test]
    fn parse_decrypted_payload_1() {
        let reason = "Terrible connection!";
        let frames = vec![
            QuicFrame::ConnectionClose(frames::connection_close_frame::ConnectionCloseFrame {
                error_code: 29,
                reason_length: reason.len() as u16,
                reason_phrase: Some(reason.to_string()),
            }),
            QuicFrame::MaxStreamData(frames::max_stream_data_frame::MaxStreamDataFrame {
                stream_id: 20099 as u32,
                max_stream_data: 290 as u64,
            }),
        ];

        let mut bytes = Vec::new();

        for frame in &frames {
            let frame_bytes = frame.as_bytes();
            bytes.extend(frame_bytes);
        }

        let parsed_frames = QuicPacket::parse_decrypted_payload(&bytes).unwrap();

        assert_eq!(&frames, &parsed_frames);
    }
}

<|endoftext|>


<commit_before>pub enum Entry {
  Entity {id: String, value: String}
}

pub enum Value {
  Str(String)
}

pub struct Parser<'a> {
  source: std::str::Chars<'a>,
  ch: Option<char>,
  pos: u8
}

impl<'a> Parser<'a> {
  pub fn new(source: &'a str) -> Parser<'a> {
    Parser {
      source: source.chars(),
      ch: None,
      pos: 0
    }
  }

  fn bump(&mut self) {
    self.ch = self.source.next();

    self.pos += 1;
  }

  fn ch_is(&self, ch: char) -> bool {
    self.ch == Some(ch)
  }

  fn parse_whitespace(&mut self) {
    while self.ch_is(' ') ||
          self.ch_is('\n') ||
          self.ch_is('\t') ||
          self.ch_is('\r') { self.bump(); }
  }

  pub fn parse(&mut self) -> Vec<Entry> {
    let mut entries: Vec<Entry> = Vec::new();
    self.bump();

    loop {
      self.parse_whitespace();
      let ch = match self.ch {
        Some(ch) => ch,
        None => { break; }
      };

      if ch == '<' {
        entries.push(self.parse_entry());
        break;
      }
    }
    entries
  }

  fn parse_entry(&mut self) -> Entry {
    let id = self.parse_identifier();
    match self.ch {
      Some(_) => return self.parse_entity(id),
      None => panic!()
    };
  }

  fn parse_entity(&mut self, id: String) -> Entry {
    if !self.ch_is(' ') {
      panic!();
    }
    self.parse_whitespace();
    let value = self.parse_value();
    Entry::Entity{id: id, value:value}
  }

  fn parse_identifier(&mut self) -> String {
    let mut id = String::new();

    loop {
      self.bump();
      let ch = match self.ch {
        Some(c) => c,
        None => break,
      };

      match ch {
        'a'...'z' | 'A'...'Z' | '0'...'9' | '_' => id.push(ch),
        _ => break,
      }
    }

    id
  }

  fn parse_value(&mut self) -> String {
    match self.ch {
      Some('"') | Some('\'') => self.parse_string(),
      _ => panic!()
    }
  }

  fn parse_string(&mut self) -> String {
    let mut s = String::new();
    let quote = self.ch.unwrap();

    loop {
      self.bump();
      match self.ch {
        Some(c) if c == quote => { self.bump(); break },
        Some(c) => s.push(c),
        None => panic!()
      }
    }
    s
  }
}

fn main() {
  //let v: std::str::Chars<'a> = "abc åäö".chars();
  let mut parser = Parser::new("<entity1 \"foo\">");
  let mut entries = parser.parse();

  let entry1 = entries.pop();
  let (id, value) = match entry1 {
    Some(Entry::Entity{id, value}) => (id.clone(), value.clone()),
    None => ("".to_string(), "".to_string())
  };

  println!("The result id is {}", id);
  println!("The result value is {}", value);

}
<commit_msg>Handle many entities and loop in the right order<commit_after>pub enum Entry {
  Entity {id: String, value: String}
}

pub enum Value {
  Str(String)
}

pub struct Parser<'a> {
  source: std::str::Chars<'a>,
  ch: Option<char>,
  pos: u8
}

impl<'a> Parser<'a> {
  pub fn new(source: &'a str) -> Parser<'a> {
    Parser {
      source: source.chars(),
      ch: None,
      pos: 0
    }
  }

  fn bump(&mut self) {
    self.ch = self.source.next();

    self.pos += 1;
  }

  fn ch_is(&self, ch: char) -> bool {
    self.ch == Some(ch)
  }

  fn parse_whitespace(&mut self) {
    while self.ch_is(' ') ||
          self.ch_is('\n') ||
          self.ch_is('\t') ||
          self.ch_is('\r') { self.bump(); }
  }

  pub fn parse(&mut self) -> Vec<Entry> {
    let mut entries: Vec<Entry> = Vec::new();
    self.bump();

    loop {
      self.parse_whitespace();
      let ch = match self.ch {
        Some(ch) => ch,
        None => break
      };

      if ch == '<' {
        entries.push(self.parse_entry());
      }
    }
    entries
  }

  fn parse_entry(&mut self) -> Entry {
    let id = self.parse_identifier();
    let val = match self.ch {
      Some(_) => self.parse_entity(id),
      None => panic!()
    };

    self.parse_whitespace();
    if !self.ch_is('>') {
      panic!();
    }
    self.bump();
    val
  }

  fn parse_entity(&mut self, id: String) -> Entry {
    if !self.ch_is(' ') {
      panic!();
    }
    self.parse_whitespace();
    let value = self.parse_value();
    Entry::Entity{id: id, value:value}
  }

  fn parse_identifier(&mut self) -> String {
    let mut id = String::new();

    loop {
      self.bump();
      let ch = match self.ch {
        Some(c) => c,
        None => break,
      };

      match ch {
        'a'...'z' | 'A'...'Z' | '0'...'9' | '_' => id.push(ch),
        _ => break,
      }
    }

    id
  }

  fn parse_value(&mut self) -> String {
    match self.ch {
      Some('"') | Some('\'') => self.parse_string(),
      _ => panic!()
    }
  }

  fn parse_string(&mut self) -> String {
    let mut s = String::new();
    let quote = self.ch.unwrap();

    loop {
      self.bump();
      match self.ch {
        Some(c) if c == quote => { self.bump(); break },
        Some(c) => s.push(c),
        None => panic!()
      }
    }
    s
  }
}

fn read_file() -> String {
  let s = "<entity1 \"foo\"> <entity2 \"foo2\">".to_string();
  return s
}

fn main() {
  let source = read_file();
  let mut parser = Parser::new(source.trim());
  let mut entries = parser.parse();

  loop {
    if entries.is_empty() {
      break;
    }
    let entry1 = Some(entries.remove(0));
    let (id, value) = match entry1 {
      Some(Entry::Entity{id, value}) => (id.clone(), value.clone()),
      None => break
    };

    println!("The result id is {}", id);
    println!("The result value is {}", value);
  }
}
<|endoftext|>