<commit_before>#[derive(Debug,PartialEq)]
pub enum RleComponent {
    Run(usize, u8),
    Literal(Vec<u8>)
}

struct Encoder {
    working_values: Vec<u8>,
    components: Vec<RleComponent>,
}

impl Encoder {
    fn new() -> Encoder {
        Encoder { working_values: vec![], components: vec![] }
    }

    fn commit(&mut self, component: RleComponent) {
        self.components.push(component);
        self.working_values = vec![];
    }
}

pub fn encode(input: &str) -> Vec<RleComponent> {
    let mut encoder = Encoder::new();
    let mut input_iter = input.bytes().peekable();
    let mut last: u8 = input_iter.nth(0).unwrap();
    let mut counter: usize = 1;

    for bv in input_iter {
        if bv == last {
            counter += 1;
        } else {
            if counter == 1 {
                // TODO: Combine adjacent literals.
                encoder.commit(RleComponent::Literal(vec![last]));
            } else {
                encoder.commit(RleComponent::Run(counter, last));
            }

            counter = 1;
            last = bv;
        }
    }
    // TODO: This repeated code isn't ideal.
    if counter == 1 {
        encoder.commit(RleComponent::Literal(vec![last]));
    } else {
        encoder.commit(RleComponent::Run(counter, last));
    }

    encoder.components
}

pub fn decode(input: Vec<RleComponent>) -> String {
    let mut decoded = vec!();

    for component in input {
        let next_sequence = match component {
            RleComponent::Run(length, byte) => vec![byte;length],
            RleComponent::Literal(bytes) => bytes,
        };
        decoded.extend(next_sequence);
    }

    String::from_utf8(decoded).unwrap()
}

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

    #[test]
    fn basic_encode() {
        assert_eq!(
            encode("hello"),
            [
                RleComponent::Literal(vec![104]),
                RleComponent::Literal(vec![101]),
                RleComponent::Run(2, 108),
                RleComponent::Literal(vec![111])
            ]
        );
    }

    #[test]
    #[ignore]
    fn empty_encode() {
        assert_eq!(
            encode(""),
            []
        );
    }

    #[test]
    fn with_trailing_run() {
        assert_eq!(
            encode("helloo"),
            [
                RleComponent::Literal(vec![104]),
                RleComponent::Literal(vec![101]),
                RleComponent::Run(2, 108),
                RleComponent::Run(2, 111),
            ]
        );
    }

    #[test]
    fn moretests() {
        assert_eq!(
            encode("aaaaaab"),
            [
                RleComponent::Run(6, 97),
                RleComponent::Literal(vec![98]),
            ]
        );
    }

    #[test]
    fn basic_decode() {
        assert_eq!(
            decode(encode("aabb")),
            "aabb"
        );
    }

    #[test]
    fn basic_decode_only_literal() {
        assert_eq!(
            decode(encode("ab")),
            "ab"
        );
    }
}
<commit_msg>Concatenate adjacent literals<commit_after>use std;
#[derive(Debug,PartialEq)]
pub enum RleComponent {
    Run(usize, u8),
    Literal(Vec<u8>)
}

struct Encoder {
    working_component: Option<RleComponent>,
    components: Vec<RleComponent>,
}

impl Encoder {
    fn new() -> Encoder {
        Encoder {
            working_component: None,
            components: vec![],
        }
    }

    fn commit(&mut self) {
        let wc = std::mem::replace(&mut self.working_component, None);
        if let Some(component) = wc {
            self.components.push(component);
        }
    }

    fn append(&mut self, component: RleComponent) {
        match component {
            RleComponent::Run(_, _) => {
                self.commit();
                self.working_component = Some(component);
            },
            RleComponent::Literal(new_val) => {
                match self.working_component {
                    Some(RleComponent::Run(_, _)) => {
                        self.commit();
                        self.working_component = Some(RleComponent::Literal(new_val));
                    }
                    Some(RleComponent::Literal(ref mut vals)) => {
                        vals.extend(new_val);
                    }
                    None => {
                        self.working_component = Some(RleComponent::Literal(new_val));
                    }
                }
            }
        }
    }

    fn finish(mut self) -> Vec<RleComponent> {
        self.commit();
        self.components
    }
}

pub fn encode(input: &str) -> Vec<RleComponent> {
    let mut encoder = Encoder::new();
    let mut input_iter = input.bytes().peekable();
    let mut last: u8 = input_iter.nth(0).unwrap();
    let mut counter: usize = 1;

    for bv in input_iter {
        if bv == last {
            counter += 1;
        } else {
            if counter == 1 {
                encoder.append(RleComponent::Literal(vec![last]));
            } else {
                encoder.append(RleComponent::Run(counter, last));
            }

            counter = 1;
            last = bv;
        }
    }
    // TODO: This repeated code isn't ideal.
    if counter == 1 {
        encoder.append(RleComponent::Literal(vec![last]));
    } else {
        encoder.append(RleComponent::Run(counter, last));
    }

    encoder.finish()
}

pub fn decode(input: Vec<RleComponent>) -> String {
    let mut decoded = vec!();

    for component in input {
        let next_sequence = match component {
            RleComponent::Run(length, byte) => vec![byte;length],
            RleComponent::Literal(bytes) => bytes,
        };
        decoded.extend(next_sequence);
    }

    String::from_utf8(decoded).unwrap()
}

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

    #[test]
    fn basic_encode() {
        assert_eq!(
            encode("hello"),
            [
                RleComponent::Literal(vec![104, 101]),
                RleComponent::Run(2, 108),
                RleComponent::Literal(vec![111])
            ]
        );
    }

    #[test]
    #[ignore]
    fn empty_encode() {
        assert_eq!(
            encode(""),
            []
        );
    }

    #[test]
    fn with_trailing_run() {
        assert_eq!(
            encode("helloo"),
            [
                RleComponent::Literal(vec![104, 101]),
                RleComponent::Run(2, 108),
                RleComponent::Run(2, 111),
            ]
        );
    }

    #[test]
    fn moretests() {
        assert_eq!(
            encode("aaaaaab"),
            [
                RleComponent::Run(6, 97),
                RleComponent::Literal(vec![98]),
            ]
        );
    }

    #[test]
    fn basic_decode() {
        assert_eq!(
            decode(encode("aabb")),
            "aabb"
        );
    }

    #[test]
    fn basic_decode_only_literal() {
        assert_eq!(
            decode(encode("ab")),
            "ab"
        );
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobProvide {
    id: i32,
    fk_job: i32,
    fk_variable: i32,
}

pub fn table_create_job_provide(conn: &Connection) -> Result<(), &'static str> {
    let load_table = conn.execute_batch(
        "CREATE TABLE JOBPROVIDE (
                  id            INTEGER PRIMARY KEY ASC,
                  fk_job           INTEGER,
                  fk_variable      INTEGER,
                  UNIQUE (fk_job, fk_variable) ON CONFLICT REPLACE
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES VARIABLE_NAME(id) ON UPDATE CASCADE
                  )",
    );
    if load_table.is_err() {
        return Err("table_create_session Failed");
    }
    load_table.unwrap();
    return Ok(());
}

pub fn insert_job_provide(
    conn: &Connection,
    job: &i32,
    provider: &i32,
) -> Result<i32, &'static str> {
    let me = JobProvide {
        id: 0,
        fk_job: *job,
        fk_variable: *provider,
    };
    let load_instance = conn.execute(
        "INSERT INTO JOBPROVIDE (fk_job, fk_variable)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable],
    );
    if load_instance.is_err() {
        return Err("failed trying to INSERT INTO JOBPROVIDE");
    }
    load_instance.unwrap();
    return Ok(0);
}

pub fn list_job_provide(conn: &Connection) -> Vec<JobProvide> {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable FROM JOBPROVIDE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| JobProvide {
        id: row.get(0),
        fk_job: row.get(1),
        fk_variable: row.get(2),
    });
    let mut items = Vec::<JobProvide>::new();
    if wraped_fs_file_iter.is_err() {
        return items;
    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_provide_by_all(
    conn: &Connection,
    fk_job: &i32,
    provider: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT JOBPROVIDE.id, JOBPROVIDE.fk_job, JOBPROVIDE.fk_variable FROM JOBPROVIDE WHERE JOBPROVIDE.fk_job = ?1 AND JOBPROVIDE.fk_variable=?2").unwrap();
    let job_provide_iter = stmt.query_map(&[fk_job, provider], |row| JobProvide {
        id: row.get(0),
        fk_job: row.get(1),
        fk_variable: row.get(2),
    });
    if job_provide_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_provide_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<commit_msg>Beutify the rust code<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobProvide {
    id: i32,
    fk_job: i32,
    fk_variable: i32,
}

pub fn table_create_job_provide(conn: &Connection) -> Result<(), &'static str> {
    let load_table = conn.execute_batch(
        "CREATE TABLE JOBPROVIDE (
                  id            INTEGER PRIMARY KEY ASC,
                  fk_job           INTEGER,
                  fk_variable      INTEGER,
                  UNIQUE (fk_job, fk_variable) ON CONFLICT REPLACE
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable) REFERENCES VARIABLE_NAME(id) ON UPDATE CASCADE
                  )",
    );
    if load_table.is_err() {
        return Err("table_create_session Failed");
    }
    load_table.unwrap();
    return Ok(());
}

pub fn insert_job_provide(
    conn: &Connection,
    job: &i32,
    provider: &i32,
) -> Result<i32, &'static str> {
    let me = JobProvide {
        id: 0,
        fk_job: *job,
        fk_variable: *provider,
    };
    let load_instance = conn.execute(
        "INSERT INTO JOBPROVIDE (fk_job, fk_variable)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable],
    );
    if load_instance.is_err() {
        return Err("failed trying to INSERT INTO JOBPROVIDE");
    }
    load_instance.unwrap();
    return Ok(0);
}

pub fn list_job_provide(conn: &Connection) -> Vec<JobProvide> {
    let mut stmt = conn
        .prepare("SELECT id, fk_job, fk_variable FROM JOBPROVIDE")
        .unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| JobProvide {
        id: row.get(0),
        fk_job: row.get(1),
        fk_variable: row.get(2),
    });
    let mut items = Vec::<JobProvide>::new();
    if wraped_fs_file_iter.is_err() {
        return items;
    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {
        items.push(person.unwrap());
    }
    return items;
}

pub fn pk_job_provide_by_all(
    conn: &Connection,
    fk_job: &i32,
    provider: &i32,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let mut stmt = conn.prepare("SELECT JOBPROVIDE.id, JOBPROVIDE.fk_job, JOBPROVIDE.fk_variable FROM JOBPROVIDE WHERE JOBPROVIDE.fk_job = ?1 AND JOBPROVIDE.fk_variable=?2").unwrap();
    let job_provide_iter = stmt.query_map(&[fk_job, provider], |row| JobProvide {
        id: row.get(0),
        fk_job: row.get(1),
        fk_variable: row.get(2),
    });
    if job_provide_iter.is_err() {
        return Err("Insert failed");
    }
    let result = job_provide_iter.unwrap();
    let mut found = 0;
    for person in result {
        let bill = person.unwrap();
        *pk = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>use gfx::display_list::DisplayList;
use gfx::compositor::{LayerBuffer, LayerBufferSet};
use opts::Opts;

use azure::AzFloat;
use azure::azure_hl::{B8G8R8A8, DrawTarget};
use core::libc::c_int;
use geom::matrix2d::Matrix2D;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;

// FIXME: Tiles are busted. Disable them for now.
const TILE_SIZE: uint = 4096;

pub struct RenderLayer {
    display_list: DisplayList,
    size: Size2D<uint>
}

/// Given a layer and a buffer, either reuses the buffer (if it's of the right size and format)
/// or creates a new buffer (if it's not of the appropriate size and format) and invokes the
/// given callback with the render layer and the buffer. Returns the resulting layer buffer (which
/// might be the old layer buffer if it had the appropriate size and format).
pub fn render_layers(layer: &RenderLayer,
                     buffer_set: LayerBufferSet,
                     opts: &Opts,
                     f: &fn(layer: &RenderLayer, buffer: &LayerBuffer) -> bool) -> LayerBufferSet {
    let mut buffers = match move buffer_set { LayerBufferSet { buffers: move b } => move b };

    // FIXME: Try not to create a new array here.
    let new_buffers = dvec::DVec();

    // Divide up the layer into tiles.
    let mut y = 0;
    while y < layer.size.height {
        let mut x = 0;
        while x < layer.size.width {
            // Figure out the dimension of this tile.
            let right = uint::min(x + TILE_SIZE, layer.size.width);
            let bottom = uint::min(y + TILE_SIZE, layer.size.height);
            let width = right - x;
            let height = bottom - y;

            // Round the width up the nearest 32 pixels for DMA on the Mac.
            let mut stride = width;
            if stride % 32 != 0 {
                stride = (stride & !(32 - 1)) + 32;
            }
            assert stride % 32 == 0;
            assert stride >= width;

            debug!("tile stride %u", stride);

            let tile_rect = Rect(Point2D(x, y), Size2D(width, height));

            let buffer;
            // FIXME: Try harder to search for a matching tile.
            // FIXME: Don't use shift; it's bad for perf. Maybe reverse and pop.
            if buffers.len() != 0 && buffers[0].rect == tile_rect {
                debug!("reusing tile, (%u, %u)", x, y);
                buffer = buffers.shift();
            } else {
                // Create a new buffer.
                debug!("creating tile, (%u, %u)", x, y);

                let size = Size2D(stride as i32, height as i32);

                let mut data: ~[u8] = ~[0];
                let offset;
                unsafe {
                    // FIXME: Evil black magic to ensure that we don't perform a slow memzero
                    // of this buffer. This should be made safe.

                    let align = 256;

                    let len = ((size.width * size.height * 4) as uint) + align;
                    vec::reserve(&mut data, len);
                    vec::raw::set_len(&mut data, len);

                    // Round up to the nearest 32-byte-aligned address for DMA on the Mac.
                    let addr: uint = cast::transmute(ptr::to_unsafe_ptr(&data[0]));
                    if addr % align == 0 {
                        offset = 0;
                    } else {
                        offset = align - addr % align;
                    }

                    debug!("tile offset is %u, expected addr is %x", offset, addr + offset);
                }

                buffer = LayerBuffer {
                    draw_target: DrawTarget::new_with_data(opts.render_backend,
                                                           move data,
                                                           offset,
                                                           size,
                                                           size.width * 4,
                                                           B8G8R8A8),
                    rect: tile_rect,
                    stride: stride
                };
            }

            let _ = f(layer, &buffer);
            new_buffers.push(move buffer);

            x += TILE_SIZE;
        }
        y += TILE_SIZE;
    }

    return LayerBufferSet { buffers: move dvec::unwrap(move new_buffers) };
}

<commit_msg>gfx: Turn on 512x512 tiles once again, and work around the layer buffer badness<commit_after>use gfx::display_list::DisplayList;
use gfx::compositor::{LayerBuffer, LayerBufferSet};
use opts::Opts;

use azure::AzFloat;
use azure::azure_hl::{B8G8R8A8, DrawTarget};
use core::libc::c_int;
use geom::matrix2d::Matrix2D;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;

const TILE_SIZE: uint = 512;

pub struct RenderLayer {
    display_list: DisplayList,
    size: Size2D<uint>
}

/// Given a layer and a buffer, either reuses the buffer (if it's of the right size and format)
/// or creates a new buffer (if it's not of the appropriate size and format) and invokes the
/// given callback with the render layer and the buffer. Returns the resulting layer buffer (which
/// might be the old layer buffer if it had the appropriate size and format).
pub fn render_layers(layer: &RenderLayer,
                     buffer_set: LayerBufferSet,
                     opts: &Opts,
                     f: &fn(layer: &RenderLayer, buffer: &LayerBuffer) -> bool) -> LayerBufferSet {
    let mut buffers = match move buffer_set { LayerBufferSet { buffers: move b } => move b };

    // FIXME: Try not to create a new array here.
    let new_buffers = dvec::DVec();

    // Divide up the layer into tiles.
    let mut y = 0;
    while y < layer.size.height {
        let mut x = 0;
        while x < layer.size.width {
            // Figure out the dimension of this tile.
            let right = uint::min(x + TILE_SIZE, layer.size.width);
            let bottom = uint::min(y + TILE_SIZE, layer.size.height);
            let width = right - x;
            let height = bottom - y;

            // Round the width up the nearest 32 pixels for DMA on the Mac.
            let mut stride = width;
            if stride % 32 != 0 {
                stride = (stride & !(32 - 1)) + 32;
            }
            assert stride % 32 == 0;
            assert stride >= width;

            debug!("tile stride %u", stride);

            let tile_rect = Rect(Point2D(x, y), Size2D(width, height));

            let buffer;
            // FIXME: Try harder to search for a matching tile.
            // FIXME: Don't use shift; it's bad for perf. Maybe reverse and pop.
            /*if buffers.len() != 0 && buffers[0].rect == tile_rect {
                debug!("reusing tile, (%u, %u)", x, y);
                buffer = buffers.shift();
            } else {*/
                // Create a new buffer.
                debug!("creating tile, (%u, %u)", x, y);

                let size = Size2D(stride as i32, height as i32);

                let mut data: ~[u8] = ~[0];
                let offset;
                unsafe {
                    // FIXME: Evil black magic to ensure that we don't perform a slow memzero
                    // of this buffer. This should be made safe.

                    let align = 256;

                    let len = ((size.width * size.height * 4) as uint) + align;
                    vec::reserve(&mut data, len);
                    vec::raw::set_len(&mut data, len);

                    // Round up to the nearest 32-byte-aligned address for DMA on the Mac.
                    let addr: uint = cast::transmute(ptr::to_unsafe_ptr(&data[0]));
                    if addr % align == 0 {
                        offset = 0;
                    } else {
                        offset = align - addr % align;
                    }

                    debug!("tile offset is %u, expected addr is %x", offset, addr + offset);
                }

                buffer = LayerBuffer {
                    draw_target: DrawTarget::new_with_data(opts.render_backend,
                                                           move data,
                                                           offset,
                                                           size,
                                                           size.width * 4,
                                                           B8G8R8A8),
                    rect: tile_rect,
                    stride: stride
                };
            //}

            let _ = f(layer, &buffer);
            new_buffers.push(move buffer);

            x += TILE_SIZE;
        }
        y += TILE_SIZE;
    }

    return LayerBufferSet { buffers: move dvec::unwrap(move new_buffers) };
}

<|endoftext|>


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

// ignore-tidy-linelength
// compile-flags: -Z verbose -Z mir-emit-validate=1

// Make sure unsafe fns and fns with an unsafe block only get restricted validation.

unsafe fn write_42(x: *mut i32) -> bool {
    *x = 42;
    true
}

fn test(x: &mut i32) {
    unsafe { write_42(x) };
}

fn main() {
    test(&mut 0);

    let test_closure = unsafe { |x: &mut i32| write_42(x) };
    test_closure(&mut 0);
}

// FIXME: Also test code generated inside the closure, make sure it only does restricted validation
// because it is entirely inside an unsafe block.  Unfortunately, the interesting lines of code also
// contain name of the source file, so we cannot test for it.

// END RUST SOURCE
// START rustc.node4.EraseRegions.after.mir
// fn write_42(_1: *mut i32) -> bool {
//     bb0: {
//         Validate(Acquire, [_1: *mut i32]);
//         Validate(Release, [_1: *mut i32]);
//         return;
//     }
// }
// END rustc.node4.EraseRegions.after.mir
// START rustc.node17.EraseRegions.after.mir
// fn test(_1: &ReErased mut i32) -> () {
//     bb0: {
//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]);
//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]);
//         _3 = const write_42(_4) -> bb1;
//     }
//     bb1: {
//         Validate(Acquire, [_3: bool]);
//         Validate(Release, [_3: bool]);
//     }
// }
// END rustc.node17.EraseRegions.after.mir
<commit_msg>add a closure inside an unsafe fn to the tests<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength
// compile-flags: -Z verbose -Z mir-emit-validate=1

// Make sure unsafe fns and fns with an unsafe block only get restricted validation.

unsafe fn write_42(x: *mut i32) -> bool {
    let test_closure = |x: *mut i32| *x = 23;
    test_closure(x);
    *x = 42;
    true
}

fn test(x: &mut i32) {
    unsafe { write_42(x) };
}

fn main() {
    test(&mut 0);

    let test_closure = unsafe { |x: &mut i32| write_42(x) };
    test_closure(&mut 0);
}

// FIXME: Also test code generated inside the closure, make sure it only does restricted validation
// because it is entirely inside an unsafe block.  Unfortunately, the interesting lines of code also
// contain name of the source file, so we cannot test for it.

// END RUST SOURCE
// START rustc.node4.EraseRegions.after.mir
// fn write_42(_1: *mut i32) -> bool {
//     bb0: {
//         Validate(Acquire, [_1: *mut i32]);
//         Validate(Release, [_1: *mut i32]);
//         return;
//     }
// }
// END rustc.node4.EraseRegions.after.mir
// START rustc.node31.EraseRegions.after.mir
// fn test(_1: &ReErased mut i32) -> () {
//     bb0: {
//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]);
//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), node: DefIndex(4) => validate_4/8cd878b::test[0] }, BrAnon(0)) mut i32]);
//         _3 = const write_42(_4) -> bb1;
//     }
//     bb1: {
//         Validate(Acquire, [_3: bool]);
//         Validate(Release, [_3: bool]);
//     }
// }
// END rustc.node31.EraseRegions.after.mir
<|endoftext|>


<commit_before>//! ARMv6K Nintendo 3DS C Newlib definitions

pub type c_char = u8;
pub type c_long = i32;
pub type c_ulong = u32;

pub type wchar_t = ::c_uint;

pub type in_port_t = ::c_ushort;
pub type u_register_t = ::c_uint;
pub type u_char = ::c_uchar;
pub type u_short = ::c_ushort;
pub type u_int = ::c_uint;
pub type u_long = c_ulong;
pub type ushort = ::c_ushort;
pub type uint = ::c_uint;
pub type ulong = c_ulong;
pub type clock_t = c_ulong;
pub type daddr_t = c_long;
pub type caddr_t = *mut c_char;
pub type sbintime_t = ::c_longlong;

// External implementations are needed to use networking and threading.
s! {
    pub struct sockaddr {
        pub sa_family: ::sa_family_t,
        pub sa_data: [::c_char; 26usize],
    }

    pub struct sockaddr_storage {
        pub ss_family: ::sa_family_t,
        pub __ss_padding: [::c_char; 26usize],
    }

    pub struct sockaddr_in {
        pub sin_family: ::sa_family_t,
        pub sin_port: in_port_t,
        pub sin_addr: ::in_addr,
    }

    pub struct sockaddr_in6 {
        pub sin6_family: ::sa_family_t,
        pub sin6_port: ::in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }

    pub struct sockaddr_un {
        pub sun_len: ::c_uchar,
        pub sun_family: ::sa_family_t,
        pub sun_path: [::c_char; 104usize],
    }
}

pub const SIGEV_NONE: ::c_int = 1;
pub const SIGEV_SIGNAL: ::c_int = 2;
pub const SIGEV_THREAD: ::c_int = 3;
pub const SA_NOCLDSTOP: ::c_int = 1;
pub const MINSIGSTKSZ: ::c_int = 2048;
pub const SIGSTKSZ: ::c_int = 8192;
pub const SS_ONSTACK: ::c_int = 1;
pub const SS_DISABLE: ::c_int = 2;
pub const SIG_SETMASK: ::c_int = 0;
pub const SIG_BLOCK: ::c_int = 1;
pub const SIG_UNBLOCK: ::c_int = 2;
pub const SIGHUP: ::c_int = 1;
pub const SIGINT: ::c_int = 2;
pub const SIGQUIT: ::c_int = 3;
pub const SIGILL: ::c_int = 4;
pub const SIGTRAP: ::c_int = 5;
pub const SIGABRT: ::c_int = 6;
pub const SIGEMT: ::c_int = 7;
pub const SIGFPE: ::c_int = 8;
pub const SIGKILL: ::c_int = 9;
pub const SIGBUS: ::c_int = 10;
pub const SIGSEGV: ::c_int = 11;
pub const SIGSYS: ::c_int = 12;
pub const SIGPIPE: ::c_int = 13;
pub const SIGALRM: ::c_int = 14;
pub const SIGTERM: ::c_int = 15;
pub const SIGURG: ::c_int = 16;
pub const SIGSTOP: ::c_int = 17;
pub const SIGTSTP: ::c_int = 18;
pub const SIGCONT: ::c_int = 19;
pub const SIGCHLD: ::c_int = 20;
pub const SIGCLD: ::c_int = 20;
pub const SIGTTIN: ::c_int = 21;
pub const SIGTTOU: ::c_int = 22;
pub const SIGIO: ::c_int = 23;
pub const SIGPOLL: ::c_int = 23;
pub const SIGXCPU: ::c_int = 24;
pub const SIGXFSZ: ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF: ::c_int = 27;
pub const SIGWINCH: ::c_int = 28;
pub const SIGLOST: ::c_int = 29;
pub const SIGUSR1: ::c_int = 30;
pub const SIGUSR2: ::c_int = 31;
pub const NSIG: ::c_int = 32;
pub const CLOCK_ENABLED: ::c_uint = 1;
pub const CLOCK_DISABLED: ::c_uint = 0;
pub const CLOCK_ALLOWED: ::c_uint = 1;
pub const CLOCK_DISALLOWED: ::c_uint = 0;
pub const TIMER_ABSTIME: ::c_uint = 4;
pub const SOL_SOCKET: ::c_int = 65535;
pub const MSG_OOB: ::c_int = 1;
pub const MSG_PEEK: ::c_int = 2;
pub const MSG_DONTWAIT: ::c_int = 4;
pub const MSG_DONTROUTE: ::c_int = 0;
pub const MSG_WAITALL: ::c_int = 0;
pub const MSG_MORE: ::c_int = 0;
pub const MSG_NOSIGNAL: ::c_int = 0;
pub const SOL_CONFIG: ::c_uint = 65534;

pub const _SC_PAGESIZE: ::c_int = 8;
pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51;

pub const PTHREAD_STACK_MIN: ::size_t = 4096;
pub const WNOHANG: ::c_int = 1;

pub const POLLIN: ::c_short = 0x0001;
pub const POLLPRI: ::c_short = 0x0002;
pub const POLLOUT: ::c_short = 0x0004;
pub const POLLRDNORM: ::c_short = 0x0040;
pub const POLLWRNORM: ::c_short = POLLOUT;
pub const POLLRDBAND: ::c_short = 0x0080;
pub const POLLWRBAND: ::c_short = 0x0100;
pub const POLLERR: ::c_short = 0x0008;
pub const POLLHUP: ::c_short = 0x0010;
pub const POLLNVAL: ::c_short = 0x0020;

pub const EAI_AGAIN: ::c_int = 2;
pub const EAI_BADFLAGS: ::c_int = 3;
pub const EAI_FAIL: ::c_int = 4;
pub const EAI_SERVICE: ::c_int = 9;
pub const EAI_SYSTEM: ::c_int = 11;
pub const EAI_BADHINTS: ::c_int = 12;
pub const EAI_PROTOCOL: ::c_int = 13;
pub const EAI_OVERFLOW: ::c_int = 14;
pub const EAI_MAX: ::c_int = 15;

pub const AF_UNIX: ::c_int = 1;
pub const AF_INET6: ::c_int = 23;

pub const FIONBIO: ::c_ulong = 1;

pub const RTLD_DEFAULT: *mut ::c_void = 0 as *mut ::c_void;

// Horizon OS works doesn't or can't hold any of this information
safe_f! {
    pub {const} fn WIFSTOPPED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WSTOPSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFCONTINUED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WIFSIGNALED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WTERMSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFEXITED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WEXITSTATUS(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WCOREDUMP(_status: ::c_int) -> bool {
        false
    }
}

extern "C" {
    pub fn pthread_create(
        native: *mut ::pthread_t,
        attr: *const ::pthread_attr_t,
        f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void,
        value: *mut ::c_void,
    ) -> ::c_int;

    pub fn gethostid() -> ::c_long;
}
<commit_msg>Auto merge of #2715 - AzureMarker:feature/horizon-pthread, r=Amanieu<commit_after>//! ARMv6K Nintendo 3DS C Newlib definitions

pub type c_char = u8;
pub type c_long = i32;
pub type c_ulong = u32;

pub type wchar_t = ::c_uint;

pub type in_port_t = ::c_ushort;
pub type u_register_t = ::c_uint;
pub type u_char = ::c_uchar;
pub type u_short = ::c_ushort;
pub type u_int = ::c_uint;
pub type u_long = c_ulong;
pub type ushort = ::c_ushort;
pub type uint = ::c_uint;
pub type ulong = c_ulong;
pub type clock_t = c_ulong;
pub type daddr_t = c_long;
pub type caddr_t = *mut c_char;
pub type sbintime_t = ::c_longlong;

// External implementations are needed to use networking and threading.
s! {
    pub struct sockaddr {
        pub sa_family: ::sa_family_t,
        pub sa_data: [::c_char; 26usize],
    }

    pub struct sockaddr_storage {
        pub ss_family: ::sa_family_t,
        pub __ss_padding: [::c_char; 26usize],
    }

    pub struct sockaddr_in {
        pub sin_family: ::sa_family_t,
        pub sin_port: in_port_t,
        pub sin_addr: ::in_addr,
    }

    pub struct sockaddr_in6 {
        pub sin6_family: ::sa_family_t,
        pub sin6_port: ::in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }

    pub struct sockaddr_un {
        pub sun_len: ::c_uchar,
        pub sun_family: ::sa_family_t,
        pub sun_path: [::c_char; 104usize],
    }

    pub struct sched_param {
        pub sched_priority: ::c_int,
    }
}

pub const SIGEV_NONE: ::c_int = 1;
pub const SIGEV_SIGNAL: ::c_int = 2;
pub const SIGEV_THREAD: ::c_int = 3;
pub const SA_NOCLDSTOP: ::c_int = 1;
pub const MINSIGSTKSZ: ::c_int = 2048;
pub const SIGSTKSZ: ::c_int = 8192;
pub const SS_ONSTACK: ::c_int = 1;
pub const SS_DISABLE: ::c_int = 2;
pub const SIG_SETMASK: ::c_int = 0;
pub const SIG_BLOCK: ::c_int = 1;
pub const SIG_UNBLOCK: ::c_int = 2;
pub const SIGHUP: ::c_int = 1;
pub const SIGINT: ::c_int = 2;
pub const SIGQUIT: ::c_int = 3;
pub const SIGILL: ::c_int = 4;
pub const SIGTRAP: ::c_int = 5;
pub const SIGABRT: ::c_int = 6;
pub const SIGEMT: ::c_int = 7;
pub const SIGFPE: ::c_int = 8;
pub const SIGKILL: ::c_int = 9;
pub const SIGBUS: ::c_int = 10;
pub const SIGSEGV: ::c_int = 11;
pub const SIGSYS: ::c_int = 12;
pub const SIGPIPE: ::c_int = 13;
pub const SIGALRM: ::c_int = 14;
pub const SIGTERM: ::c_int = 15;
pub const SIGURG: ::c_int = 16;
pub const SIGSTOP: ::c_int = 17;
pub const SIGTSTP: ::c_int = 18;
pub const SIGCONT: ::c_int = 19;
pub const SIGCHLD: ::c_int = 20;
pub const SIGCLD: ::c_int = 20;
pub const SIGTTIN: ::c_int = 21;
pub const SIGTTOU: ::c_int = 22;
pub const SIGIO: ::c_int = 23;
pub const SIGPOLL: ::c_int = 23;
pub const SIGXCPU: ::c_int = 24;
pub const SIGXFSZ: ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF: ::c_int = 27;
pub const SIGWINCH: ::c_int = 28;
pub const SIGLOST: ::c_int = 29;
pub const SIGUSR1: ::c_int = 30;
pub const SIGUSR2: ::c_int = 31;
pub const NSIG: ::c_int = 32;
pub const CLOCK_ENABLED: ::c_uint = 1;
pub const CLOCK_DISABLED: ::c_uint = 0;
pub const CLOCK_ALLOWED: ::c_uint = 1;
pub const CLOCK_DISALLOWED: ::c_uint = 0;
pub const TIMER_ABSTIME: ::c_uint = 4;
pub const SOL_SOCKET: ::c_int = 65535;
pub const MSG_OOB: ::c_int = 1;
pub const MSG_PEEK: ::c_int = 2;
pub const MSG_DONTWAIT: ::c_int = 4;
pub const MSG_DONTROUTE: ::c_int = 0;
pub const MSG_WAITALL: ::c_int = 0;
pub const MSG_MORE: ::c_int = 0;
pub const MSG_NOSIGNAL: ::c_int = 0;
pub const SOL_CONFIG: ::c_uint = 65534;

pub const _SC_PAGESIZE: ::c_int = 8;
pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51;

pub const PTHREAD_STACK_MIN: ::size_t = 4096;
pub const WNOHANG: ::c_int = 1;

pub const POLLIN: ::c_short = 0x0001;
pub const POLLPRI: ::c_short = 0x0002;
pub const POLLOUT: ::c_short = 0x0004;
pub const POLLRDNORM: ::c_short = 0x0040;
pub const POLLWRNORM: ::c_short = POLLOUT;
pub const POLLRDBAND: ::c_short = 0x0080;
pub const POLLWRBAND: ::c_short = 0x0100;
pub const POLLERR: ::c_short = 0x0008;
pub const POLLHUP: ::c_short = 0x0010;
pub const POLLNVAL: ::c_short = 0x0020;

pub const EAI_AGAIN: ::c_int = 2;
pub const EAI_BADFLAGS: ::c_int = 3;
pub const EAI_FAIL: ::c_int = 4;
pub const EAI_SERVICE: ::c_int = 9;
pub const EAI_SYSTEM: ::c_int = 11;
pub const EAI_BADHINTS: ::c_int = 12;
pub const EAI_PROTOCOL: ::c_int = 13;
pub const EAI_OVERFLOW: ::c_int = 14;
pub const EAI_MAX: ::c_int = 15;

pub const AF_UNIX: ::c_int = 1;
pub const AF_INET6: ::c_int = 23;

pub const FIONBIO: ::c_ulong = 1;

pub const RTLD_DEFAULT: *mut ::c_void = 0 as *mut ::c_void;

// For pthread get/setschedparam
pub const SCHED_FIFO: ::c_int = 1;
pub const SCHED_RR: ::c_int = 2;

// Horizon OS works doesn't or can't hold any of this information
safe_f! {
    pub {const} fn WIFSTOPPED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WSTOPSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFCONTINUED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WIFSIGNALED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WTERMSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFEXITED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WEXITSTATUS(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WCOREDUMP(_status: ::c_int) -> bool {
        false
    }
}

extern "C" {
    pub fn pthread_create(
        native: *mut ::pthread_t,
        attr: *const ::pthread_attr_t,
        f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void,
        value: *mut ::c_void,
    ) -> ::c_int;

    pub fn pthread_attr_getschedparam(
        attr: *const ::pthread_attr_t,
        param: *mut sched_param,
    ) -> ::c_int;

    pub fn pthread_attr_setschedparam(
        attr: *mut ::pthread_attr_t,
        param: *const sched_param,
    ) -> ::c_int;

    pub fn pthread_attr_getprocessorid_np(
        attr: *const ::pthread_attr_t,
        processor_id: *mut ::c_int,
    ) -> ::c_int;

    pub fn pthread_attr_setprocessorid_np(
        attr: *mut ::pthread_attr_t,
        processor_id: ::c_int,
    ) -> ::c_int;

    pub fn pthread_getschedparam(
        native: ::pthread_t,
        policy: *mut ::c_int,
        param: *mut ::sched_param,
    ) -> ::c_int;

    pub fn pthread_setschedparam(
        native: ::pthread_t,
        policy: ::c_int,
        param: *const ::sched_param,
    ) -> ::c_int;

    pub fn pthread_getprocessorid_np() -> ::c_int;

    pub fn gethostid() -> ::c_long;
}
<|endoftext|>


<commit_before>//! ARMv6K Nintendo 3DS C Newlib definitions

pub type c_char = u8;
pub type c_long = i32;
pub type c_ulong = u32;

pub type wchar_t = ::c_uint;

pub type in_port_t = ::c_ushort;
pub type u_register_t = ::c_uint;
pub type u_char = ::c_uchar;
pub type u_short = ::c_ushort;
pub type u_int = ::c_uint;
pub type u_long = c_ulong;
pub type ushort = ::c_ushort;
pub type uint = ::c_uint;
pub type ulong = c_ulong;
pub type clock_t = c_ulong;
pub type daddr_t = c_long;
pub type caddr_t = *mut c_char;
pub type sbintime_t = ::c_longlong;

// External implementations are needed to use networking and threading.
s! {
    pub struct sockaddr {
        pub sa_family: ::sa_family_t,
        pub sa_data: [::c_char; 26usize],
    }

    pub struct sockaddr_storage {
        pub ss_family: ::sa_family_t,
        pub __ss_padding: [::c_char; 26usize],
    }

    pub struct sockaddr_in {
        pub sin_family: ::sa_family_t,
        pub sin_port: in_port_t,
        pub sin_addr: ::in_addr,
    }

    pub struct sockaddr_in6 {
        pub sin6_family: ::sa_family_t,
        pub sin6_port: ::in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }

    pub struct sockaddr_un {
        pub sun_len: ::c_uchar,
        pub sun_family: ::sa_family_t,
        pub sun_path: [::c_char; 104usize],
    }
}

pub const SIGEV_NONE: ::c_int = 1;
pub const SIGEV_SIGNAL: ::c_int = 2;
pub const SIGEV_THREAD: ::c_int = 3;
pub const SA_NOCLDSTOP: ::c_int = 1;
pub const MINSIGSTKSZ: ::c_int = 2048;
pub const SIGSTKSZ: ::c_int = 8192;
pub const SS_ONSTACK: ::c_int = 1;
pub const SS_DISABLE: ::c_int = 2;
pub const SIG_SETMASK: ::c_int = 0;
pub const SIG_BLOCK: ::c_int = 1;
pub const SIG_UNBLOCK: ::c_int = 2;
pub const SIGHUP: ::c_int = 1;
pub const SIGINT: ::c_int = 2;
pub const SIGQUIT: ::c_int = 3;
pub const SIGILL: ::c_int = 4;
pub const SIGTRAP: ::c_int = 5;
pub const SIGABRT: ::c_int = 6;
pub const SIGEMT: ::c_int = 7;
pub const SIGFPE: ::c_int = 8;
pub const SIGKILL: ::c_int = 9;
pub const SIGBUS: ::c_int = 10;
pub const SIGSEGV: ::c_int = 11;
pub const SIGSYS: ::c_int = 12;
pub const SIGPIPE: ::c_int = 13;
pub const SIGALRM: ::c_int = 14;
pub const SIGTERM: ::c_int = 15;
pub const SIGURG: ::c_int = 16;
pub const SIGSTOP: ::c_int = 17;
pub const SIGTSTP: ::c_int = 18;
pub const SIGCONT: ::c_int = 19;
pub const SIGCHLD: ::c_int = 20;
pub const SIGCLD: ::c_int = 20;
pub const SIGTTIN: ::c_int = 21;
pub const SIGTTOU: ::c_int = 22;
pub const SIGIO: ::c_int = 23;
pub const SIGPOLL: ::c_int = 23;
pub const SIGXCPU: ::c_int = 24;
pub const SIGXFSZ: ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF: ::c_int = 27;
pub const SIGWINCH: ::c_int = 28;
pub const SIGLOST: ::c_int = 29;
pub const SIGUSR1: ::c_int = 30;
pub const SIGUSR2: ::c_int = 31;
pub const NSIG: ::c_int = 32;
pub const CLOCK_ENABLED: ::c_uint = 1;
pub const CLOCK_DISABLED: ::c_uint = 0;
pub const CLOCK_ALLOWED: ::c_uint = 1;
pub const CLOCK_DISALLOWED: ::c_uint = 0;
pub const TIMER_ABSTIME: ::c_uint = 4;
pub const SOL_SOCKET: ::c_int = 65535;
pub const MSG_OOB: ::c_int = 1;
pub const MSG_PEEK: ::c_int = 2;
pub const MSG_DONTWAIT: ::c_int = 4;
pub const MSG_DONTROUTE: ::c_int = 0;
pub const MSG_WAITALL: ::c_int = 0;
pub const MSG_MORE: ::c_int = 0;
pub const MSG_NOSIGNAL: ::c_int = 0;
pub const SOL_CONFIG: ::c_uint = 65534;

pub const _SC_PAGESIZE: ::c_int = 8;
pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51;

pub const PTHREAD_STACK_MIN: ::size_t = 4096;
pub const WNOHANG: ::c_int = 1;

pub const POLLIN: ::c_short = 0x0001;
pub const POLLPRI: ::c_short = 0x0002;
pub const POLLOUT: ::c_short = 0x0004;
pub const POLLRDNORM: ::c_short = 0x0040;
pub const POLLWRNORM: ::c_short = POLLOUT;
pub const POLLRDBAND: ::c_short = 0x0080;
pub const POLLWRBAND: ::c_short = 0x0100;
pub const POLLERR: ::c_short = 0x0008;
pub const POLLHUP: ::c_short = 0x0010;
pub const POLLNVAL: ::c_short = 0x0020;

pub const EAI_AGAIN: ::c_int = 2;
pub const EAI_BADFLAGS: ::c_int = 3;
pub const EAI_FAIL: ::c_int = 4;
pub const EAI_SERVICE: ::c_int = 9;
pub const EAI_SYSTEM: ::c_int = 11;
pub const EAI_BADHINTS: ::c_int = 12;
pub const EAI_PROTOCOL: ::c_int = 13;
pub const EAI_OVERFLOW: ::c_int = 14;
pub const EAI_MAX: ::c_int = 15;

pub const AF_UNIX: ::c_int = 1;
pub const AF_INET6: ::c_int = 23;

pub const FIONBIO: ::c_ulong = 1;

pub const RTLD_DEFAULT: *mut ::c_void = 0 as *mut ::c_void;

// Horizon OS works doesn't or can't hold any of this information
safe_f! {
    pub {const} fn WIFSTOPPED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WSTOPSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFCONTINUED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WIFSIGNALED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WTERMSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFEXITED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WEXITSTATUS(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WCOREDUMP(_status: ::c_int) -> bool {
        false
    }
}

extern "C" {
    pub fn pthread_create(
        native: *mut ::pthread_t,
        attr: *const ::pthread_attr_t,
        f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void,
        value: *mut ::c_void,
    ) -> ::c_int;

    pub fn gethostid() -> ::c_long;
}
<commit_msg>Add getrandom call on horizon OS<commit_after>//! ARMv6K Nintendo 3DS C Newlib definitions

pub type c_char = u8;
pub type c_long = i32;
pub type c_ulong = u32;

pub type wchar_t = ::c_uint;

pub type in_port_t = ::c_ushort;
pub type u_register_t = ::c_uint;
pub type u_char = ::c_uchar;
pub type u_short = ::c_ushort;
pub type u_int = ::c_uint;
pub type u_long = c_ulong;
pub type ushort = ::c_ushort;
pub type uint = ::c_uint;
pub type ulong = c_ulong;
pub type clock_t = c_ulong;
pub type daddr_t = c_long;
pub type caddr_t = *mut c_char;
pub type sbintime_t = ::c_longlong;

// External implementations are needed to use networking and threading.
s! {
    pub struct sockaddr {
        pub sa_family: ::sa_family_t,
        pub sa_data: [::c_char; 26usize],
    }

    pub struct sockaddr_storage {
        pub ss_family: ::sa_family_t,
        pub __ss_padding: [::c_char; 26usize],
    }

    pub struct sockaddr_in {
        pub sin_family: ::sa_family_t,
        pub sin_port: in_port_t,
        pub sin_addr: ::in_addr,
    }

    pub struct sockaddr_in6 {
        pub sin6_family: ::sa_family_t,
        pub sin6_port: ::in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }

    pub struct sockaddr_un {
        pub sun_len: ::c_uchar,
        pub sun_family: ::sa_family_t,
        pub sun_path: [::c_char; 104usize],
    }
}

pub const SIGEV_NONE: ::c_int = 1;
pub const SIGEV_SIGNAL: ::c_int = 2;
pub const SIGEV_THREAD: ::c_int = 3;
pub const SA_NOCLDSTOP: ::c_int = 1;
pub const MINSIGSTKSZ: ::c_int = 2048;
pub const SIGSTKSZ: ::c_int = 8192;
pub const SS_ONSTACK: ::c_int = 1;
pub const SS_DISABLE: ::c_int = 2;
pub const SIG_SETMASK: ::c_int = 0;
pub const SIG_BLOCK: ::c_int = 1;
pub const SIG_UNBLOCK: ::c_int = 2;
pub const SIGHUP: ::c_int = 1;
pub const SIGINT: ::c_int = 2;
pub const SIGQUIT: ::c_int = 3;
pub const SIGILL: ::c_int = 4;
pub const SIGTRAP: ::c_int = 5;
pub const SIGABRT: ::c_int = 6;
pub const SIGEMT: ::c_int = 7;
pub const SIGFPE: ::c_int = 8;
pub const SIGKILL: ::c_int = 9;
pub const SIGBUS: ::c_int = 10;
pub const SIGSEGV: ::c_int = 11;
pub const SIGSYS: ::c_int = 12;
pub const SIGPIPE: ::c_int = 13;
pub const SIGALRM: ::c_int = 14;
pub const SIGTERM: ::c_int = 15;
pub const SIGURG: ::c_int = 16;
pub const SIGSTOP: ::c_int = 17;
pub const SIGTSTP: ::c_int = 18;
pub const SIGCONT: ::c_int = 19;
pub const SIGCHLD: ::c_int = 20;
pub const SIGCLD: ::c_int = 20;
pub const SIGTTIN: ::c_int = 21;
pub const SIGTTOU: ::c_int = 22;
pub const SIGIO: ::c_int = 23;
pub const SIGPOLL: ::c_int = 23;
pub const SIGXCPU: ::c_int = 24;
pub const SIGXFSZ: ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF: ::c_int = 27;
pub const SIGWINCH: ::c_int = 28;
pub const SIGLOST: ::c_int = 29;
pub const SIGUSR1: ::c_int = 30;
pub const SIGUSR2: ::c_int = 31;
pub const NSIG: ::c_int = 32;
pub const CLOCK_ENABLED: ::c_uint = 1;
pub const CLOCK_DISABLED: ::c_uint = 0;
pub const CLOCK_ALLOWED: ::c_uint = 1;
pub const CLOCK_DISALLOWED: ::c_uint = 0;
pub const TIMER_ABSTIME: ::c_uint = 4;
pub const SOL_SOCKET: ::c_int = 65535;
pub const MSG_OOB: ::c_int = 1;
pub const MSG_PEEK: ::c_int = 2;
pub const MSG_DONTWAIT: ::c_int = 4;
pub const MSG_DONTROUTE: ::c_int = 0;
pub const MSG_WAITALL: ::c_int = 0;
pub const MSG_MORE: ::c_int = 0;
pub const MSG_NOSIGNAL: ::c_int = 0;
pub const SOL_CONFIG: ::c_uint = 65534;

pub const _SC_PAGESIZE: ::c_int = 8;
pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51;

pub const PTHREAD_STACK_MIN: ::size_t = 4096;
pub const WNOHANG: ::c_int = 1;

pub const POLLIN: ::c_short = 0x0001;
pub const POLLPRI: ::c_short = 0x0002;
pub const POLLOUT: ::c_short = 0x0004;
pub const POLLRDNORM: ::c_short = 0x0040;
pub const POLLWRNORM: ::c_short = POLLOUT;
pub const POLLRDBAND: ::c_short = 0x0080;
pub const POLLWRBAND: ::c_short = 0x0100;
pub const POLLERR: ::c_short = 0x0008;
pub const POLLHUP: ::c_short = 0x0010;
pub const POLLNVAL: ::c_short = 0x0020;

pub const EAI_AGAIN: ::c_int = 2;
pub const EAI_BADFLAGS: ::c_int = 3;
pub const EAI_FAIL: ::c_int = 4;
pub const EAI_SERVICE: ::c_int = 9;
pub const EAI_SYSTEM: ::c_int = 11;
pub const EAI_BADHINTS: ::c_int = 12;
pub const EAI_PROTOCOL: ::c_int = 13;
pub const EAI_OVERFLOW: ::c_int = 14;
pub const EAI_MAX: ::c_int = 15;

pub const AF_UNIX: ::c_int = 1;
pub const AF_INET6: ::c_int = 23;

pub const FIONBIO: ::c_ulong = 1;

pub const RTLD_DEFAULT: *mut ::c_void = 0 as *mut ::c_void;

// Horizon OS works doesn't or can't hold any of this information
safe_f! {
    pub {const} fn WIFSTOPPED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WSTOPSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFCONTINUED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WIFSIGNALED(_status: ::c_int) -> bool {
        false
    }

    pub {const} fn WTERMSIG(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WIFEXITED(_status: ::c_int) -> bool {
        true
    }

    pub {const} fn WEXITSTATUS(_status: ::c_int) -> ::c_int {
        0
    }

    pub {const} fn WCOREDUMP(_status: ::c_int) -> bool {
        false
    }
}

extern "C" {
    pub fn pthread_create(
        native: *mut ::pthread_t,
        attr: *const ::pthread_attr_t,
        f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void,
        value: *mut ::c_void,
    ) -> ::c_int;

    pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;

    pub fn gethostid() -> ::c_long;
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::HashMap;
use std::convert::TryInto;
use std::env;
use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak};

use super::super::super::target::bytecode;
use super::super::frame::Closure;
use super::super::gc::GcTrace;
use super::super::value::Value;
use super::LoadedFunction;

pub struct InnerLoadedModule {
    /// The name of the module. This should almost always be the canonicalized
    /// path to the source file.
    name: String,
    /// The source code of the module.
    source: String,
    functions: Vec<LoadedFunction>,
    /// The module's static scope; it holds:
    ///   - Imports
    ///   - Bound or exported variables
    ///   - Bound or exported functions
    static_closure: Closure,
    // A module loaded into memory is uninitialized. Only after it has been
    // evaluated (and imports and exports resolved) is it initialized.
    initialized: bool,
    exports: HashMap<String, Value>,
}

impl InnerLoadedModule {
    fn empty(name: String, source: String, builtins_closure: Option<Closure>) -> Self {
        Self {
            name,
            source,
            functions: vec![],
            static_closure: Closure::new_static(builtins_closure),
            initialized: false,
            exports: HashMap::new(),
        }
    }
}

// Opaque wrapper around a reference-counted loaded unit.
#[derive(Clone)]
pub struct LoadedModule(Rc<RefCell<InnerLoadedModule>>);

impl LoadedModule {
    pub fn from_bytecode(
        module: bytecode::layout::Module,
        name: String,
        source: String,
        builtins_closure: Option<Closure>,
    ) -> Self {
        let inner = Rc::new(RefCell::new(InnerLoadedModule::empty(
            name,
            source,
            builtins_closure,
        )));
        let functions = module
            .functions
            .into_iter()
            .map(|function| {
                let weak_loaded_module = Rc::downgrade(&inner);
                LoadedFunction::new(weak_loaded_module, function)
            })
            .collect::<Vec<LoadedFunction>>();
        inner.borrow_mut().functions = functions;
        Self(inner)
    }

    pub fn builtin(name: String) -> Self {
        let inner = Rc::new(RefCell::new(InnerLoadedModule::empty(
            name,
            "".to_string(),
            None,
        )));
        Self(inner)
    }

    pub fn name(&self) -> String {
        self.0.borrow().name.clone()
    }

    pub fn source(&self) -> String {
        self.0.borrow().source.clone()
    }

    /// Returns a path to the directory in which relative imports can be
    /// processed for this module.
    pub fn relative_import_path(&self) -> Option<PathBuf> {
        let name = self.name();
        // FIXME: Make REPL detection and handling smarter.
        if name.starts_with("repl[") {
            return env::current_dir().ok();
        }
        let path = Path::new(&name);
        if path.is_file() {
            return path.parent().map(Path::to_path_buf);
        }
        None
    }

    pub fn main(&self) -> LoadedFunction {
        self.0.borrow().functions[0].clone()
    }

    pub fn static_closure(&self) -> Closure {
        self.0.borrow().static_closure.clone()
    }

    pub fn initialized(&self) -> bool {
        self.0.borrow().initialized
    }

    pub fn set_initialized(&self) {
        let mut inner = self.0.borrow_mut();
        inner.initialized = true;
    }

    /// Should only be called by the REPL!
    pub fn override_static_closure(&self, static_closure: Closure) {
        self.0.borrow_mut().static_closure = static_closure;
    }

    pub fn function(&self, id: u16) -> LoadedFunction {
        self.0
            .borrow()
            .functions
            .iter()
            .find(|&function| function.id() == id)
            .expect("Function not found")
            .clone()
    }

    pub fn get_export<N: AsRef<str>>(&self, name: N) -> Option<Value> {
        self.0
            .borrow_mut()
            .exports
            .get(name.as_ref())
            .map(Clone::clone)
    }

    pub fn set_export<N: Into<String>>(&self, name: N, value: Value) {
        self.0.borrow_mut().exports.insert(name.into(), value);
    }
}

pub type WeakLoadedModule = Weak<RefCell<InnerLoadedModule>>;

impl TryInto<LoadedModule> for WeakLoadedModule {
    type Error = ();

    fn try_into(self) -> Result<LoadedModule, Self::Error> {
        match self.upgrade() {
            Some(inner) => Ok(LoadedModule(inner)),
            None => Err(()),
        }
    }
}

impl GcTrace for LoadedModule {
    fn trace(&self) {
        let inner = self.0.borrow();
        inner.static_closure.trace();
        for export in inner.exports.values() {
            export.trace();
        }
    }
}
<commit_msg>Add more helpful panic message when trying to get main function on empty module<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use std::convert::TryInto;
use std::env;
use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak};

use super::super::super::target::bytecode;
use super::super::frame::Closure;
use super::super::gc::GcTrace;
use super::super::value::Value;
use super::LoadedFunction;

pub struct InnerLoadedModule {
    /// The name of the module. This should almost always be the canonicalized
    /// path to the source file.
    name: String,
    /// The source code of the module.
    source: String,
    functions: Vec<LoadedFunction>,
    /// The module's static scope; it holds:
    ///   - Imports
    ///   - Bound or exported variables
    ///   - Bound or exported functions
    static_closure: Closure,
    // A module loaded into memory is uninitialized. Only after it has been
    // evaluated (and imports and exports resolved) is it initialized.
    initialized: bool,
    exports: HashMap<String, Value>,
}

impl InnerLoadedModule {
    fn empty(name: String, source: String, builtins_closure: Option<Closure>) -> Self {
        Self {
            name,
            source,
            functions: vec![],
            static_closure: Closure::new_static(builtins_closure),
            initialized: false,
            exports: HashMap::new(),
        }
    }
}

// Opaque wrapper around a reference-counted loaded unit.
#[derive(Clone)]
pub struct LoadedModule(Rc<RefCell<InnerLoadedModule>>);

impl LoadedModule {
    pub fn from_bytecode(
        module: bytecode::layout::Module,
        name: String,
        source: String,
        builtins_closure: Option<Closure>,
    ) -> Self {
        let inner = Rc::new(RefCell::new(InnerLoadedModule::empty(
            name,
            source,
            builtins_closure,
        )));
        let functions = module
            .functions
            .into_iter()
            .map(|function| {
                let weak_loaded_module = Rc::downgrade(&inner);
                LoadedFunction::new(weak_loaded_module, function)
            })
            .collect::<Vec<LoadedFunction>>();
        inner.borrow_mut().functions = functions;
        Self(inner)
    }

    pub fn builtin(name: String) -> Self {
        let inner = Rc::new(RefCell::new(InnerLoadedModule::empty(
            name,
            "".to_string(),
            None,
        )));
        Self(inner)
    }

    pub fn name(&self) -> String {
        self.0.borrow().name.clone()
    }

    pub fn source(&self) -> String {
        self.0.borrow().source.clone()
    }

    /// Returns a path to the directory in which relative imports can be
    /// processed for this module.
    pub fn relative_import_path(&self) -> Option<PathBuf> {
        let name = self.name();
        // FIXME: Make REPL detection and handling smarter.
        if name.starts_with("repl[") {
            return env::current_dir().ok();
        }
        let path = Path::new(&name);
        if path.is_file() {
            return path.parent().map(Path::to_path_buf);
        }
        None
    }

    pub fn main(&self) -> LoadedFunction {
        match self.0.borrow().functions.get(0) {
            Some(function) => function.clone(),
            None => unreachable!("Tried getting a main function for an empty module; perhaps it's trying to evaluate a builtin module?")
        }
    }

    pub fn static_closure(&self) -> Closure {
        self.0.borrow().static_closure.clone()
    }

    pub fn initialized(&self) -> bool {
        self.0.borrow().initialized
    }

    pub fn set_initialized(&self) {
        let mut inner = self.0.borrow_mut();
        inner.initialized = true;
    }

    /// Should only be called by the REPL!
    pub fn override_static_closure(&self, static_closure: Closure) {
        self.0.borrow_mut().static_closure = static_closure;
    }

    pub fn function(&self, id: u16) -> LoadedFunction {
        self.0
            .borrow()
            .functions
            .iter()
            .find(|&function| function.id() == id)
            .expect("Function not found")
            .clone()
    }

    pub fn get_export<N: AsRef<str>>(&self, name: N) -> Option<Value> {
        self.0
            .borrow_mut()
            .exports
            .get(name.as_ref())
            .map(Clone::clone)
    }

    pub fn set_export<N: Into<String>>(&self, name: N, value: Value) {
        self.0.borrow_mut().exports.insert(name.into(), value);
    }
}

pub type WeakLoadedModule = Weak<RefCell<InnerLoadedModule>>;

impl TryInto<LoadedModule> for WeakLoadedModule {
    type Error = ();

    fn try_into(self) -> Result<LoadedModule, Self::Error> {
        match self.upgrade() {
            Some(inner) => Ok(LoadedModule(inner)),
            None => Err(()),
        }
    }
}

impl GcTrace for LoadedModule {
    fn trace(&self) {
        let inner = self.0.borrow();
        inner.static_closure.trace();
        for export in inner.exports.values() {
            export.trace();
        }
    }
}
<|endoftext|>


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

use std::ffi::CString;
use std::io;
use std::thread;

use libc::c_char;
use mio;

use domain::types::*;
use util::Consume;

const POLLING_DELAY_MS: u64 = 50;

#[derive(Debug)]
pub enum Envelope {
    Cmd(Command),
    Shutdown
}

pub struct Domain {
    worker: thread::JoinHandle<()>,
    tx: mio::Sender<Envelope>
}

impl Domain {
    pub fn new() -> Domain {
        let (worker, tx) = spawn_worker();
        Domain { worker: worker, tx: tx }
    }

    pub fn shutdown(self) {
        self.tx.send(Envelope::Shutdown).unwrap_or_else(|e| {
            warn!("unexpected error while sending shutdown message to lvar domain: {}", e);
        });
        self.worker.join().unwrap_or_else(|_| {
            warn!("unexpected error while waiting for lvar domain worker thread");
        });
    }

    pub fn consumer(&self) -> Consumer {
        Consumer { tx: self.tx.clone() }
    }
}

#[derive(Clone)]
pub struct Consumer {
    tx: mio::Sender<Envelope>
}

impl Consume for Consumer {
    type Item = Command;
    type Error = mio::NotifyError<Envelope>;
    fn consume(&mut self, cmd: Command) -> Result<(), mio::NotifyError<Envelope>> {
        self.tx.send(Envelope::Cmd(cmd))
    }
}

struct Observer {
    lvar: String,
    client: Client,
    retain: Option<Value>,
}

impl Observer {
}

struct Context {
    observers: Vec<Observer>,
}

impl Context {
    pub fn new()  -> Context {
        Context {
            observers: Vec::new(),
        }
    }

    fn process_write(&mut self, lvar: &str, value: Value) -> io::Result<()> {
        debug!("writing value {} to lvar {}", value, lvar);
        let id = check_named_variable(lvar);
        if id == -1 {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                format!("there is no such named variable '{}'", lvar)));
        }
        set_named_variable_value(id, f64::from(value));
        Ok(())
    }

    fn process_obs(&mut self, lvar: &str, client: Client) {
        debug!("client {} observing lvar {}", client.name(), lvar);
        self.observers.push(Observer {
            lvar: lvar.to_string(),
            client: client,
            retain: None,
        });
    }
}

fn spawn_worker() -> (thread::JoinHandle<()>, mio::Sender<Envelope>) {
    let event_loop = mio::EventLoop::new().unwrap();
    let tx = event_loop.channel();
    let worker = thread::spawn(move || {
        let mut event_loop = event_loop;
        let mut ctx = Context::new();
        event_loop.timeout_ms((), POLLING_DELAY_MS).unwrap();
        event_loop.run(&mut ctx).unwrap();
    });
    (worker, tx)
}

impl mio::Handler for Context {
    type Timeout = ();
    type Message = Envelope;

    fn timeout(&mut self, event_loop: &mut mio::EventLoop<Context>, _: ()) {
        // TODO: implement this
    }

    fn notify(&mut self, event_loop: &mut mio::EventLoop<Context>, msg: Envelope) {
        match msg {
            Envelope::Cmd(Command::Write(Var::LVar(lvar), value)) => {
                if let Err(e) = self.process_write(&lvar, value) {
                    error!("unexpected IO error while writing LVAR {}: {}", lvar, e);
                }
            },
            Envelope::Cmd(Command::Observe(Var::LVar(lvar), client)) => {
                self.process_obs(&lvar, client);
            },
            Envelope::Shutdown => event_loop.shutdown(),
            other => {
                warn!("LVAR domain received an unexpected message: {:?}", other);
            },
        }
    }
}

//////////////////////////////////////////////////////////////////////////////////
// The following code provides the low level routines to access FSX/P3D panels. //
//////////////////////////////////////////////////////////////////////////////////

pub type Bool = i32;
pub type Enum = i32;
pub type Flags32 = u32;
pub type GeneratePhase = u32;
pub type Id = i32;

fn check_named_variable(name: &str) -> Id {
    unsafe {
        let func = (*Panels).check_named_variable;
        let name = CString::new(name).unwrap();
        (func)(name.as_ptr())
    }
}

fn get_named_variable_value(id: Id) -> f64 {
    unsafe {
        let func = (*Panels).get_named_variable_value;
        (func)(id)
    }
}

fn set_named_variable_value(id: Id, value: f64) {
    unsafe {
        let func = (*Panels).set_named_variable_value;
        (func)(id, value)
    }
}

fn is_initialized() -> bool {
    unsafe { !Panels.is_null() }
}

/// This struct declares all panel related functions exported by FSX/P3D.
/// Most of the fields (those whose name starts with underscore) are not used by FlightVars.
/// In order to simplify the code, their declared function signatures don't correspond to the
/// actual ones. If you want to use such functions you'll have to set their signatures to that
/// declared in `struct PANELS` in `gauges.h` header file of P3D SDK.
pub struct PanelFunctions {
    _mod_id: Id,
    _mod_init: extern "stdcall" fn(),
    _mod_deinit: extern "stdcall" fn(),
    _mod_flags: Flags32,
    _mod_priority: u32,
    _mod_version: u32,

    _reserved1: extern "stdcall" fn(),
    _reserved2: extern "stdcall" fn(),
    _reserved3: extern "stdcall" fn(),
    _reserved4: extern "stdcall" fn(),
    _reserved5: extern "stdcall" fn(),
    _is_panel_visible_ident: extern "stdcall" fn(),
    _tooltip_units_getset: extern "stdcall" fn(),
    _reserved7: extern "stdcall" fn(),
    _reserved8: extern "stdcall" fn(),
    _reserved9: extern "stdcall" fn(),
    _reserved10: extern "stdcall" fn(),
    _reserved11: extern "stdcall" fn(),
    _reserved12: extern "stdcall" fn(),
    _reserved13: extern "stdcall" fn(),
    _reserved14: extern "stdcall" fn(),
    _reserved15: extern "stdcall" fn(),
    _reserved16: extern "stdcall" fn(),
    _reserved17: extern "stdcall" fn(),
    _element_list_query: extern "stdcall" fn(),
    _element_list_install: extern "stdcall" fn(),
    _element_list_initialize: extern "stdcall" fn(),
    _element_list_update: extern "stdcall" fn(),
    _element_list_generate: extern "stdcall" fn(),
    _element_list_plot: extern "stdcall" fn(),
    _element_list_erase: extern "stdcall" fn(),
    _element_list_kill: extern "stdcall" fn(),
    _mouse_list_install: extern "stdcall" fn(),
    _mouse_list_register: extern "stdcall" fn(),
    _mouse_list_unregister: extern "stdcall" fn(),
    _panel_window_togle: extern "stdcall" fn(),
    _trigger_key_event: extern "stdcall" fn(),
    _register_var_by_name: extern "stdcall" fn(),
    _initialize_var: extern "stdcall" fn(),
    _initialize_var_by_name: extern "stdcall" fn(),
    _lookup_var: extern "stdcall" fn(),
    _unregister_var_by_name: extern "stdcall" fn(),
    _unregister_all_named_vars: extern "stdcall" fn(),
    _reserved18: extern "stdcall" fn(),
    _reserved19: extern "stdcall" fn(),
    _panel_window_close_ident: extern "stdcall" fn(),
    _panel_window_open_ident: extern "stdcall" fn(),
    _panel_window_toggle_hud_color: extern "stdcall" fn(),
    _panel_window_toggle_hud_units: extern "stdcall" fn(),
    _radio_stack_popup: extern "stdcall" fn(),
    _radio_stack_autoclose: extern "stdcall" fn(),
    pub check_named_variable: extern "stdcall" fn(name: *const c_char) -> Id,
    _register_named_variable: extern "stdcall" fn(),
    pub get_named_variable_value: extern "stdcall" fn(id: Id) -> f64,
    _get_named_variable_typed_value: extern "stdcall" fn(),
    pub set_named_variable_value: extern "stdcall" fn(id: Id, value: f64),
    _set_named_variable_typed_value: extern "stdcall" fn(),
    _reserved26: extern "stdcall" fn(),
    _reserved27: extern "stdcall" fn(),
    _get_name_of_named_variable: extern "stdcall" fn(),
    _reserved29: extern "stdcall" fn(),
    _panel_resource_string_get: extern "stdcall" fn(),
    _panel_window_toggle_menu_id: extern "stdcall" fn(),
    _reserved30: extern "stdcall" fn(),
    _reserved31: extern "stdcall" fn(),
    _element_use_color: extern "stdcall" fn(),
    _set_gauge_flags: extern "stdcall" fn(),
    _get_gauge_flags: extern "stdcall" fn(),
    _gauge_calculator_code_precompile: extern "stdcall" fn(),
    _execute_calculator_code: extern "stdcall" fn(),
    _format_calculator_string: extern "stdcall" fn(),
    _reserved32: extern "stdcall" fn(),
    _reserved33: extern "stdcall" fn(),
    _get_units_enum: extern "stdcall" fn(),
    _get_aircraft_var_enum: extern "stdcall" fn(),
    _aircraft_varget: extern "stdcall" fn(),
    _panel_register_c_callback: extern "stdcall" fn(),
    _panel_get_registered_c_callback: extern "stdcall" fn(),
    _panel_get_aircraft_c_callback: extern "stdcall" fn(),
    _send_key_event: extern "stdcall" fn(),
    _register_key_event_handler: extern "stdcall" fn(),
    _unregister_key_event_handler: extern "stdcall" fn(),
    _reserved34: extern "stdcall" fn(),
    _reserved35: extern "stdcall" fn(),
    _process_shared_event_out: extern "stdcall" fn(),
    _is_master: extern "stdcall" fn(),
    _reserved36: extern "stdcall" fn(),
    _set_named_variable_value_sync: extern "stdcall" fn(),
    _set_named_variable_sync_enabled: extern "stdcall" fn(),
}

#[allow(non_upper_case_globals)]
#[no_mangle]
pub static mut Panels: *mut PanelFunctions = 0 as *mut PanelFunctions;

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

    #[test]
    fn should_init_and_shutdown() {
        let mut domain = Domain::new();
        domain.shutdown();
    }
}
<commit_msg>Implement observe command in `lvar` domain<commit_after>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::ffi::CString;
use std::io;
use std::thread;

use libc::c_char;
use mio;

use domain::types::*;
use util::Consume;

const POLLING_DELAY_MS: u64 = 50;

#[derive(Debug)]
pub enum Envelope {
    Cmd(Command),
    Shutdown
}

pub struct Domain {
    worker: thread::JoinHandle<()>,
    tx: mio::Sender<Envelope>
}

impl Domain {
    pub fn new() -> Domain {
        let (worker, tx) = spawn_worker();
        Domain { worker: worker, tx: tx }
    }

    pub fn shutdown(self) {
        self.tx.send(Envelope::Shutdown).unwrap_or_else(|e| {
            warn!("unexpected error while sending shutdown message to lvar domain: {}", e);
        });
        self.worker.join().unwrap_or_else(|_| {
            warn!("unexpected error while waiting for lvar domain worker thread");
        });
    }

    pub fn consumer(&self) -> Consumer {
        Consumer { tx: self.tx.clone() }
    }
}

#[derive(Clone)]
pub struct Consumer {
    tx: mio::Sender<Envelope>
}

impl Consume for Consumer {
    type Item = Command;
    type Error = mio::NotifyError<Envelope>;
    fn consume(&mut self, cmd: Command) -> Result<(), mio::NotifyError<Envelope>> {
        self.tx.send(Envelope::Cmd(cmd))
    }
}

struct Observer {
    lvar: String,
    client: Client,
    retain: Option<Value>,
}

impl Observer {
    pub fn trigger_event(&mut self) {
        let id = check_named_variable(&self.lvar).unwrap();
        let val = Value::Int(get_named_variable_value(id) as isize);
        let must_trigger = self.retain.as_ref().map(|v| *v != val).unwrap_or(true);
        if must_trigger {
            let var = Var::LVar(self.lvar.clone());
            if let Err(e) = self.client.sender().send(Event::Update(var, val)) {
                error!("unexpected error while sending event to client {}: {}",
                    self.client.name(), e);
            }
            self.retain = Some(val);
        }
    }
}

struct Context {
    observers: Vec<Observer>,
}

impl Context {
    pub fn new()  -> Context {
        Context {
            observers: Vec::new(),
        }
    }

    fn process_write(&mut self, lvar: &str, value: Value) -> io::Result<()> {
        debug!("writing value {} to lvar {}", value, lvar);
        let id = try!(check_named_variable(lvar).ok_or(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("there is no such named variable '{}'", lvar))));
        set_named_variable_value(id, f64::from(value));
        Ok(())
    }

    fn process_obs(&mut self, lvar: &str, client: Client) {
        debug!("client {} observing lvar {}", client.name(), lvar);
        self.observers.push(Observer {
            lvar: lvar.to_string(),
            client: client,
            retain: None,
        });
    }
}

fn spawn_worker() -> (thread::JoinHandle<()>, mio::Sender<Envelope>) {
    let event_loop = mio::EventLoop::new().unwrap();
    let tx = event_loop.channel();
    let worker = thread::spawn(move || {
        let mut event_loop = event_loop;
        let mut ctx = Context::new();
        event_loop.timeout_ms((), POLLING_DELAY_MS).unwrap();
        event_loop.run(&mut ctx).unwrap();
    });
    (worker, tx)
}

impl mio::Handler for Context {
    type Timeout = ();
    type Message = Envelope;

    fn timeout(&mut self, event_loop: &mut mio::EventLoop<Context>, _: ()) {
        for obs in self.observers.iter_mut() {
            obs.trigger_event();
        }
        event_loop.timeout_ms((), POLLING_DELAY_MS).unwrap();
    }

    fn notify(&mut self, event_loop: &mut mio::EventLoop<Context>, msg: Envelope) {
        match msg {
            Envelope::Cmd(Command::Write(Var::LVar(lvar), value)) => {
                if let Err(e) = self.process_write(&lvar, value) {
                    error!("unexpected IO error while writing LVAR {}: {}", lvar, e);
                }
            },
            Envelope::Cmd(Command::Observe(Var::LVar(lvar), client)) => {
                self.process_obs(&lvar, client);
            },
            Envelope::Shutdown => event_loop.shutdown(),
            other => {
                warn!("LVAR domain received an unexpected message: {:?}", other);
            },
        }
    }
}

//////////////////////////////////////////////////////////////////////////////////
// The following code provides the low level routines to access FSX/P3D panels. //
//////////////////////////////////////////////////////////////////////////////////

pub type Bool = i32;
pub type Enum = i32;
pub type Flags32 = u32;
pub type GeneratePhase = u32;
pub type Id = i32;

fn check_named_variable(name: &str) -> Option<Id> {
    unsafe {
        let func = (*Panels).check_named_variable;
        let name = CString::new(name).unwrap();
        let id = (func)(name.as_ptr());
        if id != -1 { Some(id) } else { None }
    }
}

fn get_named_variable_value(id: Id) -> f64 {
    unsafe {
        let func = (*Panels).get_named_variable_value;
        (func)(id)
    }
}

fn set_named_variable_value(id: Id, value: f64) {
    unsafe {
        let func = (*Panels).set_named_variable_value;
        (func)(id, value)
    }
}

fn is_initialized() -> bool {
    unsafe { !Panels.is_null() }
}

/// This struct declares all panel related functions exported by FSX/P3D.
/// Most of the fields (those whose name starts with underscore) are not used by FlightVars.
/// In order to simplify the code, their declared function signatures don't correspond to the
/// actual ones. If you want to use such functions you'll have to set their signatures to that
/// declared in `struct PANELS` in `gauges.h` header file of P3D SDK.
pub struct PanelFunctions {
    _mod_id: Id,
    _mod_init: extern "stdcall" fn(),
    _mod_deinit: extern "stdcall" fn(),
    _mod_flags: Flags32,
    _mod_priority: u32,
    _mod_version: u32,

    _reserved1: extern "stdcall" fn(),
    _reserved2: extern "stdcall" fn(),
    _reserved3: extern "stdcall" fn(),
    _reserved4: extern "stdcall" fn(),
    _reserved5: extern "stdcall" fn(),
    _is_panel_visible_ident: extern "stdcall" fn(),
    _tooltip_units_getset: extern "stdcall" fn(),
    _reserved7: extern "stdcall" fn(),
    _reserved8: extern "stdcall" fn(),
    _reserved9: extern "stdcall" fn(),
    _reserved10: extern "stdcall" fn(),
    _reserved11: extern "stdcall" fn(),
    _reserved12: extern "stdcall" fn(),
    _reserved13: extern "stdcall" fn(),
    _reserved14: extern "stdcall" fn(),
    _reserved15: extern "stdcall" fn(),
    _reserved16: extern "stdcall" fn(),
    _reserved17: extern "stdcall" fn(),
    _element_list_query: extern "stdcall" fn(),
    _element_list_install: extern "stdcall" fn(),
    _element_list_initialize: extern "stdcall" fn(),
    _element_list_update: extern "stdcall" fn(),
    _element_list_generate: extern "stdcall" fn(),
    _element_list_plot: extern "stdcall" fn(),
    _element_list_erase: extern "stdcall" fn(),
    _element_list_kill: extern "stdcall" fn(),
    _mouse_list_install: extern "stdcall" fn(),
    _mouse_list_register: extern "stdcall" fn(),
    _mouse_list_unregister: extern "stdcall" fn(),
    _panel_window_togle: extern "stdcall" fn(),
    _trigger_key_event: extern "stdcall" fn(),
    _register_var_by_name: extern "stdcall" fn(),
    _initialize_var: extern "stdcall" fn(),
    _initialize_var_by_name: extern "stdcall" fn(),
    _lookup_var: extern "stdcall" fn(),
    _unregister_var_by_name: extern "stdcall" fn(),
    _unregister_all_named_vars: extern "stdcall" fn(),
    _reserved18: extern "stdcall" fn(),
    _reserved19: extern "stdcall" fn(),
    _panel_window_close_ident: extern "stdcall" fn(),
    _panel_window_open_ident: extern "stdcall" fn(),
    _panel_window_toggle_hud_color: extern "stdcall" fn(),
    _panel_window_toggle_hud_units: extern "stdcall" fn(),
    _radio_stack_popup: extern "stdcall" fn(),
    _radio_stack_autoclose: extern "stdcall" fn(),
    pub check_named_variable: extern "stdcall" fn(name: *const c_char) -> Id,
    _register_named_variable: extern "stdcall" fn(),
    pub get_named_variable_value: extern "stdcall" fn(id: Id) -> f64,
    _get_named_variable_typed_value: extern "stdcall" fn(),
    pub set_named_variable_value: extern "stdcall" fn(id: Id, value: f64),
    _set_named_variable_typed_value: extern "stdcall" fn(),
    _reserved26: extern "stdcall" fn(),
    _reserved27: extern "stdcall" fn(),
    _get_name_of_named_variable: extern "stdcall" fn(),
    _reserved29: extern "stdcall" fn(),
    _panel_resource_string_get: extern "stdcall" fn(),
    _panel_window_toggle_menu_id: extern "stdcall" fn(),
    _reserved30: extern "stdcall" fn(),
    _reserved31: extern "stdcall" fn(),
    _element_use_color: extern "stdcall" fn(),
    _set_gauge_flags: extern "stdcall" fn(),
    _get_gauge_flags: extern "stdcall" fn(),
    _gauge_calculator_code_precompile: extern "stdcall" fn(),
    _execute_calculator_code: extern "stdcall" fn(),
    _format_calculator_string: extern "stdcall" fn(),
    _reserved32: extern "stdcall" fn(),
    _reserved33: extern "stdcall" fn(),
    _get_units_enum: extern "stdcall" fn(),
    _get_aircraft_var_enum: extern "stdcall" fn(),
    _aircraft_varget: extern "stdcall" fn(),
    _panel_register_c_callback: extern "stdcall" fn(),
    _panel_get_registered_c_callback: extern "stdcall" fn(),
    _panel_get_aircraft_c_callback: extern "stdcall" fn(),
    _send_key_event: extern "stdcall" fn(),
    _register_key_event_handler: extern "stdcall" fn(),
    _unregister_key_event_handler: extern "stdcall" fn(),
    _reserved34: extern "stdcall" fn(),
    _reserved35: extern "stdcall" fn(),
    _process_shared_event_out: extern "stdcall" fn(),
    _is_master: extern "stdcall" fn(),
    _reserved36: extern "stdcall" fn(),
    _set_named_variable_value_sync: extern "stdcall" fn(),
    _set_named_variable_sync_enabled: extern "stdcall" fn(),
}

#[allow(non_upper_case_globals)]
#[no_mangle]
pub static mut Panels: *mut PanelFunctions = 0 as *mut PanelFunctions;

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

    #[test]
    fn should_init_and_shutdown() {
        let mut domain = Domain::new();
        domain.shutdown();
    }
}
<|endoftext|>