<commit_before>//! # C API for rav1e
//!
//! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/)
//! encoder written in [Rust](https://rust-lang.org)
//!
//! This is the C-compatible API

extern crate rav1e;
extern crate libc;

use std::slice;
use std::sync::Arc;

use std::ffi::CStr;
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::c_int;

use libc::size_t;
use libc::ptrdiff_t;

/// Raw video Frame
///
/// It can be allocated throught rav1e_frame_new(), populated using rav1e_frame_fill_plane()
/// and freed using rav1e_frame_unref().
pub struct Frame(Arc<rav1e::Frame<u16>>);

type EncoderStatus=rav1e::EncoderStatus;

/// Encoder configuration
///
/// Instantiate it using rav1e_config_default() and fine-tune it using
/// rav1e_config_parse().
///
/// Use rav1e_config_unref() to free its memory.
pub struct Config {
    cfg: rav1e::Config,
    last_err: Option<EncoderStatus>,
}

/// Encoder context
///
/// Contains the encoding state, it is created by rav1e_context_new() using an
/// Encoder configuration.
///
/// Use rav1e_context_unref() to free its memory.
pub struct Context {
    ctx: rav1e::Context<u16>,
    last_err: Option<EncoderStatus>,
}

type FrameType = rav1e::FrameType;

/// Encoded Packet
///
/// The encoded packets are retrieved using rav1e_receive_packet().
///
/// Use rav1e_packet_unref() to free its memory.
#[repr(C)]
pub struct Packet {
    /// Encoded data buffer
    pub data: *const u8,
    /// Encoded data buffer size
    pub len: size_t,
    /// Frame sequence number
    pub number: u64,
    /// Frame type
    pub frame_type: FrameType,
}

type ChromaSamplePosition=rav1e::ChromaSamplePosition;
type ChromaSampling=rav1e::ChromaSampling;
type MatrixCoefficients=rav1e::MatrixCoefficients;
type ColorPrimaries=rav1e::ColorPrimaries;
type TransferCharacteristics=rav1e::TransferCharacteristics;
type Rational=rav1e::Rational;

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_default() -> *mut Config {
    let cfg = rav1e::Config {
        enc: rav1e::EncoderConfig::default(),
        threads: 0,
    };

    let c = Box::new(Config {
        cfg,
        last_err: None,
    });

    Box::into_raw(c)
}

/// Set color properties of the stream.
///
/// Supported values are defined by the enum types
/// RaMatrixCoefficients, RaColorPrimaries, and RaTransferCharacteristics
/// respectively.
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_color_description(cfg: *mut Config,
                                                            matrix: MatrixCoefficients,
                                                            primaries: ColorPrimaries,
                                                            transfer: TransferCharacteristics
) -> c_int {
    (*cfg).cfg.enc.color_description = Some(rav1e::ColorDescription {
        matrix_coefficients: matrix,
        color_primaries: primaries,
        transfer_characteristics: transfer,
    });

    if (*cfg).cfg.enc.color_description.is_some() { 0 } else { -1 }
}

/// Set the content light level information for HDR10 streams.
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_content_light(cfg: *mut Config,
                                                        max_content_light_level: u16,
                                                        max_frame_average_light_level: u16
) -> c_int {
    (*cfg).cfg.enc.content_light = Some(rav1e::ContentLight {
        max_content_light_level,
        max_frame_average_light_level,
    });

    if (*cfg).cfg.enc.content_light.is_some() { 0 } else { -1 }
}

/// Set the mastering display information for HDR10 streams.
///
/// primaries and white_point arguments are RaPoint, containing 0.16 fixed point values.
/// max_luminance is a 24.8 fixed point value.
/// min_luminance is a 18.14 fixed point value.
///
/// Returns a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_mastering_display(cfg: *mut Config,
                                                            primaries: [rav1e::Point; 3],
                                                            white_point: rav1e::Point,
                                                            max_luminance: u32,
                                                            min_luminance: u32
) -> c_int {
    (*cfg).cfg.enc.mastering_display = Some(rav1e::MasteringDisplay {
        primaries,
        white_point,
        max_luminance,
        min_luminance,
    });

    if (*cfg).cfg.enc.mastering_display.is_some() { 0 } else { -1 }
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_unref(cfg: *mut Config) {
    if !cfg.is_null() {
        let _ = Box::from_raw(cfg);
    }
}

unsafe fn option_match(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char
) -> Result<(), ()> {
    let key = CStr::from_ptr(key).to_str().map_err(|_| ())?;
    let value = CStr::from_ptr(value).to_str().map_err(|_| ())?;
    let enc = &mut(*cfg).cfg.enc;

    match key {
        "width" => enc.width = value.parse().map_err(|_| ())?,
        "height" => enc.height = value.parse().map_err(|_| ())?,
        "speed" => enc.speed_settings = rav1e::SpeedSettings::from_preset(value.parse().map_err(|_| ())?),

        "threads" => (*cfg).cfg.threads = value.parse().map_err(|_| ())?,

        "tune" => enc.tune = value.parse().map_err(|_| ())?,
        "quantizer" => enc.quantizer = value.parse().map_err(|_| ())?,

        "key_frame_interval" => enc.max_key_frame_interval = value.parse().map_err(|_| ())?,
        "min_key_frame_interval" => enc.min_key_frame_interval = value.parse().map_err(|_| ())?,
        "low_latency" => enc.low_latency = value.parse().map_err(|_| ())?,

        _ => return Err(())
    }

    Ok(())
}

/// Set a configuration parameter using its key and value as string.
///
/// Available keys and values
/// - "quantizer": 0-255, default 100
/// - "speed": 0-10, default 3
/// - "tune": "psnr"-"psychovisual", default "psnr"
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char,
) -> c_int {
    if option_match(cfg, key, value) == Ok(()) { 0 } else { -1 }
}

/// Set a configuration parameter using its key and value as integer.
///
/// Available keys and values are the same as rav1e_config_parse()
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse_int(
    cfg: *mut Config,
    key: *const c_char,
    value: c_int,
) -> c_int {
    let val = CString::new(value.to_string()).unwrap();
    if option_match(cfg, key, val.as_ptr()) == Ok(()) { 0 } else { -1 }
}

/// Generate a new encoding context from a populated encoder configuration
///
/// Multiple contexts can be generated through it.
#[no_mangle]
pub unsafe extern "C" fn rav1e_context_new(cfg: *const Config) -> *mut Context {
    let ctx = Context {
        ctx: (*cfg).cfg.new_context(),
        last_err: None,
    };

    Box::into_raw(Box::new(ctx))
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_context_unref(ctx: *mut Context) {
    if !ctx.is_null() {
        let _ = Box::from_raw(ctx);
    }
}

/// Produce a new frame from the encoding context
///
/// It must be populated using rav1e_frame_fill_plane().
///
/// The frame is reference counted and must be released passing it to rav1e_frame_unref(),
/// see rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_new(ctx: *const Context) -> *mut Frame {
    let f = (*ctx).ctx.new_frame();
    let frame = Box::new(Frame(f));

    Box::into_raw(frame)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_unref(frame: *mut Frame) {
    if !frame.is_null() {
        let _ = Box::from_raw(frame);
    }
}

/// Send the frame for encoding
///
/// The function increases the frame internal reference count and it can be passed multiple
/// times to different rav1e_send_frame().
///
/// Returns:
/// - `0` on success,
/// - `> 0` if the input queue is full
/// - `< 0` on unrecoverable failure
#[no_mangle]
pub unsafe extern "C" fn rav1e_send_frame(ctx: *mut Context, frame: *const Frame) -> c_int {
    let frame = if frame.is_null() {
        None
    } else {
        Some((*frame).0.clone())
    };

    (*ctx)
        .ctx
        .send_frame(frame)
        .map(|_v| {
            (*ctx).last_err = None;
            0
        }).unwrap_or_else(|e| {
            use rav1e::EncoderStatus::*;
            (*ctx).last_err = Some(e);
            match e {
                EnoughData => 1,
                NeedMoreData | NeedMoreFrames => unreachable!(),
                _ => -1,
            }
        })
}

/// Receive encoded data
///
/// Returns:
/// - `0` on success
/// - `> 0` if additional frame data is required
/// - `< 0` on unrecoverable failure
#[no_mangle]
pub unsafe extern "C" fn rav1e_receive_packet(
    ctx: *mut Context,
    pkt: *mut *mut Packet,
) -> c_int {
    (*ctx)
        .ctx
        .receive_packet()
        .map(|p| {
            (*ctx).last_err = None;
            let rav1e::Packet { data, number, frame_type, .. } = p;
            let len  = data.len();
            let data = Box::into_raw(data.into_boxed_slice()) as *const u8;
            let packet = Packet {
                data,
                len,
                number,
                frame_type,
            };
            *pkt = Box::into_raw(Box::new(packet));
            0
        }).unwrap_or_else(|e| {
            use rav1e::EncoderStatus::*;
            (*ctx).last_err = Some(e);
            match e {
                NeedMoreData |
                    NeedMoreFrames => 1,
                EnoughData => unreachable!(),
                _ => -1,
            }
        })
}

#[no_mangle]
pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) {
    if !pkt.is_null() {
        let pkt = Box::from_raw(pkt);
        let _ = Box::from_raw(pkt.data as *mut u8);
    }
}

/// Produce a sequence header matching the current encoding context
///
/// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
///
/// Use rav1e_container_sequence_header_unref() to free it.
#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header(ctx: *mut Context, buf_size: *mut size_t) -> *mut u8 {
    let buf = (*ctx).ctx.container_sequence_header();

    *buf_size = buf.len();
    Box::into_raw(buf.into_boxed_slice()) as *mut u8
}

#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header_unref(sequence: *mut u8) {
    if !sequence.is_null() {
        let _ = Box::from_raw(sequence);
    }
}

/// Fill a frame plane
///
/// Currently the frame contains 3 planes, the first is luminance followed by
/// chrominance.
///
/// The data is copied and this function has to be called for each plane.
///
/// frame: A frame provided by rav1e_frame_new()
/// plane: The index of the plane starting from 0
/// data: The data to be copied
/// data_len: Lenght of the buffer
/// stride: Plane line in bytes, including padding
/// bytewidth: Number of bytes per component, either 1 or 2
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_fill_plane(
    frame: *mut Frame,
    plane: c_int,
    data: *const u8,
    data_len: size_t,
    stride: ptrdiff_t,
    bytewidth: c_int,
) {
    let f = &mut (*frame).0;
    let input = Arc::make_mut(f);
    let data_slice = slice::from_raw_parts(data, data_len as usize);

    input.planes[plane as usize].copy_from_raw_u8(data_slice, stride as usize, bytewidth as usize);
}
<commit_msg>crav1e: Update to the current API<commit_after>//! # C API for rav1e
//!
//! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/)
//! encoder written in [Rust](https://rust-lang.org)
//!
//! This is the C-compatible API

extern crate rav1e;
extern crate libc;

use std::slice;
use std::sync::Arc;

use std::ffi::CStr;
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::c_int;

use libc::size_t;
use libc::ptrdiff_t;

/// Raw video Frame
///
/// It can be allocated throught rav1e_frame_new(), populated using rav1e_frame_fill_plane()
/// and freed using rav1e_frame_unref().
pub struct Frame(Arc<rav1e::Frame<u16>>);

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub enum EncoderStatus {
    /// Normal operation
    Success = 0,
    /// The encoder needs more data to produce an output Packet
    /// May be emitted by `Context::receive_packet`  when frame reordering is enabled.
    NeedMoreData,
    /// There are enough Frames queue
    /// May be emitted by `Context::send_frame` when the input queue is constrained
    EnoughData,
    /// The encoder already produced the number of frames requested
    /// May be emitted by `Context::receive_packet` after a flush request had been processed
    /// or the frame limit had been reached.
    LimitReached,
    /// Generic fatal error
    Failure = -1,
}

impl From<Option<rav1e::EncoderStatus>> for EncoderStatus {
    fn from(status: Option<rav1e::EncoderStatus>) -> Self {
        match status {
            None => EncoderStatus::Success,
            Some(s) => match s {
                rav1e::EncoderStatus::NeedMoreData => EncoderStatus::NeedMoreData,
                rav1e::EncoderStatus::EnoughData => EncoderStatus::EnoughData,
                rav1e::EncoderStatus::LimitReached => EncoderStatus::LimitReached,
                rav1e::EncoderStatus::Failure => EncoderStatus::Failure,
            }
        }
    }
}

/// Encoder configuration
///
/// Instantiate it using rav1e_config_default() and fine-tune it using
/// rav1e_config_parse().
///
/// Use rav1e_config_unref() to free its memory.
pub struct Config {
    cfg: rav1e::Config,
}

/// Encoder context
///
/// Contains the encoding state, it is created by rav1e_context_new() using an
/// Encoder configuration.
///
/// Use rav1e_context_unref() to free its memory.
pub struct Context {
    ctx: rav1e::Context<u16>,
    last_err: Option<rav1e::EncoderStatus>,
}

type FrameType = rav1e::FrameType;

/// Encoded Packet
///
/// The encoded packets are retrieved using rav1e_receive_packet().
///
/// Use rav1e_packet_unref() to free its memory.
#[repr(C)]
pub struct Packet {
    /// Encoded data buffer
    pub data: *const u8,
    /// Encoded data buffer size
    pub len: size_t,
    /// Frame sequence number
    pub number: u64,
    /// Frame type
    pub frame_type: FrameType,
}

type ChromaSamplePosition=rav1e::ChromaSamplePosition;
type ChromaSampling=rav1e::ChromaSampling;
type MatrixCoefficients=rav1e::MatrixCoefficients;
type ColorPrimaries=rav1e::ColorPrimaries;
type TransferCharacteristics=rav1e::TransferCharacteristics;
type Rational=rav1e::Rational;

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_default() -> *mut Config {
    let cfg = rav1e::Config {
        enc: rav1e::EncoderConfig::default(),
        threads: 0,
    };

    let c = Box::new(Config {
        cfg,
    });

    Box::into_raw(c)
}

/// Set color properties of the stream.
///
/// Supported values are defined by the enum types
/// RaMatrixCoefficients, RaColorPrimaries, and RaTransferCharacteristics
/// respectively.
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_color_description(cfg: *mut Config,
                                                            matrix: MatrixCoefficients,
                                                            primaries: ColorPrimaries,
                                                            transfer: TransferCharacteristics
) -> c_int {
    (*cfg).cfg.enc.color_description = Some(rav1e::ColorDescription {
        matrix_coefficients: matrix,
        color_primaries: primaries,
        transfer_characteristics: transfer,
    });

    if (*cfg).cfg.enc.color_description.is_some() { 0 } else { -1 }
}

/// Set the content light level information for HDR10 streams.
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_content_light(cfg: *mut Config,
                                                        max_content_light_level: u16,
                                                        max_frame_average_light_level: u16
) -> c_int {
    (*cfg).cfg.enc.content_light = Some(rav1e::ContentLight {
        max_content_light_level,
        max_frame_average_light_level,
    });

    if (*cfg).cfg.enc.content_light.is_some() { 0 } else { -1 }
}

/// Set the mastering display information for HDR10 streams.
///
/// primaries and white_point arguments are RaPoint, containing 0.16 fixed point values.
/// max_luminance is a 24.8 fixed point value.
/// min_luminance is a 18.14 fixed point value.
///
/// Returns a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_mastering_display(cfg: *mut Config,
                                                            primaries: [rav1e::Point; 3],
                                                            white_point: rav1e::Point,
                                                            max_luminance: u32,
                                                            min_luminance: u32
) -> c_int {
    (*cfg).cfg.enc.mastering_display = Some(rav1e::MasteringDisplay {
        primaries,
        white_point,
        max_luminance,
        min_luminance,
    });

    if (*cfg).cfg.enc.mastering_display.is_some() { 0 } else { -1 }
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_unref(cfg: *mut Config) {
    if !cfg.is_null() {
        let _ = Box::from_raw(cfg);
    }
}

unsafe fn option_match(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char
) -> Result<(), ()> {
    let key = CStr::from_ptr(key).to_str().map_err(|_| ())?;
    let value = CStr::from_ptr(value).to_str().map_err(|_| ())?;
    let enc = &mut(*cfg).cfg.enc;

    match key {
        "width" => enc.width = value.parse().map_err(|_| ())?,
        "height" => enc.height = value.parse().map_err(|_| ())?,
        "speed" => enc.speed_settings = rav1e::SpeedSettings::from_preset(value.parse().map_err(|_| ())?),

        "threads" => (*cfg).cfg.threads = value.parse().map_err(|_| ())?,

        "tune" => enc.tune = value.parse().map_err(|_| ())?,
        "quantizer" => enc.quantizer = value.parse().map_err(|_| ())?,

        "key_frame_interval" => enc.max_key_frame_interval = value.parse().map_err(|_| ())?,
        "min_key_frame_interval" => enc.min_key_frame_interval = value.parse().map_err(|_| ())?,
        "low_latency" => enc.low_latency = value.parse().map_err(|_| ())?,

        _ => return Err(())
    }

    Ok(())
}

/// Set a configuration parameter using its key and value as string.
///
/// Available keys and values
/// - "quantizer": 0-255, default 100
/// - "speed": 0-10, default 3
/// - "tune": "psnr"-"psychovisual", default "psnr"
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char,
) -> c_int {
    if option_match(cfg, key, value) == Ok(()) { 0 } else { -1 }
}

/// Set a configuration parameter using its key and value as integer.
///
/// Available keys and values are the same as rav1e_config_parse()
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse_int(
    cfg: *mut Config,
    key: *const c_char,
    value: c_int,
) -> c_int {
    let val = CString::new(value.to_string()).unwrap();
    if option_match(cfg, key, val.as_ptr()) == Ok(()) { 0 } else { -1 }
}

/// Generate a new encoding context from a populated encoder configuration
///
/// Multiple contexts can be generated through it.
#[no_mangle]
pub unsafe extern "C" fn rav1e_context_new(cfg: *const Config) -> *mut Context {
    let ctx = Context {
        ctx: (*cfg).cfg.new_context(),
        last_err: None,
    };

    Box::into_raw(Box::new(ctx))
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_context_unref(ctx: *mut Context) {
    if !ctx.is_null() {
        let _ = Box::from_raw(ctx);
    }
}

/// Produce a new frame from the encoding context
///
/// It must be populated using rav1e_frame_fill_plane().
///
/// The frame is reference counted and must be released passing it to rav1e_frame_unref(),
/// see rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_new(ctx: *const Context) -> *mut Frame {
    let f = (*ctx).ctx.new_frame();
    let frame = Box::new(Frame(f));

    Box::into_raw(frame)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_unref(frame: *mut Frame) {
    if !frame.is_null() {
        let _ = Box::from_raw(frame);
    }
}

/// Send the frame for encoding
///
/// The function increases the frame internal reference count and it can be passed multiple
/// times to different rav1e_send_frame().
///
/// Returns:
/// - `0` on success,
/// - `> 0` if the input queue is full
/// - `< 0` on unrecoverable failure
#[no_mangle]
pub unsafe extern "C" fn rav1e_send_frame(ctx: *mut Context, frame: *const Frame) -> EncoderStatus {
    let frame = if frame.is_null() {
        None
    } else {
        Some((*frame).0.clone())
    };

    let ret = (*ctx)
        .ctx
        .send_frame(frame)
        .map(|_v| {
            None
        }).unwrap_or_else(|e| {
            Some(e)
        });

    (*ctx).last_err = ret;

    ret.into()
}

/// Return the last encoder status
#[no_mangle]
pub unsafe extern "C" fn rav1e_last_status(ctx: *const Context) -> EncoderStatus {
    (*ctx).last_err.into()
}

/// Return a string matching the EncooderStatus variant.
#[no_mangle]
pub unsafe extern "C" fn rav1e_status_to_str(status: EncoderStatus) -> *mut c_char {
    let status = format!("{:?}", status);
    let cptr = CString::new(status).unwrap().as_ptr();

    libc::strdup(cptr)
}

/// Receive encoded data
///
/// Returns:
/// - `0` on success
/// - `> 0` if additional frame data is required
/// - `< 0` on unrecoverable failure
#[no_mangle]
pub unsafe extern "C" fn rav1e_receive_packet(
    ctx: *mut Context,
    pkt: *mut *mut Packet,
) -> EncoderStatus {
    let ret = (*ctx)
        .ctx
        .receive_packet()
        .map(|p| {
            let rav1e::Packet { data, number, frame_type, .. } = p;
            let len  = data.len();
            let data = Box::into_raw(data.into_boxed_slice()) as *const u8;
            let packet = Packet {
                data,
                len,
                number,
                frame_type,
            };
            *pkt = Box::into_raw(Box::new(packet));
            None
        }).unwrap_or_else(|e| {
            Some(e)
        });

    (*ctx).last_err = ret;

    ret.into()
}

#[no_mangle]
pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) {
    if !pkt.is_null() {
        let pkt = Box::from_raw(pkt);
        let _ = Box::from_raw(pkt.data as *mut u8);
    }
}

/// Produce a sequence header matching the current encoding context
///
/// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
///
/// Use rav1e_container_sequence_header_unref() to free it.
#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header(ctx: *mut Context, buf_size: *mut size_t) -> *mut u8 {
    let buf = (*ctx).ctx.container_sequence_header();

    *buf_size = buf.len();
    Box::into_raw(buf.into_boxed_slice()) as *mut u8
}

#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header_unref(sequence: *mut u8) {
    if !sequence.is_null() {
        let _ = Box::from_raw(sequence);
    }
}

/// Fill a frame plane
///
/// Currently the frame contains 3 planes, the first is luminance followed by
/// chrominance.
///
/// The data is copied and this function has to be called for each plane.
///
/// frame: A frame provided by rav1e_frame_new()
/// plane: The index of the plane starting from 0
/// data: The data to be copied
/// data_len: Lenght of the buffer
/// stride: Plane line in bytes, including padding
/// bytewidth: Number of bytes per component, either 1 or 2
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_fill_plane(
    frame: *mut Frame,
    plane: c_int,
    data: *const u8,
    data_len: size_t,
    stride: ptrdiff_t,
    bytewidth: c_int,
) {
    let f = &mut (*frame).0;
    let input = Arc::make_mut(f);
    let data_slice = slice::from_raw_parts(data, data_len as usize);

    input.planes[plane as usize].copy_from_raw_u8(data_slice, stride as usize, bytewidth as usize);
}
<|endoftext|>


<commit_before>use std::slice;
use cose::decoder::decode_signature;

unsafe fn from_raw(ptr: *const u8, len: usize) -> Vec<u8> {
    slice::from_raw_parts(ptr, len).to_vec()
}

type VerifyCallback = extern "C" fn(*const u8, /* payload */
                                    usize, /* payload len */
                                    *const u8, /* cert_chain */
                                    usize, /* cert_chain len */
                                    *const u8, /* signare cert */
                                    usize /*signare cert len */) -> bool;

#[no_mangle]
pub unsafe extern "C" fn verify_signature_with_cpp(
    payload: *const u8,
    payload_len: usize,
    cose_signature: *const u8,
    cose_signature_len: usize,
    verify_callback: VerifyCallback,
) -> bool {
    if payload.is_null() || cose_signature.is_null() || payload_len == 0 ||
        cose_signature_len == 0
    {
        return false;
    }

    // Build Rust variables from C parameters.
    let payload = from_raw(payload, payload_len);
    let cose_signature = from_raw(cose_signature, cose_signature_len);

    // Parse the incoming signature.
    let cose_signatures = decode_signature(cose_signature, &payload);
    let cose_signatures = match cose_signatures {
        Ok(signature) => signature,
        Err(_) => Vec::new(),
    };
    if cose_signatures.len() < 1 {
        return false;
    }
    // let signature_type = &cose_signatures[0].signature_type;
    // let signature_algorithm = match *signature_type {
    //     CoseSignatureType::ES256 => nss::SignatureAlgorithm::ES256,
    //     _ => return false,
    // };
    // let signature_bytes = &cose_signatures[0].signature;
    let real_payload = &cose_signatures[0].to_verify;

    // Call callback to verify the parsed signatures.
    let result = verify_callback(
        real_payload.as_ptr(),
        real_payload.len(),
        cose_signatures[0].certs.as_ptr(),
        cose_signatures[0].certs.len(),
        cose_signatures[0].signer_cert.as_ptr(),
        cose_signatures[0].signer_cert.len(),
    );

    result
}
<commit_msg>rustfmt<commit_after>use std::slice;
use cose::decoder::decode_signature;

unsafe fn from_raw(ptr: *const u8, len: usize) -> Vec<u8> {
    slice::from_raw_parts(ptr, len).to_vec()
}

type VerifyCallback = extern "C" fn(*const u8, /* payload */
                                    usize, /* payload len */
                                    *const u8, /* cert_chain */
                                    usize, /* cert_chain len */
                                    *const u8, /* signare cert */
                                    usize /*signare cert len */)
                                    -> bool;

#[no_mangle]
pub unsafe extern "C" fn verify_signature_with_cpp(
    payload: *const u8,
    payload_len: usize,
    cose_signature: *const u8,
    cose_signature_len: usize,
    verify_callback: VerifyCallback,
) -> bool {
    if payload.is_null() || cose_signature.is_null() || payload_len == 0 ||
        cose_signature_len == 0
    {
        return false;
    }

    // Build Rust variables from C parameters.
    let payload = from_raw(payload, payload_len);
    let cose_signature = from_raw(cose_signature, cose_signature_len);

    // Parse the incoming signature.
    let cose_signatures = decode_signature(cose_signature, &payload);
    let cose_signatures = match cose_signatures {
        Ok(signature) => signature,
        Err(_) => Vec::new(),
    };
    if cose_signatures.len() < 1 {
        return false;
    }
    // let signature_type = &cose_signatures[0].signature_type;
    // let signature_algorithm = match *signature_type {
    //     CoseSignatureType::ES256 => nss::SignatureAlgorithm::ES256,
    //     _ => return false,
    // };
    // let signature_bytes = &cose_signatures[0].signature;
    let real_payload = &cose_signatures[0].to_verify;

    // Call callback to verify the parsed signatures.
    let result = verify_callback(
        real_payload.as_ptr(),
        real_payload.len(),
        cose_signatures[0].certs.as_ptr(),
        cose_signatures[0].certs.len(),
        cose_signatures[0].signer_cert.as_ptr(),
        cose_signatures[0].signer_cert.len(),
    );

    result
}
<|endoftext|>


<commit_before>use na;

use traits::Number;

/// Returns the maximum among three values.
pub fn max3_scalar<N: Number>(a: N, b: N, c: N) -> N {
    na::sup(&na::sup(&a, &b), &c)
}

/// Returns the maximum among four values.
pub fn max4_scalar<N: Number>(a: N, b: N, c: N, d: N) -> N {
    na::sup(&na::sup(&a, &b), &na::sup(&c, &d))
}

/// Returns the minimum among three values.
pub fn min3_scalar<N: Number>(a: N, b: N, c: N) -> N {
    na::inf(&na::inf(&a, &b), &c)
}

/// Returns the minimum among four values.
pub fn min4_scalar<N: Number>(a: N, b: N, c: N, d: N) -> N {
    na::inf(&na::inf(&a, &b), &na::inf(&c, &d))
}<commit_msg>Add see also + examples for scalar min/max.<commit_after>use na;

use traits::Number;

/// Returns the maximum among three values.
///
/// # Examples:
///
/// ```
/// # use nalgebra_glm as glm;
/// assert_eq!(3.0, glm::max3_scalar(1.0, 2.0, 3.0));
/// assert_eq!(2, glm::max3_scalar(0, 1, 2));
/// ```
///
/// # See also:
///
/// * [`max4_scalar`](fn.max4_scalar.html)
/// * [`min3_scalar`](fn.min3_scalar.html)
/// * [`min4_scalar`](fn.min4_scalar.html)
pub fn max3_scalar<N: Number>(a: N, b: N, c: N) -> N {
    na::sup(&na::sup(&a, &b), &c)
}

/// Returns the maximum among four values.
///
/// # Examples:
///
/// ```
/// # use nalgebra_glm as glm;
/// assert_eq!(4.0, glm::max4_scalar(2.0, 4.0, 1.0, 3.0));
/// assert_eq!(7, glm::max4_scalar(1, 0, 7, 2));
/// ```
///
/// # See also:
///
/// * [`max3_scalar`](fn.max3_scalar.html)
/// * [`min3_scalar`](fn.min3_scalar.html)
/// * [`min4_scalar`](fn.min4_scalar.html)
pub fn max4_scalar<N: Number>(a: N, b: N, c: N, d: N) -> N {
    na::sup(&na::sup(&a, &b), &na::sup(&c, &d))
}

/// Returns the minimum among three values.
///
/// # Examples:
///
/// ```
/// # use nalgebra_glm as glm;
/// assert_eq!(1.0, glm::min3_scalar(1.0, 2.0, 3.0));
/// assert_eq!(0, glm::min3_scalar(0, 1, 2));
/// ```
///
/// # See also:
///
/// * [`max3_scalar`](fn.max3_scalar.html)
/// * [`max4_scalar`](fn.max4_scalar.html)
/// * [`min4_scalar`](fn.min4_scalar.html)
pub fn min3_scalar<N: Number>(a: N, b: N, c: N) -> N {
    na::inf(&na::inf(&a, &b), &c)
}

/// Returns the minimum among four values.
///
/// # Examples:
///
/// ```
/// # use nalgebra_glm as glm;
/// assert_eq!(1.0, glm::min4_scalar(2.0, 4.0, 1.0, 3.0));
/// assert_eq!(0, glm::min4_scalar(1, 0, 7, 2));
/// ```
///
/// # See also:
///
/// * [`max3_scalar`](fn.max3_scalar.html)
/// * [`max4_scalar`](fn.max4_scalar.html)
/// * [`min3_scalar`](fn.min3_scalar.html)
pub fn min4_scalar<N: Number>(a: N, b: N, c: N, d: N) -> N {
    na::inf(&na::inf(&a, &b), &na::inf(&c, &d))
}
<|endoftext|>


<commit_before>use winapi;
use user32;
use kernel32;
use gdi32;

use winapi::{UINT, WPARAM, LPARAM};
use winapi::windef::HWND;
use winapi::winuser::WNDCLASSEXW;

use std::ptr;
use std::mem;
use std::ops::Drop;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::path::PathBuf;
use std::cell::RefCell;
use std::sync::mpsc::{Sender, Receiver};

use num::FromPrimitive;

use config::WindowConfig;
use event::{Event, VKeyCode};

#[derive(Clone)]
pub struct InternalWindow( pub HWND );

unsafe impl Send for InternalWindow {}
unsafe impl Sync for InternalWindow {}

impl InternalWindow {
    #[inline]
    pub fn new<'a>(name: String, config: WindowConfig, owner: Option<HWND>) -> InternalWindow {
        unsafe {
            let class_name = register_window_class();

            let window_name = osstr(&name);

            let (style, style_ex) = {
                use config::InitialState::*;

                let mut style = winapi::WS_SYSMENU;
                let mut style_ex = 0;

                if !config.borderless && !config.tool_window {
                    style |= winapi::WS_CAPTION;

                    if config.resizable {
                        style |= winapi::WS_SIZEBOX;

                        if config.maximizable {
                            style |= winapi::WS_MAXIMIZEBOX;
                        }
                    }

                    if config.minimizable {
                        style |= winapi::WS_MINIMIZEBOX;
                    }

                    style_ex |= winapi::WS_EX_WINDOWEDGE;
                }

                if config.tool_window {
                    style_ex |= winapi::WS_EX_TOOLWINDOW;
                }

                match config.initial_state {
                    Windowed    => (),
                    Minimized   => style |= winapi::WS_MINIMIZE,
                    Maximized   => style |= winapi::WS_MAXIMIZE
                }

                (style, style_ex)
            };

            let size = match config.size {
                Some(s) => {
                    let mut size_rect = winapi::RECT {
                        left: 0,
                        top: 0,
                        right: s.0,
                        bottom: s.1
                    };

                    user32::AdjustWindowRectEx(&mut size_rect, style, 0, style_ex);
                    (size_rect.right - size_rect.left, size_rect.bottom - size_rect.top)
                }

                None => (winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT)
            };

            let window_handle = user32::CreateWindowExW(
                style_ex,
                class_name.as_ptr(),
                window_name.as_ptr() as winapi::LPCWSTR,
                style,
                winapi::CW_USEDEFAULT,
                winapi::CW_USEDEFAULT,
                size.0,
                size.1,
                // This parameter specifies the window's owner. If the window
                // is unowned, then it passes a null pointer to the parameter.
                owner.unwrap_or(ptr::null_mut()),
                ptr::null_mut(),
                kernel32::GetModuleHandleW(ptr::null()),
                ptr::null_mut()
            );

            if window_handle == ptr::null_mut() {
                panic!(format!("Error: {}", ::std::io::Error::last_os_error()));
            }

            // If the window should be borderless, make it borderless
            if config.borderless {
                user32::SetWindowLongW(window_handle, -16, 0);
            }

            if let Some(p) = config.icon {
                let path = wide_path(p).as_ptr();

                // Load the 32x32 icon
                let icon = user32::LoadImageW(ptr::null_mut(), path, winapi::IMAGE_ICON, 32, 32, winapi::LR_LOADFROMFILE);
                if icon != ptr::null_mut() {
                    user32::SendMessageW(window_handle, winapi::WM_SETICON, winapi::ICON_BIG as u64, icon as winapi::LPARAM);
                }
                else {
                    panic!("Could not load 32x32 icon (TODO: Make this not panic)");
                }

                // Load the 16x16 icon
                let icon = user32::LoadImageW(ptr::null_mut(), path, winapi::IMAGE_ICON, 16, 16, winapi::LR_LOADFROMFILE);
                if icon != ptr::null_mut() {
                    user32::SendMessageW(window_handle, winapi::WM_SETICON, winapi::ICON_SMALL as u64, icon as winapi::LPARAM);
                }
                else {
                    panic!("Could not load 16x16 icon (TODO: Make this not panic)");
                }
            }

            InternalWindow( window_handle )
        }
    }

    #[inline]
    pub fn set_title(&self, title: &str) {
        unsafe {
            let title = osstr(title);
            user32::SetWindowTextW(self.0, title.as_ptr());
        }
    }

    #[inline]
    pub fn show(&self) {
        unsafe {
            user32::ShowWindow(self.0, winapi::SW_SHOW);
        }
    }

    #[inline]
    pub fn hide(&self) {
        unsafe {
            user32::ShowWindow(self.0, winapi::SW_HIDE);
        }
    }

    #[inline]
    pub fn enable(&self) {
        unsafe {
            user32::EnableWindow(self.0, winapi::TRUE);
        }
    }

    #[inline]
    pub fn disable(&self) {
        unsafe {
            user32::EnableWindow(self.0, winapi::FALSE);
        }
    }

    #[inline]
    pub fn focus(&self) {
        unsafe {
            // The SetFocus method does not work across threads, but SendMessage does. As
            // such, this sends a message to the corresponding window where the focus is set
            // in the callback, which is executed in the correct thread.
            user32::SendMessageW(self.0, MSG_GAINFOCUS, 0, 0);
        }
    }

    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        unsafe {
            let mut rect = mem::uninitialized();

            match user32::GetWindowRect(self.0, &mut rect) {
                0 => None,
                _ => Some((rect.left as i32, rect.top as i32))
            }
        }
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        unsafe {
            let mut rect = mem::uninitialized();

            match user32::GetClientRect(self.0, &mut rect) {
                0 => None,
                _ => Some(((rect.right - rect.left) as u32,
                           (rect.bottom - rect.top) as u32))
            }
        }
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        unsafe {
            let mut rect = mem::uninitialized();

            match user32::GetWindowRect(self.0, &mut rect) {
                0 => None,
                _ => Some(((rect.right - rect.left) as u32,
                           (rect.bottom - rect.top) as u32))
            }
        }
    }

    #[inline]
    pub fn set_position(&self, x: i32, y: i32) -> Option<()> {
        unsafe {
            let result = user32::SetWindowPos(
                self.0,
                ptr::null_mut(),
                x,
                y,
                0,
                0,
                winapi::SWP_NOSIZE | winapi::SWP_NOZORDER | winapi::SWP_NOACTIVATE
            );

            match result {
                0 => None,
                _ => Some(())
            }
        }
    }

    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) -> Option<()> {
        unsafe {
            let mut rect = winapi::RECT {
                left: 0,
                top: 0,
                right: x as i32,
                bottom: y as i32
            };

            user32::AdjustWindowRectEx(
                &mut rect,
                user32::GetWindowLongW(self.0, -16) as u32, // Get the window's style
                0,
                user32::GetWindowLongW(self.0, -20) as u32  // Get the window's extended style
            );

            let result = user32::SetWindowPos(
                self.0,
                ptr::null_mut(),
                0,
                0,
                rect.right - rect.left,
                rect.bottom - rect.top,
                winapi::SWP_NOMOVE | winapi::SWP_NOZORDER | winapi::SWP_NOACTIVATE
            );

            match result {
                0 => None,
                _ => Some(())
            }
        }
    }

    pub fn kill(&self) {
        unsafe {
            user32::PostMessageW(self.0, winapi::WM_DESTROY, 0, 0);
        }
    }
}

impl Drop for InternalWindow {
    fn drop(&mut self) {
        self.kill();
    }
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name = osstr("Window Class");

    let window_class = WNDCLASSEXW {
        cbSize: mem::size_of::<WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_OWNDC | winapi::CS_VREDRAW | winapi::CS_HREDRAW,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut()
    };
    user32::RegisterClassExW(&window_class);

    class_name
}

thread_local!(pub static CALLBACK_DATA: RefCell<Option<CallbackData>> = RefCell::new(None));

pub struct CallbackData {
    win_vec: Vec<WindowDataIntern>,
    win_sender: Sender<WindowData>
}

impl CallbackData {
    #[inline]
    pub fn new(vec_window: HWND, event_sender: Sender<Event>, sender: Sender<WindowData>) -> CallbackData {
        let mut data_vector = Vec::with_capacity(4);
        data_vector.push(WindowDataIntern::new(vec_window, event_sender));

        CallbackData {
            win_vec: data_vector,
            win_sender: sender
        }
    }
}

struct WindowDataIntern {
    window: HWND,
    sender: Sender<Event>
}

impl WindowDataIntern {
    #[inline]
    fn new(window: HWND, sender: Sender<Event>) -> WindowDataIntern {
        WindowDataIntern {
            window: window,
            sender: sender
        }
    }
}

pub struct WindowData( pub InternalWindow, pub Receiver<Event> );

pub const MSG_NEWOWNEDWINDOW: UINT = 0xADD;
pub const MSG_GAINFOCUS: UINT = 71913;

fn send_event(source: HWND, event: Event) {
    CALLBACK_DATA.with(|data| {
        let data = data.borrow();

        let vector = match *data {
            Some(ref d) => &d.win_vec,
            None => return
        };

        match get_window_index(vector, source) {
            -1  => (),
            i   => {vector[i as usize].sender.send(event).ok();}
        }
    });
}

fn get_window_index(vector: &Vec<WindowDataIntern>, window: HWND) -> isize {
    let mut index = vector.len();

    if index != 0 {
        while index != 0 {
            index -= 1;

            if vector[index].window == window {
                return index as isize;
            }
        }
    }

    -1
}

unsafe extern "system" fn callback(hwnd: HWND, msg: UINT,
                                   wparam: WPARAM, lparam: LPARAM)
                                   -> winapi::LRESULT {
    match msg {
        winapi::WM_KEYDOWN  => {
            use event::Event::KeyInput;
            use event::PressState;

            let press_state = {
                match lparam & 0x40000000 {
                    0 => PressState::Pressed,
                    _ => PressState::Held
                }
            };

            match VKeyCode::from_u64(wparam) {
                Some(k) => send_event(hwnd, KeyInput(press_state, k)),
                None    => ()
            }

            0
        }

        winapi::WM_KEYUP    => {
            use event::Event::KeyInput;
            use event::PressState;

            match VKeyCode::from_u64(wparam) {
                Some(k) => send_event(hwnd, KeyInput(PressState::Released, k)),
                None    => ()
            }

            0
        }

        // Currently only draws black.
        // TODO: Make it actually draw shit
        winapi::WM_PAINT    => {
            let mut pstruct = mem::uninitialized();
            let hdc = user32::BeginPaint(hwnd, &mut pstruct);

            user32::FillRect(hdc, &pstruct.rcPaint, gdi32::CreateSolidBrush(0x000000));

            user32::EndPaint(hwnd, &pstruct);
            0
        }

        MSG_GAINFOCUS       => {
            user32::SetFocus(hwnd);

            0
        }

        MSG_NEWOWNEDWINDOW  => {
            use std::mem::transmute;
            use std::sync::mpsc;

            // For this message, pointers to the name and window config are stored in the
            // WPARAM and LPARAM parameters, respectively. This turns them into proper pointers
            // and gets the objects from the pointers.
            let name = (*transmute::<WPARAM, &&str>(wparam)).to_string();
            let config: WindowConfig = transmute::<LPARAM, &WindowConfig>(lparam).clone();

            let internal_window = InternalWindow::new(name, config, Some(hwnd));
            let (tx, rx) = mpsc::channel();

            CALLBACK_DATA.with(|data| {
                let mut data = data.borrow_mut();

                {
                    // This block of code gets a reference to the vector of windows and pushes information
                    // about new window to the top of the vector

                    let mut vector = match *data {
                        Some(ref mut v) => &mut v.win_vec,
                        None            => return
                    };

                    vector.push(WindowDataIntern::new(internal_window.0, tx));
                }

                // Get a reference to the window data sender
                let sender = match *data {
                    Some(ref r) => &r.win_sender,
                    None        => return
                };

                sender.send(WindowData(internal_window, rx)).ok();
            });

            0
        }

        winapi::WM_DESTROY  => {
            use event::Event::Closed;

            CALLBACK_DATA.with(|data| {
                let mut vector = data.borrow_mut();

                let mut vector = match *vector {
                    Some(ref mut v) => &mut v.win_vec,
                    None        => return
                };

                // If this window's information is still in the vector, remove it from
                // the vector and send the closed message for this window.
                match get_window_index(vector, hwnd) {
                    -1  => (),
                    i   => {vector.remove(i as usize).sender.send(Closed).ok();}
                }
            });

            user32::DestroyWindow(hwnd);
            0
        }

        _ => user32::DefWindowProcW(hwnd, msg, wparam, lparam)
    }

}

fn osstr<'a>(s: &'a str) -> Vec<u16> {
    OsStr::new(s).encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>()
}

fn wide_path(path: PathBuf) -> Vec<u16> {
    path.as_os_str().encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>()
}<commit_msg>Began experimenting with changing the cursor<commit_after>use winapi;
use user32;
use kernel32;
use gdi32;

use winapi::{UINT, WPARAM, LPARAM};
use winapi::windef::HWND;
use winapi::winuser::WNDCLASSEXW;

use std::ptr;
use std::mem;
use std::ops::Drop;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::path::PathBuf;
use std::cell::RefCell;
use std::sync::mpsc::{Sender, Receiver};

use num::FromPrimitive;

use config::WindowConfig;
use event::{Event, VKeyCode};

#[derive(Clone)]
pub struct InternalWindow( pub HWND );

unsafe impl Send for InternalWindow {}
unsafe impl Sync for InternalWindow {}

impl InternalWindow {
    #[inline]
    pub fn new<'a>(name: String, config: WindowConfig, owner: Option<HWND>) -> InternalWindow {
        unsafe {
            let class_name = register_window_class();

            let window_name = osstr(&name);

            let (style, style_ex) = {
                use config::InitialState::*;

                let mut style = winapi::WS_SYSMENU;
                let mut style_ex = 0;

                if !config.borderless && !config.tool_window {
                    style |= winapi::WS_CAPTION;

                    if config.resizable {
                        style |= winapi::WS_SIZEBOX;

                        if config.maximizable {
                            style |= winapi::WS_MAXIMIZEBOX;
                        }
                    }

                    if config.minimizable {
                        style |= winapi::WS_MINIMIZEBOX;
                    }

                    style_ex |= winapi::WS_EX_WINDOWEDGE;
                }

                if config.tool_window {
                    style_ex |= winapi::WS_EX_TOOLWINDOW;
                }

                match config.initial_state {
                    Windowed    => (),
                    Minimized   => style |= winapi::WS_MINIMIZE,
                    Maximized   => style |= winapi::WS_MAXIMIZE
                }

                (style, style_ex)
            };

            let size = match config.size {
                Some(s) => {
                    let mut size_rect = winapi::RECT {
                        left: 0,
                        top: 0,
                        right: s.0,
                        bottom: s.1
                    };

                    user32::AdjustWindowRectEx(&mut size_rect, style, 0, style_ex);
                    (size_rect.right - size_rect.left, size_rect.bottom - size_rect.top)
                }

                None => (winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT)
            };

            let window_handle = user32::CreateWindowExW(
                style_ex,
                class_name.as_ptr(),
                window_name.as_ptr() as winapi::LPCWSTR,
                style,
                winapi::CW_USEDEFAULT,
                winapi::CW_USEDEFAULT,
                size.0,
                size.1,
                // This parameter specifies the window's owner. If the window
                // is unowned, then it passes a null pointer to the parameter.
                owner.unwrap_or(ptr::null_mut()),
                ptr::null_mut(),
                kernel32::GetModuleHandleW(ptr::null()),
                ptr::null_mut()
            );

            if window_handle == ptr::null_mut() {
                panic!(format!("Error: {}", ::std::io::Error::last_os_error()));
            }

            // If the window should be borderless, make it borderless
            if config.borderless {
                user32::SetWindowLongW(window_handle, -16, 0);
            }

            if let Some(p) = config.icon {
                let path = wide_path(p).as_ptr();

                // Load the 32x32 icon
                let icon = user32::LoadImageW(ptr::null_mut(), path, winapi::IMAGE_ICON, 32, 32, winapi::LR_LOADFROMFILE);
                if icon != ptr::null_mut() {
                    user32::SendMessageW(window_handle, winapi::WM_SETICON, winapi::ICON_BIG as u64, icon as winapi::LPARAM);
                }
                else {
                    panic!("Could not load 32x32 icon (TODO: Make this not panic)");
                }

                // Load the 16x16 icon
                let icon = user32::LoadImageW(ptr::null_mut(), path, winapi::IMAGE_ICON, 16, 16, winapi::LR_LOADFROMFILE);
                if icon != ptr::null_mut() {
                    user32::SendMessageW(window_handle, winapi::WM_SETICON, winapi::ICON_SMALL as u64, icon as winapi::LPARAM);
                }
                else {
                    panic!("Could not load 16x16 icon (TODO: Make this not panic)");
                }
            }

            InternalWindow( window_handle )
        }
    }

    #[inline]
    pub fn set_title(&self, title: &str) {
        unsafe {
            let title = osstr(title);
            user32::SetWindowTextW(self.0, title.as_ptr());
        }
    }

    #[inline]
    pub fn show(&self) {
        unsafe {
            user32::ShowWindow(self.0, winapi::SW_SHOW);
        }
    }

    #[inline]
    pub fn hide(&self) {
        unsafe {
            user32::ShowWindow(self.0, winapi::SW_HIDE);
        }
    }

    #[inline]
    pub fn enable(&self) {
        unsafe {
            user32::EnableWindow(self.0, winapi::TRUE);
        }
    }

    #[inline]
    pub fn disable(&self) {
        unsafe {
            user32::EnableWindow(self.0, winapi::FALSE);
        }
    }

    #[inline]
    pub fn focus(&self) {
        unsafe {
            // The SetFocus method does not work across threads, but SendMessage does. As
            // such, this sends a message to the corresponding window where the focus is set
            // in the callback, which is executed in the correct thread.
            user32::SendMessageW(self.0, MSG_GAINFOCUS, 0, 0);
        }
    }

    #[inline]
    pub fn get_position(&self) -> Option<(i32, i32)> {
        unsafe {
            let mut rect = mem::uninitialized();

            match user32::GetWindowRect(self.0, &mut rect) {
                0 => None,
                _ => Some((rect.left as i32, rect.top as i32))
            }
        }
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<(u32, u32)> {
        unsafe {
            let mut rect = mem::uninitialized();

            match user32::GetClientRect(self.0, &mut rect) {
                0 => None,
                _ => Some(((rect.right - rect.left) as u32,
                           (rect.bottom - rect.top) as u32))
            }
        }
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<(u32, u32)> {
        unsafe {
            let mut rect = mem::uninitialized();

            match user32::GetWindowRect(self.0, &mut rect) {
                0 => None,
                _ => Some(((rect.right - rect.left) as u32,
                           (rect.bottom - rect.top) as u32))
            }
        }
    }

    #[inline]
    pub fn set_position(&self, x: i32, y: i32) -> Option<()> {
        unsafe {
            let result = user32::SetWindowPos(
                self.0,
                ptr::null_mut(),
                x,
                y,
                0,
                0,
                winapi::SWP_NOSIZE | winapi::SWP_NOZORDER | winapi::SWP_NOACTIVATE
            );

            match result {
                0 => None,
                _ => Some(())
            }
        }
    }

    #[inline]
    pub fn set_inner_size(&self, x: u32, y: u32) -> Option<()> {
        unsafe {
            let mut rect = winapi::RECT {
                left: 0,
                top: 0,
                right: x as i32,
                bottom: y as i32
            };

            user32::AdjustWindowRectEx(
                &mut rect,
                user32::GetWindowLongW(self.0, -16) as u32, // Get the window's style
                0,
                user32::GetWindowLongW(self.0, -20) as u32  // Get the window's extended style
            );

            let result = user32::SetWindowPos(
                self.0,
                ptr::null_mut(),
                0,
                0,
                rect.right - rect.left,
                rect.bottom - rect.top,
                winapi::SWP_NOMOVE | winapi::SWP_NOZORDER | winapi::SWP_NOACTIVATE
            );

            match result {
                0 => None,
                _ => Some(())
            }
        }
    }

    pub fn kill(&self) {
        unsafe {
            user32::PostMessageW(self.0, winapi::WM_DESTROY, 0, 0);
        }
    }
}

impl Drop for InternalWindow {
    fn drop(&mut self) {
        self.kill();
    }
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name = osstr("Window Class");

    let window_class = WNDCLASSEXW {
        cbSize: mem::size_of::<WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_OWNDC | winapi::CS_VREDRAW | winapi::CS_HREDRAW,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut()
    };
    user32::RegisterClassExW(&window_class);

    class_name
}

thread_local!(pub static CALLBACK_DATA: RefCell<Option<CallbackData>> = RefCell::new(None));

pub struct CallbackData {
    win_vec: Vec<WindowDataIntern>,
    win_sender: Sender<WindowData>
}

impl CallbackData {
    #[inline]
    pub fn new(vec_window: HWND, event_sender: Sender<Event>, sender: Sender<WindowData>) -> CallbackData {
        let mut data_vector = Vec::with_capacity(4);
        data_vector.push(WindowDataIntern::new(vec_window, event_sender));

        CallbackData {
            win_vec: data_vector,
            win_sender: sender
        }
    }
}

struct WindowDataIntern {
    window: HWND,
    sender: Sender<Event>
}

impl WindowDataIntern {
    #[inline]
    fn new(window: HWND, sender: Sender<Event>) -> WindowDataIntern {
        WindowDataIntern {
            window: window,
            sender: sender
        }
    }
}

pub struct WindowData( pub InternalWindow, pub Receiver<Event> );

pub const MSG_NEWOWNEDWINDOW: UINT = 0xADD;
pub const MSG_GAINFOCUS: UINT = 71913;

fn send_event(source: HWND, event: Event) {
    CALLBACK_DATA.with(|data| {
        let data = data.borrow();

        let vector = match *data {
            Some(ref d) => &d.win_vec,
            None => return
        };

        match get_window_index(vector, source) {
            -1  => (),
            i   => {vector[i as usize].sender.send(event).ok();}
        }
    });
}

fn get_window_index(vector: &Vec<WindowDataIntern>, window: HWND) -> isize {
    let mut index = vector.len();

    if index != 0 {
        while index != 0 {
            index -= 1;

            if vector[index].window == window {
                return index as isize;
            }
        }
    }

    -1
}

unsafe extern "system" fn callback(hwnd: HWND, msg: UINT,
                                   wparam: WPARAM, lparam: LPARAM)
                                   -> winapi::LRESULT {
    match msg {
        winapi::WM_KEYDOWN  => {
            use event::Event::KeyInput;
            use event::PressState;

            let press_state = {
                match lparam & 0x40000000 {
                    0 => PressState::Pressed,
                    _ => PressState::Held
                }
            };

            match VKeyCode::from_u64(wparam) {
                Some(k) => send_event(hwnd, KeyInput(press_state, k)),
                None    => ()
            }

            0
        }

        winapi::WM_SETCURSOR=> {
            let cursor =  user32::LoadCursorW(ptr::null_mut(), winapi::IDC_WAIT);
            if cursor != ptr::null_mut() {
                user32::SetCursor(cursor);
            }

            0
        }

        winapi::WM_KEYUP    => {
            use event::Event::KeyInput;
            use event::PressState;

            match VKeyCode::from_u64(wparam) {
                Some(k) => send_event(hwnd, KeyInput(PressState::Released, k)),
                None    => ()
            }

            0
        }

        // Currently only draws black.
        // TODO: Make it actually draw shit
        winapi::WM_PAINT    => {
            let mut pstruct = mem::uninitialized();
            let hdc = user32::BeginPaint(hwnd, &mut pstruct);

            user32::FillRect(hdc, &pstruct.rcPaint, gdi32::CreateSolidBrush(0x000000));

            user32::EndPaint(hwnd, &pstruct);
            0
        }

        MSG_GAINFOCUS       => {
            user32::SetFocus(hwnd);

            0
        }

        MSG_NEWOWNEDWINDOW  => {
            use std::mem::transmute;
            use std::sync::mpsc;

            // For this message, pointers to the name and window config are stored in the
            // WPARAM and LPARAM parameters, respectively. This turns them into proper pointers
            // and gets the objects from the pointers.
            let name = (*transmute::<WPARAM, &&str>(wparam)).to_string();
            let config: WindowConfig = transmute::<LPARAM, &WindowConfig>(lparam).clone();

            let internal_window = InternalWindow::new(name, config, Some(hwnd));
            let (tx, rx) = mpsc::channel();

            CALLBACK_DATA.with(|data| {
                let mut data = data.borrow_mut();

                {
                    // This block of code gets a reference to the vector of windows and pushes information
                    // about new window to the top of the vector

                    let mut vector = match *data {
                        Some(ref mut v) => &mut v.win_vec,
                        None            => return
                    };

                    vector.push(WindowDataIntern::new(internal_window.0, tx));
                }

                // Get a reference to the window data sender
                let sender = match *data {
                    Some(ref r) => &r.win_sender,
                    None        => return
                };

                sender.send(WindowData(internal_window, rx)).ok();
            });

            0
        }

        winapi::WM_DESTROY  => {
            use event::Event::Closed;

            CALLBACK_DATA.with(|data| {
                let mut vector = data.borrow_mut();

                let mut vector = match *vector {
                    Some(ref mut v) => &mut v.win_vec,
                    None        => return
                };

                // If this window's information is still in the vector, remove it from
                // the vector and send the closed message for this window.
                match get_window_index(vector, hwnd) {
                    -1  => (),
                    i   => {vector.remove(i as usize).sender.send(Closed).ok();}
                }
            });

            user32::DestroyWindow(hwnd);
            0
        }

        _ => user32::DefWindowProcW(hwnd, msg, wparam, lparam)
    }

}

fn osstr<'a>(s: &'a str) -> Vec<u16> {
    OsStr::new(s).encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>()
}

fn wide_path(path: PathBuf) -> Vec<u16> {
    path.as_os_str().encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>()
}<|endoftext|>


<commit_before>use hyper::header::AccessControlAllowOrigin;
use hyper::server::Request;

pub fn read_origin(req: &Request) -> Option<String> {
	match req.headers().get_raw("origin") {
		Some(ref v) if v.len() == 1 => {
				String::from_utf8(&v[0]).ok()
		},
		_ => None
	}
}

pub fn get_cors_header(allowed: &[AccessControlAllowOrigin], origin: &Option<String>) -> Option<AccessControlAllowOrigin> {

	if allowed.is_empty() {
		return None;
	}

	if let Some(ref origin) = *origin {
		for cors in allowed  {
			match *cors {
				AccessControlAllowOrigin::Any => return Some(AccessControlAllowOrigin::Value(origin.clone())),
				AccessControlAllowOrigin::Null => return Some(AccessControlAllowOrigin::Null),
				AccessControlAllowOrigin::Value(ref val) if val == origin => return Some(AccessControlAllowOrigin::Value(origin.clone())),
				_ => {}
			}
		}
	}

	Some(AccessControlAllowOrigin::Null)
}

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

	#[test]
	fn should_return_none_for_empty_list() {
		// given
		let origin = None;

		// when
		let res = get_cors_header(&Vec::new(), &origin);

		// then
		assert_eq!(res, None);
	}

	#[test]
	fn should_return_none_for_empty_origin() {
		// given
		let origin = None;

		// when
		let res = get_cors_header(
			&vec![AccessControlAllowOrigin::Value("http://ethereum.org".into())],
			&origin
		);

		// then
		assert_eq!(res, Some(AccessControlAllowOrigin::Null));
	}

	#[test]
	fn should_return_none_for_not_matching_origin() {
		// given
		let origin = Some("http://ethcore.io".into());

		// when
		let res = get_cors_header(
			&vec![AccessControlAllowOrigin::Value("http://ethereum.org".into())],
			&origin
		);

		// then
		assert_eq!(res, Some(AccessControlAllowOrigin::Null));
	}

	#[test]
	fn should_return_specific_origin_if_we_allow_any() {
		// given
		let origin = Some("http://ethcore.io".into());

		// when
		let res = get_cors_header(&vec![AccessControlAllowOrigin::Any], &origin);

		// then
		assert_eq!(res, Some(AccessControlAllowOrigin::Value("http://ethcore.io".into())));
	}

	#[test]
	fn should_return_specific_origin_if_there_is_a_match() {
		// given
		let origin = Some("http://ethcore.io".into());

		// when
		let res = get_cors_header(
			&vec![AccessControlAllowOrigin::Value("http://ethereum.org".into()), AccessControlAllowOrigin::Value("http://ethcore.io".into())],
			&origin
		);

		// then
		assert_eq!(res, Some(AccessControlAllowOrigin::Value("http://ethcore.io".into())));
	}
}
<commit_msg>Formatting fix<commit_after>use hyper::header::AccessControlAllowOrigin;
use hyper::server::Request;

pub fn read_origin(req: &Request) -> Option<String> {
	match req.headers().get_raw("origin") {
		Some(ref v) if v.len() == 1 => {
			String::from_utf8(&v[0]).ok()
		},
		_ => None
	}
}

pub fn get_cors_header(allowed: &[AccessControlAllowOrigin], origin: &Option<String>) -> Option<AccessControlAllowOrigin> {

	if allowed.is_empty() {
		return None;
	}

	if let Some(ref origin) = *origin {
		for cors in allowed  {
			match *cors {
				AccessControlAllowOrigin::Any => return Some(AccessControlAllowOrigin::Value(origin.clone())),
				AccessControlAllowOrigin::Null => return Some(AccessControlAllowOrigin::Null),
				AccessControlAllowOrigin::Value(ref val) if val == origin => return Some(AccessControlAllowOrigin::Value(origin.clone())),
				_ => {}
			}
		}
	}

	Some(AccessControlAllowOrigin::Null)
}

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

	#[test]
	fn should_return_none_for_empty_list() {
		// given
		let origin = None;

		// when
		let res = get_cors_header(&Vec::new(), &origin);

		// then
		assert_eq!(res, None);
	}

	#[test]
	fn should_return_none_for_empty_origin() {
		// given
		let origin = None;

		// when
		let res = get_cors_header(
			&vec![AccessControlAllowOrigin::Value("http://ethereum.org".into())],
			&origin
		);

		// then
		assert_eq!(res, Some(AccessControlAllowOrigin::Null));
	}

	#[test]
	fn should_return_none_for_not_matching_origin() {
		// given
		let origin = Some("http://ethcore.io".into());

		// when
		let res = get_cors_header(
			&vec![AccessControlAllowOrigin::Value("http://ethereum.org".into())],
			&origin
		);

		// then
		assert_eq!(res, Some(AccessControlAllowOrigin::Null));
	}

	#[test]
	fn should_return_specific_origin_if_we_allow_any() {
		// given
		let origin = Some("http://ethcore.io".into());

		// when
		let res = get_cors_header(&vec![AccessControlAllowOrigin::Any], &origin);

		// then
		assert_eq!(res, Some(AccessControlAllowOrigin::Value("http://ethcore.io".into())));
	}

	#[test]
	fn should_return_specific_origin_if_there_is_a_match() {
		// given
		let origin = Some("http://ethcore.io".into());

		// when
		let res = get_cors_header(
			&vec![AccessControlAllowOrigin::Value("http://ethereum.org".into()), AccessControlAllowOrigin::Value("http://ethcore.io".into())],
			&origin
		);

		// then
		assert_eq!(res, Some(AccessControlAllowOrigin::Value("http://ethcore.io".into())));
	}
}
<|endoftext|>


<commit_before><commit_msg>fix(Execution cancellation): Improve handling of cancel requests<commit_after><|endoftext|>


<commit_before>// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use itertools::Itertools;

use crate::{
    conversion::api::{Api, TypeKind},
    types::QualifiedName,
};

use super::{
    fun::{FnPhase, FnPrePhase1, PodAndDepAnalysis},
    pod::PodAnalysis,
    tdef::TypedefAnalysis,
};

pub(crate) trait HasDependencies {
    fn name(&self) -> &QualifiedName;
    fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_>;

    fn format_deps(&self) -> String {
        self.deps().join(",")
    }
}

impl HasDependencies for Api<FnPrePhase1> {
    fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_> {
        match self {
            Api::Typedef {
                old_tyname,
                analysis: TypedefAnalysis { deps, .. },
                ..
            } => Box::new(old_tyname.iter().chain(deps.iter())),
            Api::Struct {
                analysis:
                    PodAnalysis {
                        kind: TypeKind::Pod,
                        bases,
                        field_deps,
                        ..
                    },
                ..
            } => Box::new(field_deps.iter().chain(bases.iter())),
            Api::Function { analysis, .. } => Box::new(analysis.deps.iter()),
            Api::Subclass {
                name: _,
                superclass,
            } => Box::new(std::iter::once(superclass)),
            Api::RustSubclassFn { details, .. } => Box::new(details.dependencies.iter()),
            Api::RustFn { deps, .. } => Box::new(deps.iter()),
            _ => Box::new(std::iter::empty()),
        }
    }

    fn name(&self) -> &QualifiedName {
        self.name()
    }
}

impl HasDependencies for Api<FnPhase> {
    /// Any dependencies on other APIs which this API has.
    fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_> {
        match self {
            Api::Typedef {
                old_tyname,
                analysis: TypedefAnalysis { deps, .. },
                ..
            } => Box::new(old_tyname.iter().chain(deps.iter())),
            Api::Struct {
                analysis:
                    PodAndDepAnalysis {
                        pod:
                            PodAnalysis {
                                kind: TypeKind::Pod,
                                bases,
                                field_deps,
                                ..
                            },
                        constructor_and_allocator_deps,
                        ..
                    },
                ..
            } => Box::new(
                field_deps
                    .iter()
                    .chain(bases.iter())
                    .chain(constructor_and_allocator_deps.iter()),
            ),
            Api::Struct {
                analysis:
                    PodAndDepAnalysis {
                        constructor_and_allocator_deps,
                        ..
                    },
                ..
            } => Box::new(constructor_and_allocator_deps.iter()),
            Api::Function { analysis, .. } => Box::new(analysis.deps.iter()),
            Api::Subclass {
                name: _,
                superclass,
            } => Box::new(std::iter::once(superclass)),
            Api::RustSubclassFn { details, .. } => Box::new(details.dependencies.iter()),
            Api::RustFn { deps, .. } => Box::new(deps.iter()),
            _ => Box::new(std::iter::empty()),
        }
    }

    fn name(&self) -> &QualifiedName {
        self.name()
    }
}
<commit_msg>Properly propagate deps for non-POD structs<commit_after>// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use itertools::Itertools;

use crate::{
    conversion::api::{Api, TypeKind},
    types::QualifiedName,
};

use super::{
    fun::{FnPhase, FnPrePhase1, PodAndDepAnalysis},
    pod::PodAnalysis,
    tdef::TypedefAnalysis,
};

pub(crate) trait HasDependencies {
    fn name(&self) -> &QualifiedName;
    fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_>;

    fn format_deps(&self) -> String {
        self.deps().join(",")
    }
}

impl HasDependencies for Api<FnPrePhase1> {
    fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_> {
        match self {
            Api::Typedef {
                old_tyname,
                analysis: TypedefAnalysis { deps, .. },
                ..
            } => Box::new(old_tyname.iter().chain(deps.iter())),
            Api::Struct {
                analysis: PodAnalysis {
                    bases, field_deps, ..
                },
                ..
            } => Box::new(field_deps.iter().chain(bases.iter())),
            Api::Function { analysis, .. } => Box::new(analysis.deps.iter()),
            Api::Subclass {
                name: _,
                superclass,
            } => Box::new(std::iter::once(superclass)),
            Api::RustSubclassFn { details, .. } => Box::new(details.dependencies.iter()),
            Api::RustFn { deps, .. } => Box::new(deps.iter()),
            _ => Box::new(std::iter::empty()),
        }
    }

    fn name(&self) -> &QualifiedName {
        self.name()
    }
}

impl HasDependencies for Api<FnPhase> {
    /// Any dependencies on other APIs which this API has.
    fn deps(&self) -> Box<dyn Iterator<Item = &QualifiedName> + '_> {
        match self {
            Api::Typedef {
                old_tyname,
                analysis: TypedefAnalysis { deps, .. },
                ..
            } => Box::new(old_tyname.iter().chain(deps.iter())),
            Api::Struct {
                analysis:
                    PodAndDepAnalysis {
                        pod:
                            PodAnalysis {
                                kind: TypeKind::Pod,
                                bases,
                                field_deps,
                                ..
                            },
                        constructor_and_allocator_deps,
                        ..
                    },
                ..
            } => Box::new(
                field_deps
                    .iter()
                    .chain(bases.iter())
                    .chain(constructor_and_allocator_deps.iter()),
            ),
            Api::Struct {
                analysis:
                    PodAndDepAnalysis {
                        constructor_and_allocator_deps,
                        ..
                    },
                ..
            } => Box::new(constructor_and_allocator_deps.iter()),
            Api::Function { analysis, .. } => Box::new(analysis.deps.iter()),
            Api::Subclass {
                name: _,
                superclass,
            } => Box::new(std::iter::once(superclass)),
            Api::RustSubclassFn { details, .. } => Box::new(details.dependencies.iter()),
            Api::RustFn { deps, .. } => Box::new(deps.iter()),
            _ => Box::new(std::iter::empty()),
        }
    }

    fn name(&self) -> &QualifiedName {
        self.name()
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use voodoo::window::Point;

use level;
use program::{Ability, Program, ProgramBuilder, Team};

const LEVELS: [[&'static str; 20]; 2] = [
    [
        "                                                          ",
        "                                                          ",
        "          .........................                       ",
        "          .........................                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "   o...............s             .....                    ",
        "   o...............s             .....                    ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          .........................                       ",
        "          .........................                       ",
        "                                                          ",
        "                                                          ",
        "                                                          ",
    ],
    [
        "                                                          ",
        "                                                          ",
        "          .........................                       ",
        "          ..........    ...........                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          o........s    ...........                       ",
        "          o........s    ...........                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..........    ...........                       ",
        "          .........................                       ",
        "                                                          ",
        "                                                          ",
        "                                                          ",
    ],
];

lazy_static! {
    static ref PROGRAMS: HashMap<String, ProgramBuilder> = {
        let mut m = HashMap::new();

        m.insert("s".to_owned(),
                 ProgramBuilder::new("Sprinter")
                 .max_tail(2)
                 .max_moves(10));

        m
    };
}

pub fn load_level(id: usize) -> level::Level {
    let mut level = level::Level::new(&LEVELS[id]);

    for (row_offset, row) in LEVELS[id].iter().enumerate() {
        for (col_offset, c) in row.chars().enumerate() {
            let s: String = c.to_string();
            if let Some(builder) = PROGRAMS.get(&s) {
                let mut instance = builder.instance(Team::Enemy);
                instance.position = Point::new(col_offset as u16 + 1, row_offset as u16 + 1);
                level.add_program(instance);
            }
        }
    }

    level
}

// sprinters (s) - very fast, low damage, low health
<commit_msg>fix(AI): add ability to AI programs<commit_after>use std::collections::HashMap;

use voodoo::window::Point;

use level;
use program::{Ability, Program, ProgramBuilder, Team};

const LEVELS: [[&'static str; 20]; 2] = [
    [
        "                                                          ",
        "                                                          ",
        "          .........................                       ",
        "          .........................                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "   o...............s             .....                    ",
        "   o...............s             .....                    ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          .........................                       ",
        "          .........................                       ",
        "                                                          ",
        "                                                          ",
        "                                                          ",
    ],
    [
        "                                                          ",
        "                                                          ",
        "          .........................                       ",
        "          ..........    ...........                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          o........s    ...........                       ",
        "          o........s    ...........                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..                     ..                       ",
        "          ..........    ...........                       ",
        "          .........................                       ",
        "                                                          ",
        "                                                          ",
        "                                                          ",
    ],
];

lazy_static! {
    static ref PROGRAMS: HashMap<String, ProgramBuilder> = {
        let mut m = HashMap::new();

        m.insert("s".to_owned(),
                 ProgramBuilder::new("Sprinter")
                 .ability("Overflow", Ability::Destroy { damage: 1, range: 3 })
                 .max_tail(2)
                 .max_moves(10));

        m
    };
}

pub fn load_level(id: usize) -> level::Level {
    let mut level = level::Level::new(&LEVELS[id]);

    for (row_offset, row) in LEVELS[id].iter().enumerate() {
        for (col_offset, c) in row.chars().enumerate() {
            let s: String = c.to_string();
            if let Some(builder) = PROGRAMS.get(&s) {
                let mut instance = builder.instance(Team::Enemy);
                instance.position = Point::new(col_offset as u16 + 1, row_offset as u16 + 1);
                level.add_program(instance);
            }
        }
    }

    level
}

// sprinters (s) - very fast, low damage, low health
<|endoftext|>


<commit_before>use socket::Socket;

pub enum Unit {
    RAW,
    VOLTS,
}

impl ::std::fmt::Display for Unit {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Unit::RAW => "RAW",
            &Unit::VOLTS => "VOLTS",
        };

        write!(f, "{}", display)
    }
}

pub enum Format {
    FLOAT,
    ASCII,
}

impl ::std::fmt::Display for Format {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Format::FLOAT => "FLOAT",
            &Format::ASCII => "ASCII",
        };

        write!(f, "{}", display)
    }
}

pub struct Data {
    socket: Socket,
}

impl Data {
    pub fn new(socket: Socket) -> Self {
        Data {
            socket: socket,
        }
    }

    /**
     * Returns current position of write pointer.
     */
    pub fn get_write_pointer(&mut self) -> u32 {
        self.socket.send("ACQ:WPOS?");

        self.socket.receive()
            .parse()
            .unwrap()
    }

    /**
     * Returns position where trigger event appeared.
     */
    pub fn get_trigger_position(&mut self) -> u32 {
        self.socket.send("ACQ:TPOS?");

        self.socket.receive()
            .parse()
            .unwrap()
    }

    /**
     * Selects units in which acquired data will be returned.
     */
    pub fn set_units(&mut self, unit: Unit) {
        self.socket.send(format!("ACQ:DATA:UNITS {}", unit));
    }

    /**
     * Selects format acquired data will be returned.
     */
    pub fn set_format(&mut self, format: Format) {
        self.socket.send(format!("ACQ:DATA:FORMAT {}", format));
    }

    /**
     * Read samples from start to stop position.
     *
     * start = {0,1,...,16384}
     * stop_pos = {0,1,...116384}
     */
    pub fn read_slice(&mut self, source: u8, start: u16, end: u16) -> String {
        self.socket.send(format!("ACQ:SOUR{}:DATA:STA:END? {},{}", source, start, end));

        self.socket.receive()
    }

    /**
     * Read `m` samples from start position on.
     */
    pub fn read(&mut self, source: u8, start: u16, len: u32) -> String {
        self.socket.send(format!("ACQ:SOUR{}:DATA:STA:N? {},{}", source, start, len));

        self.socket.receive()
    }

    /**
     * Read full buf.
     *
     * Size starting from oldest sample in buffer (this is first sample after
     * trigger delay). Trigger delay by default is set to zero (in samples or
     * in seconds). If trigger delay is set to zero it will read full buf.
     * Size starting from trigger.
     */
    pub fn read_all(&mut self, source: u8) -> String {
        self.socket.send(format!("ACQ:SOUR{}:DATA?", source));

        self.socket.receive()
    }

    /**
     * Read m samples after trigger delay, starting from oldest sample in buffer
     * (this is first sample after trigger delay).
     *
     * Trigger delay by default is set to zero (in samples or in seconds). If
     * trigger delay is set to zero it will read m samples starting from trigger.
     */
    pub fn read_oldest(&mut self, source: u8, len: u32) -> String {
        self.socket.send(format!("ACQ:SOUR{}:DATA:OLD:N? {}", source, len));

        self.socket.receive()
    }

    /**
     * Read ``m`` samples before trigger delay.
     *
     * Trigger delay by default is set to zero (in samples or in seconds). If
     * trigger delay is set to zero it will read m samples before trigger.
     */
    pub fn read_latest(&mut self, source: u8, len: u32) -> String {
        self.socket.send(format!("ACQ:SOUR{}:DATA:LAT:N? {}", source, len));

        self.socket.receive()
    }

    /**
     * Returns buffer size.
     */
    pub fn buffer_size(&mut self) -> u32 {
        self.socket.send("ACQ:BUF:SIZE?");

        self.socket.receive()
            .parse()
            .unwrap()
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_get_write_pointer() {
        let (_, mut data) = create_data();

        assert_eq!(data.get_write_pointer(), 1024);
    }

    #[test]
    fn test_get_write_pointer_at_trigger() {
        let (_, mut data) = create_data();

        assert_eq!(data.get_trigger_position(), 512);
    }

    #[test]
    fn test_set_units() {
        let (rx, mut data) = create_data();

        data.set_units(::data::Unit::VOLTS);
        assert_eq!("ACQ:DATA:UNITS VOLTS\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_format() {
        let (rx, mut data) = create_data();

        data.set_format(::data::Format::FLOAT);
        assert_eq!("ACQ:DATA:FORMAT FLOAT\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_read_slice() {
        let (_, mut data) = create_data();

        assert_eq!(data.read_slice(1, 10, 13), "{123,231,-231}");
    }

    #[test]
    fn test_read() {
        let (_, mut data) = create_data();

        assert_eq!(data.read(1, 10, 3), "{1.2,3.2,-1.2}");
    }

    #[test]
    fn test_read_all() {
        let (_, mut data) = create_data();

        assert_eq!(data.read_all(1), "{1.2,3.2,-1.2}");
    }

    #[test]
    fn test_read_oldest() {
        let (_, mut data) = create_data();

        assert_eq!(data.read_oldest(1, 2), "{3.2,-1.2}");
    }

    #[test]
    fn test_read_latest() {
        let (_, mut data) = create_data();

        assert_eq!(data.read_latest(1, 2), "{1.2,3.2}");
    }

    #[test]
    fn test_buffer_size() {
        let (_, mut data) = create_data();

        assert_eq!(data.buffer_size(), 16384);
    }

    fn create_data() -> (::std::sync::mpsc::Receiver<String>, ::data::Data) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(addr);

        (rx, ::data::Data::new(socket))
    }
}
<commit_msg>[data] Use acquire::Source enum<commit_after>use socket::Socket;

pub enum Unit {
    RAW,
    VOLTS,
}

impl ::std::fmt::Display for Unit {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Unit::RAW => "RAW",
            &Unit::VOLTS => "VOLTS",
        };

        write!(f, "{}", display)
    }
}

pub enum Format {
    FLOAT,
    ASCII,
}

impl ::std::fmt::Display for Format {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Format::FLOAT => "FLOAT",
            &Format::ASCII => "ASCII",
        };

        write!(f, "{}", display)
    }
}

pub struct Data {
    socket: Socket,
}

impl Data {
    pub fn new(socket: Socket) -> Self {
        Data {
            socket: socket,
        }
    }

    /**
     * Returns current position of write pointer.
     */
    pub fn get_write_pointer(&mut self) -> u32 {
        self.socket.send("ACQ:WPOS?");

        self.socket.receive()
            .parse()
            .unwrap()
    }

    /**
     * Returns position where trigger event appeared.
     */
    pub fn get_trigger_position(&mut self) -> u32 {
        self.socket.send("ACQ:TPOS?");

        self.socket.receive()
            .parse()
            .unwrap()
    }

    /**
     * Selects units in which acquired data will be returned.
     */
    pub fn set_units(&mut self, unit: Unit) {
        self.socket.send(format!("ACQ:DATA:UNITS {}", unit));
    }

    /**
     * Selects format acquired data will be returned.
     */
    pub fn set_format(&mut self, format: Format) {
        self.socket.send(format!("ACQ:DATA:FORMAT {}", format));
    }

    /**
     * Read samples from start to stop position.
     *
     * start = {0,1,...,16384}
     * stop_pos = {0,1,...116384}
     */
    pub fn read_slice(&mut self, source: ::acquire::Source, start: u16, end: u16) -> String {
        self.socket.send(format!("ACQ:{}:DATA:STA:END? {},{}", source, start, end));

        self.socket.receive()
    }

    /**
     * Read `m` samples from start position on.
     */
    pub fn read(&mut self, source: ::acquire::Source, start: u16, len: u32) -> String {
        self.socket.send(format!("ACQ:{}:DATA:STA:N? {},{}", source, start, len));

        self.socket.receive()
    }

    /**
     * Read full buf.
     *
     * Size starting from oldest sample in buffer (this is first sample after
     * trigger delay). Trigger delay by default is set to zero (in samples or
     * in seconds). If trigger delay is set to zero it will read full buf.
     * Size starting from trigger.
     */
    pub fn read_all(&mut self, source: ::acquire::Source) -> String {
        self.socket.send(format!("ACQ:{}:DATA?", source));

        self.socket.receive()
    }

    /**
     * Read m samples after trigger delay, starting from oldest sample in buffer
     * (this is first sample after trigger delay).
     *
     * Trigger delay by default is set to zero (in samples or in seconds). If
     * trigger delay is set to zero it will read m samples starting from trigger.
     */
    pub fn read_oldest(&mut self, source: ::acquire::Source, len: u32) -> String {
        self.socket.send(format!("ACQ:{}:DATA:OLD:N? {}", source, len));

        self.socket.receive()
    }

    /**
     * Read ``m`` samples before trigger delay.
     *
     * Trigger delay by default is set to zero (in samples or in seconds). If
     * trigger delay is set to zero it will read m samples before trigger.
     */
    pub fn read_latest(&mut self, source: ::acquire::Source, len: u32) -> String {
        self.socket.send(format!("ACQ:{}:DATA:LAT:N? {}", source, len));

        self.socket.receive()
    }

    /**
     * Returns buffer size.
     */
    pub fn buffer_size(&mut self) -> u32 {
        self.socket.send("ACQ:BUF:SIZE?");

        self.socket.receive()
            .parse()
            .unwrap()
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_get_write_pointer() {
        let (_, mut data) = create_data();

        assert_eq!(data.get_write_pointer(), 1024);
    }

    #[test]
    fn test_get_write_pointer_at_trigger() {
        let (_, mut data) = create_data();

        assert_eq!(data.get_trigger_position(), 512);
    }

    #[test]
    fn test_set_units() {
        let (rx, mut data) = create_data();

        data.set_units(::data::Unit::VOLTS);
        assert_eq!("ACQ:DATA:UNITS VOLTS\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_set_format() {
        let (rx, mut data) = create_data();

        data.set_format(::data::Format::FLOAT);
        assert_eq!("ACQ:DATA:FORMAT FLOAT\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_read_slice() {
        let (_, mut data) = create_data();

        assert_eq!(data.read_slice(::acquire::Source::IN1, 10, 13), "{123,231,-231}");
    }

    #[test]
    fn test_read() {
        let (_, mut data) = create_data();

        assert_eq!(data.read(::acquire::Source::IN1, 10, 3), "{1.2,3.2,-1.2}");
    }

    #[test]
    fn test_read_all() {
        let (_, mut data) = create_data();

        assert_eq!(data.read_all(::acquire::Source::IN1), "{1.2,3.2,-1.2}");
    }

    #[test]
    fn test_read_oldest() {
        let (_, mut data) = create_data();

        assert_eq!(data.read_oldest(::acquire::Source::IN1, 2), "{3.2,-1.2}");
    }

    #[test]
    fn test_read_latest() {
        let (_, mut data) = create_data();

        assert_eq!(data.read_latest(::acquire::Source::IN1, 2), "{1.2,3.2}");
    }

    #[test]
    fn test_buffer_size() {
        let (_, mut data) = create_data();

        assert_eq!(data.buffer_size(), 16384);
    }

    fn create_data() -> (::std::sync::mpsc::Receiver<String>, ::data::Data) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(addr);

        (rx, ::data::Data::new(socket))
    }
}
<|endoftext|>