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

#![allow(dead_code)]

use libc::{self, c_int, c_ulong, c_void, ioctl, read};
use std::fs::{File, OpenOptions};
use std::io;
use std::mem::size_of;
use std::os::unix::io::AsRawFd;
use std::time::Duration;

use crate::gpio::{Error, Level, Result, Trigger};

#[cfg(target_env = "gnu")]
type IoctlLong = libc::c_ulong;
#[cfg(target_env = "musl")]
type IoctlLong = libc::c_long;

const NRBITS: u8 = 8;
const TYPEBITS: u8 = 8;
const SIZEBITS: u8 = 14;
const DIRBITS: u8 = 2;

const NRSHIFT: u8 = 0;
const TYPESHIFT: u8 = (NRSHIFT + NRBITS);
const SIZESHIFT: u8 = (TYPESHIFT + TYPEBITS);
const DIRSHIFT: u8 = (SIZESHIFT + SIZEBITS);

const NR_GET_CHIP_INFO: IoctlLong = 0x01 << NRSHIFT;
const NR_GET_LINE_INFO: IoctlLong = 0x02 << NRSHIFT;
const NR_GET_LINE_HANDLE: IoctlLong = 0x03 << NRSHIFT;
const NR_GET_LINE_EVENT: IoctlLong = 0x04 << NRSHIFT;
const NR_GET_LINE_VALUES: IoctlLong = 0x08 << NRSHIFT;
const NR_SET_LINE_VALUES: IoctlLong = 0x09 << NRSHIFT;

const TYPE_GPIO: IoctlLong = (0xB4 as IoctlLong) << TYPESHIFT;

const SIZE_CHIP_INFO: IoctlLong = (size_of::<ChipInfo>() as IoctlLong) << SIZESHIFT;
const SIZE_LINE_INFO: IoctlLong = (size_of::<LineInfo>() as IoctlLong) << SIZESHIFT;
const SIZE_HANDLE_REQUEST: IoctlLong = (size_of::<HandleRequest>() as IoctlLong) << SIZESHIFT;
const SIZE_EVENT_REQUEST: IoctlLong = (size_of::<EventRequest>() as IoctlLong) << SIZESHIFT;
const SIZE_HANDLE_DATA: IoctlLong = (size_of::<HandleData>() as IoctlLong) << SIZESHIFT;

const DIR_NONE: c_ulong = 0;
const DIR_WRITE: IoctlLong = 1 << DIRSHIFT;
const DIR_READ: IoctlLong = 2 << DIRSHIFT;
const DIR_READ_WRITE: IoctlLong = DIR_READ | DIR_WRITE;

const REQ_GET_CHIP_INFO: IoctlLong = DIR_READ | TYPE_GPIO | NR_GET_CHIP_INFO | SIZE_CHIP_INFO;
const REQ_GET_LINE_INFO: IoctlLong = DIR_READ_WRITE | TYPE_GPIO | NR_GET_LINE_INFO | SIZE_LINE_INFO;
const REQ_GET_LINE_HANDLE: IoctlLong =
    DIR_READ_WRITE | TYPE_GPIO | NR_GET_LINE_HANDLE | SIZE_HANDLE_REQUEST;
const REQ_GET_LINE_EVENT: IoctlLong =
    DIR_READ_WRITE | TYPE_GPIO | NR_GET_LINE_EVENT | SIZE_EVENT_REQUEST;
const REQ_GET_LINE_VALUES: IoctlLong =
    DIR_READ_WRITE | TYPE_GPIO | NR_GET_LINE_VALUES | SIZE_HANDLE_DATA;
const REQ_SET_LINE_VALUES: IoctlLong =
    DIR_READ_WRITE | TYPE_GPIO | NR_SET_LINE_VALUES | SIZE_HANDLE_DATA;

const NAME_BUFSIZE: usize = 32;
const LABEL_BUFSIZE: usize = 32;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct ChipInfo {
    pub name: [u8; NAME_BUFSIZE],
    pub label: [u8; LABEL_BUFSIZE],
    pub lines: u32,
}

impl ChipInfo {
    pub fn new(cdev_fd: c_int) -> Result<ChipInfo> {
        let mut chip_info = ChipInfo {
            name: [0u8; NAME_BUFSIZE],
            label: [0u8; LABEL_BUFSIZE],
            lines: 0,
        };

        parse_retval!(unsafe { ioctl(cdev_fd, REQ_GET_CHIP_INFO, &mut chip_info) })?;

        Ok(chip_info)
    }
}

const LINE_FLAG_KERNEL: u32 = 0x01;
const LINE_FLAG_IS_OUT: u32 = 0x02;
const LINE_FLAG_ACTIVE_LOW: u32 = 0x04;
const LINE_FLAG_OPEN_DRAIN: u32 = 0x08;
const LINE_FLAG_OPEN_SOURCE: u32 = 0x10;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct LineInfo {
    pub line_offset: u32,
    pub flags: u32,
    pub name: [u8; NAME_BUFSIZE],
    pub consumer: [u8; LABEL_BUFSIZE],
}

impl LineInfo {
    pub fn new() -> LineInfo {
        LineInfo {
            line_offset: 0,
            flags: 0,
            name: [0u8; NAME_BUFSIZE],
            consumer: [0u8; LABEL_BUFSIZE],
        }
    }
}

const HANDLES_MAX: usize = 64;
const HANDLE_FLAG_INPUT: u32 = 0x01;
const HANDLE_FLAG_OUTPUT: u32 = 0x02;
const HANDLE_FLAG_ACTIVE_LOW: u32 = 0x04;
const HANDLE_FLAG_OPEN_DRAIN: u32 = 0x08;
const HANDLE_FLAG_OPEN_SOURCE: u32 = 0x10;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct HandleRequest {
    pub line_offsets: [u32; HANDLES_MAX],
    pub flags: u32,
    pub default_values: [u8; HANDLES_MAX],
    pub consumer_label: [u8; LABEL_BUFSIZE],
    pub lines: u32,
    pub fd: c_int,
}

impl HandleRequest {
    pub fn new(cdev_fd: c_int, pins: &[u8]) -> Result<HandleRequest> {
        let mut handle_request = HandleRequest {
            line_offsets: [0u32; HANDLES_MAX],
            flags: 0,
            default_values: [0u8; HANDLES_MAX],
            consumer_label: [0u8; LABEL_BUFSIZE],
            lines: 0,
            fd: 0,
        };

        let pins: &[u8] = if pins.len() > HANDLES_MAX {
            handle_request.lines = HANDLES_MAX as u32;
            &pins[0..HANDLES_MAX]
        } else {
            handle_request.lines = pins.len() as u32;
            pins
        };

        for (idx, pin) in pins.iter().enumerate() {
            handle_request.line_offsets[idx] = u32::from(*pin);
        }

        parse_retval!(unsafe { ioctl(cdev_fd, REQ_GET_LINE_HANDLE, &mut handle_request) })?;

        Ok(handle_request)
    }

    pub fn levels(&self) -> Result<HandleData> {
        let mut handle_data = HandleData::new();

        parse_retval!(unsafe { ioctl(self.fd, REQ_GET_LINE_VALUES, &mut handle_data) })?;

        Ok(handle_data)
    }

    pub fn set_levels(&mut self, levels: &[Level]) -> Result<()> {
        let mut handle_data = HandleData::new();
        let levels: &[Level] = if levels.len() > HANDLES_MAX {
            &levels[0..HANDLES_MAX]
        } else {
            levels
        };

        for (idx, level) in levels.iter().enumerate() {
            handle_data.values[idx] = *level as u8;
        }

        parse_retval!(unsafe { ioctl(self.fd, REQ_SET_LINE_VALUES, &mut handle_data) })?;

        Ok(())
    }
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct HandleData {
    pub values: [u8; HANDLES_MAX],
}

impl HandleData {
    pub fn new() -> HandleData {
        HandleData {
            values: [0u8; HANDLES_MAX],
        }
    }
}

const EVENT_FLAG_RISING_EDGE: u32 = 0x01;
const EVENT_FLAG_FALLING_EDGE: u32 = 0x02;
const EVENT_FLAG_BOTH_EDGES: u32 = EVENT_FLAG_RISING_EDGE | EVENT_FLAG_FALLING_EDGE;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct EventRequest {
    pub line_offset: u32,
    pub handle_flags: u32,
    pub event_flags: u32,
    pub consumer_label: [u8; LABEL_BUFSIZE],
    pub fd: c_int,
}

impl EventRequest {
    pub fn new(cdev_fd: c_int, pin: u8, trigger: Trigger) -> Result<EventRequest> {
        let mut event_request = EventRequest {
            line_offset: u32::from(pin),
            handle_flags: HANDLE_FLAG_INPUT,
            event_flags: trigger as u32,
            consumer_label: [0u8; LABEL_BUFSIZE],
            fd: 0,
        };

        parse_retval!(unsafe { ioctl(cdev_fd, REQ_GET_LINE_EVENT, &mut event_request) })?;

        Ok(event_request)
    }
}

const EVENT_TYPE_RISING_EDGE: u32 = 0x01;
const EVENT_TYPE_FALLING_EDGE: u32 = 0x02;

#[derive(Copy, Clone)]
#[repr(C)]
struct EventData {
    timestamp: u64,
    id: u32,
}

impl EventData {
    fn new(event_fd: c_int) -> Result<Option<EventData>> {
        let mut event_data = EventData {
            timestamp: 0,
            id: 0,
        };

        let bytes_read = parse_retval!(unsafe {
            read(
                event_fd,
                &mut event_data as *mut EventData as *mut c_void,
                size_of::<EventData>(),
            )
        })?;

        if bytes_read != size_of::<EventData>() as isize {
            Ok(None)
        } else {
            Ok(Some(event_data))
        }
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Event {
    pub trigger: Trigger,
    pub timestamp: Duration,
}

impl Event {
    fn from_event_data(event_data: EventData) -> Event {
        Event {
            trigger: if event_data.id == EVENT_TYPE_RISING_EDGE {
                Trigger::RisingEdge
            } else {
                Trigger::FallingEdge
            },
            timestamp: Duration::from_nanos(event_data.timestamp),
        }
    }
}

// Read interrupt event
pub fn get_event(event_fd: c_int) -> Result<Option<Event>> {
    if let Some(event_data) = EventData::new(event_fd)? {
        Ok(Some(Event::from_event_data(event_data)))
    } else {
        Ok(None)
    }
}

// Find the correct gpiochip device based on its label
pub fn find_driver() -> Result<File> {
    let driver_name = b"pinctrl-bcm2835\0";

    for idx in 0..=255 {
        let gpiochip = OpenOptions::new()
            .read(true)
            .write(true)
            .open(format!("/dev/gpiochip{}", idx))?;

        let chip_info = ChipInfo::new(gpiochip.as_raw_fd())?;
        if chip_info.label[0..driver_name.len()] == driver_name[..] {
            return Ok(gpiochip);
        }
    }

    Err(Error::Io(io::Error::from_raw_os_error(2)))
}

pub fn get_level(cdev_fd: c_int, pin: u8) -> Result<Level> {
    let chip_info = ChipInfo::new(cdev_fd)?;

    assert_pin!(u32::from(pin), chip_info.lines);

    match HandleRequest::new(cdev_fd, &[pin])?.levels()?.values[0] {
        0 => Ok(Level::Low),
        1 => Ok(Level::High),
        _ => unreachable!(),
    }
}

pub fn close(fd: c_int) {
    unsafe {
        libc::close(fd);
    }
}
<commit_msg>Use `unreachable` macro when matching rising/falling edge.<commit_after>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#![allow(dead_code)]

use libc::{self, c_int, c_ulong, c_void, ioctl, read};
use std::fs::{File, OpenOptions};
use std::io;
use std::mem::size_of;
use std::os::unix::io::AsRawFd;
use std::time::Duration;

use crate::gpio::{Error, Level, Result, Trigger};

#[cfg(target_env = "gnu")]
type IoctlLong = libc::c_ulong;
#[cfg(target_env = "musl")]
type IoctlLong = libc::c_long;

const NRBITS: u8 = 8;
const TYPEBITS: u8 = 8;
const SIZEBITS: u8 = 14;
const DIRBITS: u8 = 2;

const NRSHIFT: u8 = 0;
const TYPESHIFT: u8 = (NRSHIFT + NRBITS);
const SIZESHIFT: u8 = (TYPESHIFT + TYPEBITS);
const DIRSHIFT: u8 = (SIZESHIFT + SIZEBITS);

const NR_GET_CHIP_INFO: IoctlLong = 0x01 << NRSHIFT;
const NR_GET_LINE_INFO: IoctlLong = 0x02 << NRSHIFT;
const NR_GET_LINE_HANDLE: IoctlLong = 0x03 << NRSHIFT;
const NR_GET_LINE_EVENT: IoctlLong = 0x04 << NRSHIFT;
const NR_GET_LINE_VALUES: IoctlLong = 0x08 << NRSHIFT;
const NR_SET_LINE_VALUES: IoctlLong = 0x09 << NRSHIFT;

const TYPE_GPIO: IoctlLong = (0xB4 as IoctlLong) << TYPESHIFT;

const SIZE_CHIP_INFO: IoctlLong = (size_of::<ChipInfo>() as IoctlLong) << SIZESHIFT;
const SIZE_LINE_INFO: IoctlLong = (size_of::<LineInfo>() as IoctlLong) << SIZESHIFT;
const SIZE_HANDLE_REQUEST: IoctlLong = (size_of::<HandleRequest>() as IoctlLong) << SIZESHIFT;
const SIZE_EVENT_REQUEST: IoctlLong = (size_of::<EventRequest>() as IoctlLong) << SIZESHIFT;
const SIZE_HANDLE_DATA: IoctlLong = (size_of::<HandleData>() as IoctlLong) << SIZESHIFT;

const DIR_NONE: c_ulong = 0;
const DIR_WRITE: IoctlLong = 1 << DIRSHIFT;
const DIR_READ: IoctlLong = 2 << DIRSHIFT;
const DIR_READ_WRITE: IoctlLong = DIR_READ | DIR_WRITE;

const REQ_GET_CHIP_INFO: IoctlLong = DIR_READ | TYPE_GPIO | NR_GET_CHIP_INFO | SIZE_CHIP_INFO;
const REQ_GET_LINE_INFO: IoctlLong = DIR_READ_WRITE | TYPE_GPIO | NR_GET_LINE_INFO | SIZE_LINE_INFO;
const REQ_GET_LINE_HANDLE: IoctlLong =
    DIR_READ_WRITE | TYPE_GPIO | NR_GET_LINE_HANDLE | SIZE_HANDLE_REQUEST;
const REQ_GET_LINE_EVENT: IoctlLong =
    DIR_READ_WRITE | TYPE_GPIO | NR_GET_LINE_EVENT | SIZE_EVENT_REQUEST;
const REQ_GET_LINE_VALUES: IoctlLong =
    DIR_READ_WRITE | TYPE_GPIO | NR_GET_LINE_VALUES | SIZE_HANDLE_DATA;
const REQ_SET_LINE_VALUES: IoctlLong =
    DIR_READ_WRITE | TYPE_GPIO | NR_SET_LINE_VALUES | SIZE_HANDLE_DATA;

const NAME_BUFSIZE: usize = 32;
const LABEL_BUFSIZE: usize = 32;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct ChipInfo {
    pub name: [u8; NAME_BUFSIZE],
    pub label: [u8; LABEL_BUFSIZE],
    pub lines: u32,
}

impl ChipInfo {
    pub fn new(cdev_fd: c_int) -> Result<ChipInfo> {
        let mut chip_info = ChipInfo {
            name: [0u8; NAME_BUFSIZE],
            label: [0u8; LABEL_BUFSIZE],
            lines: 0,
        };

        parse_retval!(unsafe { ioctl(cdev_fd, REQ_GET_CHIP_INFO, &mut chip_info) })?;

        Ok(chip_info)
    }
}

const LINE_FLAG_KERNEL: u32 = 0x01;
const LINE_FLAG_IS_OUT: u32 = 0x02;
const LINE_FLAG_ACTIVE_LOW: u32 = 0x04;
const LINE_FLAG_OPEN_DRAIN: u32 = 0x08;
const LINE_FLAG_OPEN_SOURCE: u32 = 0x10;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct LineInfo {
    pub line_offset: u32,
    pub flags: u32,
    pub name: [u8; NAME_BUFSIZE],
    pub consumer: [u8; LABEL_BUFSIZE],
}

impl LineInfo {
    pub fn new() -> LineInfo {
        LineInfo {
            line_offset: 0,
            flags: 0,
            name: [0u8; NAME_BUFSIZE],
            consumer: [0u8; LABEL_BUFSIZE],
        }
    }
}

const HANDLES_MAX: usize = 64;
const HANDLE_FLAG_INPUT: u32 = 0x01;
const HANDLE_FLAG_OUTPUT: u32 = 0x02;
const HANDLE_FLAG_ACTIVE_LOW: u32 = 0x04;
const HANDLE_FLAG_OPEN_DRAIN: u32 = 0x08;
const HANDLE_FLAG_OPEN_SOURCE: u32 = 0x10;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct HandleRequest {
    pub line_offsets: [u32; HANDLES_MAX],
    pub flags: u32,
    pub default_values: [u8; HANDLES_MAX],
    pub consumer_label: [u8; LABEL_BUFSIZE],
    pub lines: u32,
    pub fd: c_int,
}

impl HandleRequest {
    pub fn new(cdev_fd: c_int, pins: &[u8]) -> Result<HandleRequest> {
        let mut handle_request = HandleRequest {
            line_offsets: [0u32; HANDLES_MAX],
            flags: 0,
            default_values: [0u8; HANDLES_MAX],
            consumer_label: [0u8; LABEL_BUFSIZE],
            lines: 0,
            fd: 0,
        };

        let pins: &[u8] = if pins.len() > HANDLES_MAX {
            handle_request.lines = HANDLES_MAX as u32;
            &pins[0..HANDLES_MAX]
        } else {
            handle_request.lines = pins.len() as u32;
            pins
        };

        for (idx, pin) in pins.iter().enumerate() {
            handle_request.line_offsets[idx] = u32::from(*pin);
        }

        parse_retval!(unsafe { ioctl(cdev_fd, REQ_GET_LINE_HANDLE, &mut handle_request) })?;

        Ok(handle_request)
    }

    pub fn levels(&self) -> Result<HandleData> {
        let mut handle_data = HandleData::new();

        parse_retval!(unsafe { ioctl(self.fd, REQ_GET_LINE_VALUES, &mut handle_data) })?;

        Ok(handle_data)
    }

    pub fn set_levels(&mut self, levels: &[Level]) -> Result<()> {
        let mut handle_data = HandleData::new();
        let levels: &[Level] = if levels.len() > HANDLES_MAX {
            &levels[0..HANDLES_MAX]
        } else {
            levels
        };

        for (idx, level) in levels.iter().enumerate() {
            handle_data.values[idx] = *level as u8;
        }

        parse_retval!(unsafe { ioctl(self.fd, REQ_SET_LINE_VALUES, &mut handle_data) })?;

        Ok(())
    }
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct HandleData {
    pub values: [u8; HANDLES_MAX],
}

impl HandleData {
    pub fn new() -> HandleData {
        HandleData {
            values: [0u8; HANDLES_MAX],
        }
    }
}

const EVENT_FLAG_RISING_EDGE: u32 = 0x01;
const EVENT_FLAG_FALLING_EDGE: u32 = 0x02;
const EVENT_FLAG_BOTH_EDGES: u32 = EVENT_FLAG_RISING_EDGE | EVENT_FLAG_FALLING_EDGE;

#[derive(Copy, Clone)]
#[repr(C)]
pub struct EventRequest {
    pub line_offset: u32,
    pub handle_flags: u32,
    pub event_flags: u32,
    pub consumer_label: [u8; LABEL_BUFSIZE],
    pub fd: c_int,
}

impl EventRequest {
    pub fn new(cdev_fd: c_int, pin: u8, trigger: Trigger) -> Result<EventRequest> {
        let mut event_request = EventRequest {
            line_offset: u32::from(pin),
            handle_flags: HANDLE_FLAG_INPUT,
            event_flags: trigger as u32,
            consumer_label: [0u8; LABEL_BUFSIZE],
            fd: 0,
        };

        parse_retval!(unsafe { ioctl(cdev_fd, REQ_GET_LINE_EVENT, &mut event_request) })?;

        Ok(event_request)
    }
}

const EVENT_TYPE_RISING_EDGE: u32 = 0x01;
const EVENT_TYPE_FALLING_EDGE: u32 = 0x02;

#[derive(Copy, Clone)]
#[repr(C)]
struct EventData {
    timestamp: u64,
    id: u32,
}

impl EventData {
    fn new(event_fd: c_int) -> Result<Option<EventData>> {
        let mut event_data = EventData {
            timestamp: 0,
            id: 0,
        };

        let bytes_read = parse_retval!(unsafe {
            read(
                event_fd,
                &mut event_data as *mut EventData as *mut c_void,
                size_of::<EventData>(),
            )
        })?;

        if bytes_read != size_of::<EventData>() as isize {
            Ok(None)
        } else {
            Ok(Some(event_data))
        }
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Event {
    pub trigger: Trigger,
    pub timestamp: Duration,
}

impl Event {
    fn from_event_data(event_data: EventData) -> Event {
        Event {
            trigger: match event_data.id {
                EVENT_TYPE_RISING_EDGE => Trigger::RisingEdge,
                EVENT_TYPE_FALLING_EDGE => Trigger::FallingEdge,
                _ => unreachable!(),
            },
            timestamp: Duration::from_nanos(event_data.timestamp),
        }
    }
}

// Read interrupt event
pub fn get_event(event_fd: c_int) -> Result<Option<Event>> {
    if let Some(event_data) = EventData::new(event_fd)? {
        Ok(Some(Event::from_event_data(event_data)))
    } else {
        Ok(None)
    }
}

// Find the correct gpiochip device based on its label
pub fn find_driver() -> Result<File> {
    let driver_name = b"pinctrl-bcm2835\0";

    for idx in 0..=255 {
        let gpiochip = OpenOptions::new()
            .read(true)
            .write(true)
            .open(format!("/dev/gpiochip{}", idx))?;

        let chip_info = ChipInfo::new(gpiochip.as_raw_fd())?;
        if chip_info.label[0..driver_name.len()] == driver_name[..] {
            return Ok(gpiochip);
        }
    }

    Err(Error::Io(io::Error::from_raw_os_error(2)))
}

pub fn get_level(cdev_fd: c_int, pin: u8) -> Result<Level> {
    let chip_info = ChipInfo::new(cdev_fd)?;

    assert_pin!(u32::from(pin), chip_info.lines);

    match HandleRequest::new(cdev_fd, &[pin])?.levels()?.values[0] {
        0 => Ok(Level::Low),
        1 => Ok(Level::High),
        _ => unreachable!(),
    }
}

pub fn close(fd: c_int) {
    unsafe {
        libc::close(fd);
    }
}
<|endoftext|>


<commit_before>use std::cmp::{Eq, PartialEq, Ordering, PartialOrd};
use rand::Rng;
use rand::distributions::{IndependentSample, Range};

fn schwefel(solution: &Vec<f64>) -> f64 {
    418.9829_f64 * solution.len() as f64
        + solution.iter().fold(0_f64, |sum, x| sum + x * x.abs().sqrt().sin())
}

pub struct Individual {
    pub solution: Vec<f64>,
    pub fitness: f64,
}

impl Individual {
    pub fn new<R: Rng>(range: &Range<f64>, rng: &mut R) -> Individual {
        let solution = (0..50).map(|_| range.ind_sample(rng)).collect();
        let fitness = schwefel(&solution);

        Individual { solution: solution, fitness: fitness }
    }

    pub fn mutate<R: Rng>(&self, range: &Range<f64>, rng: &mut R) -> Individual {
        let solution = self.solution.iter().map(|&x| {
            // mutate 1 in 40 genes to a new value
            if rng.gen_weighted_bool(40) { range.ind_sample(rng) } else { x }
        }).collect();
        let fitness = schwefel(&solution);
        Individual { solution: solution, fitness: fitness }
    }
}

impl Eq for Individual {}

impl Ord for Individual {
    /// This dangerously delegates to `partial_cmp`
    fn cmp(&self, other: &Self) -> Ordering {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result;
        }
        unimplemented!();
    }
}

impl PartialEq<Individual> for Individual {
    /// This doesn't use `fitness.eq()` because it needs to be
    /// consistent with `Eq`
    fn eq(&self, other: &Individual) -> bool {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result == Ordering::Equal;
        }
        unimplemented!();
    }
}

impl PartialOrd for Individual {
    /// This delegates to `fitness.partial_cmp()`
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}
<commit_msg>Implement Clone for Individual<commit_after>use std::cmp::{Eq, PartialEq, Ordering, PartialOrd};
use rand::Rng;
use rand::distributions::{IndependentSample, Range};

fn schwefel(solution: &Vec<f64>) -> f64 {
    418.9829_f64 * solution.len() as f64
        + solution.iter().fold(0_f64, |sum, x| sum + x * x.abs().sqrt().sin())
}

pub struct Individual {
    pub solution: Vec<f64>,
    pub fitness: f64,
}

impl Individual {
    pub fn new<R: Rng>(range: &Range<f64>, rng: &mut R) -> Self {
        let solution = (0..50).map(|_| range.ind_sample(rng)).collect();
        let fitness = schwefel(&solution);

        Individual { solution: solution, fitness: fitness }
    }

    pub fn mutate<R: Rng>(&self, range: &Range<f64>, rng: &mut R) -> Individual {
        let solution = self.solution.iter().map(|&x| {
            // mutate 1 in 40 genes to a new value
            if rng.gen_weighted_bool(40) { range.ind_sample(rng) } else { x }
        }).collect();
        let fitness = schwefel(&solution);
        Individual { solution: solution, fitness: fitness }
    }
}

impl Clone for Individual {
    fn clone(&self) -> Self {
        Individual { solution: self.solution.clone(), fitness: self.fitness }
    }
}

impl Eq for Individual {}

impl Ord for Individual {
    /// This dangerously delegates to `partial_cmp`
    fn cmp(&self, other: &Self) -> Ordering {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result;
        }
        unimplemented!();
    }
}

impl PartialEq<Individual> for Individual {
    /// This doesn't use `fitness.eq()` because it needs to be
    /// consistent with `Eq`
    fn eq(&self, other: &Individual) -> bool {
        if let Some(result) = self.fitness.partial_cmp(&other.fitness) {
            return result == Ordering::Equal;
        }
        unimplemented!();
    }
}

impl PartialOrd for Individual {
    /// This delegates to `fitness.partial_cmp()`
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}
<|endoftext|>


<commit_before>extern crate glium;
extern crate image;
extern crate zip;
extern crate cgmath;
extern crate notify;

use std::io::Read;
use std::fs::File;
use std::io::Cursor;

use glium::backend::Facade;
use glium::texture::{UncompressedUintFormat, MipmapsOption};
use glium::texture::pixel_buffer::PixelBuffer;
use glium::texture::unsigned_texture2d_array::UnsignedTexture2dArray;

pub struct Lightfield {
    pub tex: UnsignedTexture2dArray,
}

impl Lightfield {
    #![allow(dead_code)]
    pub fn new<F: Facade>(facade: &F, zip_filename: &str) -> Lightfield {
        let zipfile = File::open(zip_filename).unwrap();
        let mut archive = zip::ZipArchive::new(zipfile).unwrap();

        // FIXME n's and sizes
        let nx = 1;
        let ny = 1;
        let width = 1400;
        let height = 800;

        let n = nx*ny;
        let tex = UnsignedTexture2dArray::empty_with_format(
            facade,
            UncompressedUintFormat::U8U8U8U8,
            MipmapsOption::NoMipmap,
            width, height, n).unwrap();

        for i in 0..archive.len()
        {
            let mut file = &mut archive.by_index(i).unwrap();
            let name = String::from(file.name());
            println!("loading {}", name);
            let parts: Vec<&str> = name.split("_").collect();
            let ix:u32 = parts[1].parse().unwrap();
            let iy:u32 = parts[2].parse().unwrap();
            assert!(parts[0] == "out");
            let mut contents = Vec::new();
            file.read_to_end(&mut contents).unwrap();

            let image = image::load(Cursor::new(contents), image::JPEG).unwrap().to_rgba();
            let image_dimensions = image.dimensions();
            assert!(image_dimensions == (width, height));
            //let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions);
            let layer = 0; // iy*nx+ix;
            println!("loading layer {}", layer);
            let size = width * height * 4;
            let buffer = PixelBuffer::new_empty(facade, size as usize);
            buffer.write(&image.into_raw());
            assert!(layer<n);
            tex.main_level().raw_upload_from_pixel_buffer(buffer.as_slice(),
            0..width,
            0..height,
            layer..layer+1);
            break; // XXX debug
        }
        Lightfield {tex: tex}
    }
}
<commit_msg>describe texture upload issue<commit_after>extern crate glium;
extern crate image;
extern crate zip;
extern crate cgmath;
extern crate notify;

use std::io::Read;
use std::fs::File;
use std::io::Cursor;

use glium::backend::Facade;
use glium::texture::{UncompressedUintFormat, MipmapsOption};
use glium::texture::pixel_buffer::PixelBuffer;
use glium::texture::unsigned_texture2d_array::UnsignedTexture2dArray;

pub struct Lightfield {
    pub tex: UnsignedTexture2dArray,
}

impl Lightfield {
    #![allow(dead_code)]
    pub fn new<F: Facade>(facade: &F, zip_filename: &str) -> Lightfield {
        let zipfile = File::open(zip_filename).unwrap();
        let mut archive = zip::ZipArchive::new(zipfile).unwrap();

        // FIXME n's and sizes
        let nx = 1;
        let ny = 1;
        let width = 1400;
        let height = 800;

        let n = nx*ny;
        let tex = UnsignedTexture2dArray::empty_with_format(
            facade,
            UncompressedUintFormat::U8U8U8U8,
            MipmapsOption::NoMipmap,
            width, height, n).unwrap();

        for i in 0..archive.len()
        {
            let mut file = &mut archive.by_index(i).unwrap();
            let name = String::from(file.name());
            println!("loading {}", name);
            let parts: Vec<&str> = name.split("_").collect();
            let ix:u32 = parts[1].parse().unwrap();
            let iy:u32 = parts[2].parse().unwrap();
            assert!(parts[0] == "out");
            let mut contents = Vec::new();
            file.read_to_end(&mut contents).unwrap();

            let image = image::load(Cursor::new(contents), image::JPEG).unwrap().to_rgba();
            let image_dimensions = image.dimensions();
            assert!(image_dimensions == (width, height));
            //let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(), image_dimensions);
            let layer = 0; // iy*nx+ix;
            println!("loading layer {}", layer);
            let size = width * height * 4;
            // TODO: due to wrong pixelbuffer format, texture upload uses format = GL_RED_INTEGER
            // how can i write() to a pixelbuffer with T=(u8,u8,u8,u8) from a [u8] src?
            //let buffer = PixelBuffer::<(u8, u8, u8, u8)>::new_empty(facade, size as usize);
            let buffer = PixelBuffer::<u8>::new_empty(facade, size as usize);
            buffer.write(&image.into_raw());
            assert!(layer<n);
            tex.main_level().raw_upload_from_pixel_buffer(buffer.as_slice(),
            0..width,
            0..height,
            layer..layer+1);
            break; // XXX debug
        }
        Lightfield {tex: tex}
    }
}
<|endoftext|>


<commit_before>use dht::KNodeTable;
use dht::GenericNodeTable;

use node::{Address, NodeData, Node};

pub struct NodeStore {
    pub table: KNodeTable<Address, NodeData>,
    pub my_address: Address,
}

impl NodeStore {
    pub fn new(my_address: Address) -> NodeStore {
        NodeStore {
            table: KNodeTable::new(my_address.clone()),
            my_address: my_address,
        }
    }

    pub fn update(&mut self, node: &Node) {
        let insert_suceeded = self.table.update(node);
        if !insert_suceeded {
            self.table.pop_oldest();
            assert!(self.table.update(node));
        }
    }

    pub fn find_closest_nodes(&self, address: &Address, count: usize) -> Vec<Node> {
        self.table.find(address, count)
    }
}
<commit_msg>Add NodeStore::get_node.<commit_after>use dht::KNodeTable;
use dht::GenericNodeTable;

use node::{Address, NodeData, Node};

/// Returns by a request to find a node's path and public key.
#[derive(Clone, Debug)]
pub enum GetNodeResult {
    /// The exact node, if it was found.
    FoundNode(Node),
    /// Nodes close to the searched node. They should be queried about
    /// the searched node.
    ClosestNodes(Vec<Node>),
    /// This table knows of no node at all. It should be bootstrapped
    /// using an external way (ie. find some peers).
    Nothing,
}

pub struct NodeStore {
    pub table: KNodeTable<Address, NodeData>,
    pub my_address: Address,
}

impl NodeStore {
    /// Creates a new empty NodeStore.
    pub fn new(my_address: Address) -> NodeStore {
        NodeStore {
            table: KNodeTable::new(my_address.clone()),
            my_address: my_address,
        }
    }

    /// Inserts a node in the NodeStore, poping nodes from full
    /// buckets if necessary.
    pub fn update(&mut self, node: &Node) {
        let insert_suceeded = self.table.update(node);
        if !insert_suceeded {
            self.table.pop_oldest();
            assert!(self.table.update(node));
        }
    }

    /// Retrurns an ordered vector of nodes, which are the closest to the
    /// target address this NodeStore knows about.
    pub fn find_closest_nodes(&self, address: &Address, count: usize) -> Vec<Node> {
        self.table.find(address, count)
    }

    /// Tries to get a node. On failure, returns `nb_closest` nodes (or all
    /// nodes in the store, if `nb_closest` is too high) that should be
    /// queried about the searched node.
    pub fn get_node(&self, address: &Address, nb_closest: usize) -> GetNodeResult {
        let closest_nodes = self.find_closest_nodes(address, nb_closest);
        match closest_nodes.clone().get(0) { // TODO: do not clone
            Some(closest_node) => {
                if closest_node.id == *address {
                    GetNodeResult::FoundNode(closest_node.clone())
                }
                else {
                    GetNodeResult::ClosestNodes(closest_nodes)
                }
            }
            None => GetNodeResult::Nothing,
        }
    }
}
<|endoftext|>


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

use std::fs::{OpenOptions, remove_file};
use std::io::{BufRead, BufReader, Write};
use std::collections::HashMap;
use std::mem;
use std::ops::Deref;
use strip;
use utils::{join, loop_over_files};

use stripper_interface::{
    TypeStruct,
    EventType,
    Type,
    MOD_COMMENT,
    FILE_COMMENT,
    FILE,
};
use types::OUTPUT_COMMENT_FILE;

fn get_corresponding_type(elements: &[(Option<TypeStruct>, Vec<String>)],
                          to_find: &Option<TypeStruct>,
                          mut line: usize,
                          decal: &mut usize,
                          original_content: &mut Vec<String>) -> Option<usize> {
    let mut pos = 0;

    while pos < elements.len() {
        if match (&elements[pos].0, to_find) {
            (&Some(ref a), &Some(ref b)) => {
                let ret = a == b;

                // to detect variants
                if !ret && b.ty == Type::Unknown && b.parent.is_some() && a.parent.is_some() && a.parent == b.parent {
                    if match b.parent {
                        Some(ref p) => p.ty == Type::Struct || p.ty == Type::Enum || p.ty == Type::Use,
                        None => false,
                    } {
                        let mut tmp = b.clone();

                        tmp.ty = Type::Variant;
                        a == &tmp
                    } else {
                        false
                    }
                } else {
                    ret
                }
            },
            _ => false,
        } {
            let mut file_comment = false;

            if elements[pos].1.len() > 0 && elements[pos].1[0].starts_with(FILE_COMMENT) {
                line += 1;
                file_comment = true;
            } else {
                while line > 0 && (line + *decal) > 0 &&
                      original_content[line + *decal - 1].trim().starts_with("#") {
                    line -= 1;
                }
            }
            for comment in &elements[pos].1 {
                if file_comment {
                    original_content.insert(line + *decal, comment[FILE_COMMENT.len()..].to_owned());
                } else {
                    original_content.insert(line + *decal, comment.clone());
                }
                *decal += 1;
            }
            return Some(pos);
        }
        pos += 1;
    }
    None
}

fn regenerate_comments(path: &str, infos: &mut HashMap<String, Vec<(Option<TypeStruct>, Vec<String>)>>) {
    if !infos.contains_key(path) {
        return;
    }
    match strip::build_event_list(path) {
        Ok(mut parse_result) => {
            let mut elements = infos.get_mut(path).unwrap();
            let mut position = 0;
            let mut decal = 0;

            // first, we need to put back file comment
            for entry in elements.iter() {
                if entry.0.is_none() {
                    let mut it = 0;

                    while it < parse_result.original_content.len() {
                        if parse_result.original_content[it].starts_with("/") &&
                           it + 1 < parse_result.original_content.len() &&
                           parse_result.original_content[it + 1].len() < 1 {
                            it += 2;
                            break;
                        }
                        it += 1;
                    }
                    if it < parse_result.original_content.len() {
                        for line in &entry.1 {
                            parse_result.original_content.insert(it, line.clone());
                            decal += 1;
                            it += 1;
                        }
                    }
                    break;
                }
                position += 1;
            }
            if position < elements.len() {
                elements.remove(position);
            }
            let mut waiting_type = None;
            let mut current = None;
            let mut it = 0;

            while it < parse_result.event_list.len() {
                match parse_result.event_list[it].event {
                    EventType::Type(ref t) => {
                        if t.ty != Type::Unknown {
                            waiting_type = Some(t.clone());
                            let tmp = strip::add_to_type_scope(&current, &waiting_type);

                            match get_corresponding_type(&elements, &tmp,
                                                         parse_result.event_list[it].line,
                                                         &mut decal,
                                                         &mut parse_result.original_content) {
                                Some(l) => { elements.remove(l); },
                                None => {}
                            };
                        } else {
                            match current {
                                Some(ref c) => {
                                    if c.ty == Type::Struct || c.ty == Type::Enum ||
                                       c.ty == Type::Mod {
                                        let tmp = Some(t.clone());
                                        let cc = strip::add_to_type_scope(&current, &tmp);

                                        match get_corresponding_type(&elements, &cc,
                                                                     parse_result.event_list[it].line,
                                                                     &mut decal,
                                                                     &mut parse_result.original_content) {
                                            Some(l) => { elements.remove(l); },
                                            None => {}
                                        }
                                    }
                                }
                                None => {}
                            }
                        }
                    }
                    EventType::InScope => {
                        current = strip::add_to_type_scope(&current, &waiting_type);
                        waiting_type = None;
                        match get_corresponding_type(&elements, &current,
                                                     parse_result.event_list[it].line,
                                                     &mut decal,
                                                     &mut parse_result.original_content) {
                            Some(l) => { elements.remove(l); },
                            None => {}
                        };
                    }
                    EventType::OutScope => {
                        current = strip::type_out_scope(&current);
                        waiting_type = None;
                    }
                    _ => {}
                }
                it += 1;
            }
            rewrite_file(path, &parse_result.original_content);
        }
        Err(e) => {
            println!("Error on file '{}': {}", path, e);
        }
    }
}

fn rewrite_file(path: &str, o_content: &[String]) {
    match OpenOptions::new().write(true).create(true).truncate(true).open(path) {
        Ok(mut f) => {
            write!(f, "{}", o_content.join("\n")).unwrap();
        }
        Err(e) => {
            println!("Cannot open '{}': {}", path, e);
        }
    }
}

fn parse_mod_line(line: &str) -> Option<TypeStruct> {
    let line = line.replace(MOD_COMMENT, "");
    let parts : Vec<&str> = line.split("§").collect();
    let mut current = None;

    for part in parts {
        let elems : Vec<&str> = part.split(" ").filter(|x| x.len() > 0).collect();

        current = strip::add_to_type_scope(&current.clone(),
                                           &Some(TypeStruct::new(Type::from(elems[0]),
                                                                 elems[elems.len() - 1])));
    }
    current
}

fn save_remainings(infos: &HashMap<String, Vec<(Option<TypeStruct>, Vec<String>)>>) {
    let mut remainings = 0;

    for (_, content) in infos {
        if content.len() > 0 {
            remainings += 1;
        }
    }
    if remainings < 1 {
        remove_file(OUTPUT_COMMENT_FILE);
        return;
    }
    match OpenOptions::new().write(true).create(true).truncate(true).open(OUTPUT_COMMENT_FILE) {
        Ok(mut out_file) => {
            println!("Some comments couldn't have been regenerated to the files. Saving them back to '{}'.",
                     OUTPUT_COMMENT_FILE);
            for (key, content) in infos {
                if content.len() < 1 {
                    continue;
                }
                writeln!(out_file, "{}{}", FILE_COMMENT, key);
                for line in content {
                    match line.0 {
                        Some(ref d) => {
                            writeln!(out_file, "{}{}\n{}", MOD_COMMENT, d, join(&line.1, "\n"));
                        }
                        None => {}
                    }
                }
            }
            println!("Not implemented yet.");
        }
        Err(e) => {
            println!("An error occured while trying to open '{}': {}", OUTPUT_COMMENT_FILE, e);
            return;
        }
    }
}

pub fn regenerate_doc_comments(directory: &str, verbose: bool) {
    // we start by storing files info
    let f = match OpenOptions::new().read(true).open(OUTPUT_COMMENT_FILE) {
        Ok(f) => f,
        Err(e) => {
            println!("An error occured while trying to open '{}': {}", OUTPUT_COMMENT_FILE, e);
            return;
        }
    };
    let reader = BufReader::new(f);
    let lines: Vec<String> = reader.lines().collect::<Result<_, _>>().unwrap();
    regenerate_doc_comments_real(directory, verbose, &lines);
}

pub fn regenerate_doc_comments_real<S>(directory: &str, verbose: bool, lines: &[S])
where S: Deref<Target = str> {
    let mut current_file: Option<String> = None;
    let mut infos: HashMap<String, Vec<(Option<TypeStruct>, Vec<String>)>> = HashMap::new();
    let mut current_infos: Vec<(Option<TypeStruct>, Vec<String>)> = vec![];
    let mut it = 0;

    while it < lines.len() {
        if lines[it].starts_with(FILE) {
            if let Some(file) = current_file.take() {
                if !current_infos.is_empty() {
                    infos.insert(file, mem::replace(&mut current_infos, vec![]));
                }
            }
            current_file = Some(lines[it].replace(FILE, "").to_owned());
            it += 1;
        } else if lines[it].starts_with(MOD_COMMENT) {
            let ty = parse_mod_line(&lines[it]);
            let mut comments = vec!();

            it += 1;
            if ty.is_none() {
                continue;
            }
            while it < lines.len() {
                if lines[it].starts_with(MOD_COMMENT) ||
                   lines[it].starts_with(FILE) {
                    break;
                }
                comments.push(lines[it].to_owned());
                it += 1;
            }
            if comments.len() > 0 {
                current_infos.push((ty, comments));
            }
        } else if lines[it].starts_with(FILE_COMMENT) {
            let mut comment_lines = vec!();

            while it < lines.len() && lines[it].starts_with(FILE_COMMENT) {
                comment_lines.push(lines[it][FILE_COMMENT.len()..].to_owned());
                it += 1;
            }
            current_infos.push((None, comment_lines));
        }
    }
    if let Some(file) = current_file.take() {
        if !current_infos.is_empty() {
            infos.insert(file, mem::replace(&mut current_infos, vec![]));
        }
    }
    loop_over_files(directory, &mut infos, &regenerate_comments, &vec!(), verbose);
    save_remainings(&infos);
    // TODO: rewrite comments.cmts with remaining infos in regenerate_comments
}
<commit_msg>Reimplement the parser as something resembling an FSM<commit_after>// Copyright 2015 Gomez Guillaume
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fs::{OpenOptions, remove_file};
use std::io::{BufRead, BufReader, Write};
use std::collections::HashMap;
use std::ops::Deref;
use strip;
use utils::{join, loop_over_files};

use stripper_interface::{
    TypeStruct,
    EventType,
    Type,
    MOD_COMMENT,
    FILE_COMMENT,
    FILE,
};
use types::OUTPUT_COMMENT_FILE;

fn get_corresponding_type(elements: &[(Option<TypeStruct>, Vec<String>)],
                          to_find: &Option<TypeStruct>,
                          mut line: usize,
                          decal: &mut usize,
                          original_content: &mut Vec<String>) -> Option<usize> {
    let mut pos = 0;

    while pos < elements.len() {
        if match (&elements[pos].0, to_find) {
            (&Some(ref a), &Some(ref b)) => {
                let ret = a == b;

                // to detect variants
                if !ret && b.ty == Type::Unknown && b.parent.is_some() && a.parent.is_some() && a.parent == b.parent {
                    if match b.parent {
                        Some(ref p) => p.ty == Type::Struct || p.ty == Type::Enum || p.ty == Type::Use,
                        None => false,
                    } {
                        let mut tmp = b.clone();

                        tmp.ty = Type::Variant;
                        a == &tmp
                    } else {
                        false
                    }
                } else {
                    ret
                }
            },
            _ => false,
        } {
            let mut file_comment = false;

            if elements[pos].1.len() > 0 && elements[pos].1[0].starts_with(FILE_COMMENT) {
                line += 1;
                file_comment = true;
            } else {
                while line > 0 && (line + *decal) > 0 &&
                      original_content[line + *decal - 1].trim().starts_with("#") {
                    line -= 1;
                }
            }
            for comment in &elements[pos].1 {
                if file_comment {
                    original_content.insert(line + *decal, comment[FILE_COMMENT.len()..].to_owned());
                } else {
                    original_content.insert(line + *decal, comment.clone());
                }
                *decal += 1;
            }
            return Some(pos);
        }
        pos += 1;
    }
    None
}

fn regenerate_comments(path: &str, infos: &mut HashMap<String, Vec<(Option<TypeStruct>, Vec<String>)>>) {
    if !infos.contains_key(path) {
        return;
    }
    match strip::build_event_list(path) {
        Ok(mut parse_result) => {
            let mut elements = infos.get_mut(path).unwrap();
            let mut position = 0;
            let mut decal = 0;

            // first, we need to put back file comment
            for entry in elements.iter() {
                if entry.0.is_none() {
                    let mut it = 0;

                    while it < parse_result.original_content.len() {
                        if parse_result.original_content[it].starts_with("/") &&
                           it + 1 < parse_result.original_content.len() &&
                           parse_result.original_content[it + 1].len() < 1 {
                            it += 2;
                            break;
                        }
                        it += 1;
                    }
                    if it < parse_result.original_content.len() {
                        for line in &entry.1 {
                            parse_result.original_content.insert(it, line.clone());
                            decal += 1;
                            it += 1;
                        }
                    }
                    break;
                }
                position += 1;
            }
            if position < elements.len() {
                elements.remove(position);
            }
            let mut waiting_type = None;
            let mut current = None;
            let mut it = 0;

            while it < parse_result.event_list.len() {
                match parse_result.event_list[it].event {
                    EventType::Type(ref t) => {
                        if t.ty != Type::Unknown {
                            waiting_type = Some(t.clone());
                            let tmp = strip::add_to_type_scope(&current, &waiting_type);

                            match get_corresponding_type(&elements, &tmp,
                                                         parse_result.event_list[it].line,
                                                         &mut decal,
                                                         &mut parse_result.original_content) {
                                Some(l) => { elements.remove(l); },
                                None => {}
                            };
                        } else {
                            match current {
                                Some(ref c) => {
                                    if c.ty == Type::Struct || c.ty == Type::Enum ||
                                       c.ty == Type::Mod {
                                        let tmp = Some(t.clone());
                                        let cc = strip::add_to_type_scope(&current, &tmp);

                                        match get_corresponding_type(&elements, &cc,
                                                                     parse_result.event_list[it].line,
                                                                     &mut decal,
                                                                     &mut parse_result.original_content) {
                                            Some(l) => { elements.remove(l); },
                                            None => {}
                                        }
                                    }
                                }
                                None => {}
                            }
                        }
                    }
                    EventType::InScope => {
                        current = strip::add_to_type_scope(&current, &waiting_type);
                        waiting_type = None;
                        match get_corresponding_type(&elements, &current,
                                                     parse_result.event_list[it].line,
                                                     &mut decal,
                                                     &mut parse_result.original_content) {
                            Some(l) => { elements.remove(l); },
                            None => {}
                        };
                    }
                    EventType::OutScope => {
                        current = strip::type_out_scope(&current);
                        waiting_type = None;
                    }
                    _ => {}
                }
                it += 1;
            }
            rewrite_file(path, &parse_result.original_content);
        }
        Err(e) => {
            println!("Error on file '{}': {}", path, e);
        }
    }
}

fn rewrite_file(path: &str, o_content: &[String]) {
    match OpenOptions::new().write(true).create(true).truncate(true).open(path) {
        Ok(mut f) => {
            write!(f, "{}", o_content.join("\n")).unwrap();
        }
        Err(e) => {
            println!("Cannot open '{}': {}", path, e);
        }
    }
}

fn parse_mod_line(line: &str) -> Option<TypeStruct> {
    let line = line.replace(MOD_COMMENT, "");
    let parts : Vec<&str> = line.split("§").collect();
    let mut current = None;

    for part in parts {
        let elems : Vec<&str> = part.split(" ").filter(|x| x.len() > 0).collect();

        current = strip::add_to_type_scope(&current.clone(),
                                           &Some(TypeStruct::new(Type::from(elems[0]),
                                                                 elems[elems.len() - 1])));
    }
    current
}

fn save_remainings(infos: &HashMap<String, Vec<(Option<TypeStruct>, Vec<String>)>>) {
    let mut remainings = 0;

    for (_, content) in infos {
        if content.len() > 0 {
            remainings += 1;
        }
    }
    if remainings < 1 {
        remove_file(OUTPUT_COMMENT_FILE);
        return;
    }
    match OpenOptions::new().write(true).create(true).truncate(true).open(OUTPUT_COMMENT_FILE) {
        Ok(mut out_file) => {
            println!("Some comments couldn't have been regenerated to the files. Saving them back to '{}'.",
                     OUTPUT_COMMENT_FILE);
            for (key, content) in infos {
                if content.len() < 1 {
                    continue;
                }
                writeln!(out_file, "{}{}", FILE_COMMENT, key);
                for line in content {
                    match line.0 {
                        Some(ref d) => {
                            writeln!(out_file, "{}{}\n{}", MOD_COMMENT, d, join(&line.1, "\n"));
                        }
                        None => {}
                    }
                }
            }
            println!("Not implemented yet.");
        }
        Err(e) => {
            println!("An error occured while trying to open '{}': {}", OUTPUT_COMMENT_FILE, e);
            return;
        }
    }
}

pub fn regenerate_doc_comments(directory: &str, verbose: bool) {
    // we start by storing files info
    let f = match OpenOptions::new().read(true).open(OUTPUT_COMMENT_FILE) {
        Ok(f) => f,
        Err(e) => {
            println!("An error occured while trying to open '{}': {}", OUTPUT_COMMENT_FILE, e);
            return;
        }
    };
    let reader = BufReader::new(f);
    let lines: Vec<String> = reader.lines().collect::<Result<_, _>>().unwrap();
    regenerate_doc_comments_real(directory, verbose, &lines);
}

pub fn regenerate_doc_comments_real<S>(directory: &str, verbose: bool, lines: &[S])
where S: Deref<Target = str> {
    let mut infos = parse(lines);
    loop_over_files(directory, &mut infos, &regenerate_comments, &vec!(), verbose);
    save_remainings(&infos);
    // TODO: rewrite comments.cmts with remaining infos in regenerate_comments
}

fn parse<S: Deref<Target = str>>(lines: &[S]) -> HashMap<String, Vec<(Option<TypeStruct>, Vec<String>)>> {
    enum State {
        Initial,
        File {
            file: String,
            infos: Vec<(Option<TypeStruct>, Vec<String>)>,
            ty: Option<TypeStruct>,
            comments: Vec<String>,
        }
    }

    let mut ret = HashMap::new();
    let mut lines = lines.iter();
    let mut state = State::Initial;

    while let Some(line) = lines.next() {
        state = match state {
            State::Initial => {
                if line.starts_with(FILE) {
                    State::File {
                        file: line[FILE.len()..].to_owned(),
                        infos: vec![],
                        ty: None,
                        comments: vec![],
                    }
                } else {
                    panic!("Unrecognized format");
                }
            }
            State::File { mut file, mut infos, mut ty, mut comments } => {
                if line.starts_with(FILE) {
                    if !comments.is_empty() {
                        infos.push((ty.take(), comments));
                        comments = vec![];
                    }
                    if !infos.is_empty() {
                        ret.insert(file, infos);
                        file = line[FILE.len()..].to_owned();
                        infos = vec![];
                    }
                } else if line.starts_with(FILE_COMMENT) {
                    if let Some(ty) = ty.take() {
                        if !comments.is_empty() {
                            infos.push((Some(ty), comments));
                            comments = vec![];
                        }
                    } else {
                        comments.push(line[FILE_COMMENT.len()..].to_owned());
                    }
                } else if line.starts_with(MOD_COMMENT) {
                    if !comments.is_empty() {
                        infos.push((ty, comments));
                        comments = vec![];
                    }
                    ty = parse_mod_line(line);
                } else {
                    if ty.is_some() {
                        comments.push(line[..].to_owned());
                    } else {
                        panic!("Orphan comment");
                    }
                }
                State::File {
                    file: file,
                    infos: infos,
                    ty: ty,
                    comments: comments,
                }
            }
        }
    }

    if let State::File { file, mut infos, ty, comments } = state {
        if !comments.is_empty() {
            infos.push((ty, comments));
        }
        if !infos.is_empty() {
            ret.insert(file, infos);
        }
    }

    ret
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::error::Error;
use std::sync::Arc;
use std::net::ToSocketAddrs;
use std::io;

use soio::Token;
use soio::Poll;
use soio::Ready;
use soio::PollOpt;
use soio::channel::{self, Receiver, Sender};
use soio::Events;
use soio::Event;
use soio::tcp::TcpListener;
use soio::Evented;

use threading::Pool;

use self::connection::Connection;
pub use self::stream::Stream;

pub mod connection;
pub mod stream;

const SERVER: Token = Token(0);
const CHANNEL: Token = Token(1);

pub type Handle = Box<Fn(Stream) + Send + Sync + 'static>;

pub struct Server {
    listener: TcpListener,
    conns: HashMap<Token, Connection>,
    token: usize,
    handle: Arc<Handle>,
    poll: Poll,
    events: Events,
    thread_pool: Pool,
    tx: Sender<connection::Event>,
    rx: Receiver<connection::Event>,
    run: bool,
}

impl Server {
    pub fn new<A: ToSocketAddrs>(addr: A) -> Result<Server, Box<Error + Send + Sync>> {
        let (tx, rx) = channel::channel::<connection::Event>();

        Ok(Server {
            listener: TcpListener::bind(addr)?,
            conns: HashMap::new(),
            token: 4,
            handle: Arc::new(Box::new(|_| {})),
            poll: Poll::new().unwrap(),
            events: Events::with_capacity(1024),
            thread_pool: Pool::new(),
            tx: tx,
            rx: rx,
            run: true,
        })
    }

    pub fn handle(&mut self, handle: Handle) {
        self.handle = Arc::new(handle);
    }

    fn token(&mut self) -> Token {
        self.token += 1;
        Token(self.token)
    }

    fn accept(&mut self) -> io::Result<()> {
        let (socket, _) = self.listener.accept()?;

        let thread_pool = self.thread_pool.clone();
        let tx = self.tx.clone();
        let token = self.token();

        let handle = self.handle.clone();

        self.poll.register(&socket, token, Ready::readable(), PollOpt::edge() | PollOpt::oneshot())?;
        self.conns.insert(token, Connection::new(socket, token, thread_pool, tx, handle));

        Ok(())
    }

    fn channel(&mut self) -> io::Result<()> {
        loop {
            match self.rx.try_recv() {
                Ok(event) => {
                    match event {
                        connection::Event::Close(token) => {
                            if let Some(conn) = self.conns.remove(&token) {
                                conn.deregister(&self.poll)?;
                            }
                        },
                        connection::Event::Write(token) => {
                            if let Some(conn) = self.conns.get(&token) {
                                conn.reregister(&self.poll, token, Ready::writable(), PollOpt::edge() | PollOpt::oneshot())?;
                            }
                        },
                        connection::Event::Read(token) => {
                            if let Some(conn) = self.conns.get(&token) {
                                conn.reregister(&self.poll, token, Ready::readable(), PollOpt::edge() | PollOpt::oneshot())?;
                            }
                        }
                    }
                },
                Err(_) => {
                    break;
                }
            }
        }

        Ok(())
    }

    fn connect(&mut self, event: Event ,token: Token) -> io::Result<()> {
        if event.readiness().is_hup() || event.readiness().is_error() {
            if let Some(conn) = self.conns.remove(&token) {
                conn.deregister(&self.poll)?;
            }
        }

        if event.readiness().is_readable() {
            let mut close = false;

            if let Some(mut conn) = self.conns.get_mut(&token) {
                conn.read();

                close = conn.closing;
            }

            if close {
                if let Some(conn) = self.conns.remove(&token) {
                    conn.deregister(&self.poll)?;
                }
            }
        }

        if event.readiness().is_writable() {
            let mut close = false;

            if let Some(mut conn) = self.conns.get_mut(&token) {
                conn.write();

                close =  conn.closing;
            }

            if close {
                if let Some(conn) = self.conns.remove(&token) {
                    conn.deregister(&self.poll)?;
                }
            } else {
                if let Some(conn) = self.conns.get(&token) {
                    conn.reregister(&self.poll, token, Ready::readable(), PollOpt::edge() | PollOpt::oneshot())?;
                }
            }
        }

        Ok(())
    }

    pub fn event(&mut self, event: Event) -> io::Result<()> {
        match event.token() {
            SERVER => {
                self.accept()
            },
            CHANNEL => {
                self.channel()
            },
            token => {
                self.connect(event, token)
            }
        }
    }

    pub fn run_once(&mut self) -> io::Result<()> {
        let size = try!(self.poll.poll(&mut self.events, None));

        for i in 0..size {
            let event = self.events.get(i).unwrap();
            self.event(event)?;
        }

        Ok(())
    }

    pub fn run(&mut self, handle: Handle) -> io::Result<()> {
        self.handle = Arc::new(handle);

        self.poll.register(&self.listener, SERVER, Ready::readable(), PollOpt::edge())?;

        self.poll.register(&self.rx, CHANNEL, Ready::readable(), PollOpt::edge())?;

        self.run = true;

        while self.run {
            try!(self.run_once())
        }

        Ok(())
    }
}
<commit_msg>rewrite server channel err result<commit_after>use std::collections::HashMap;
use std::error::Error;
use std::sync::Arc;
use std::net::ToSocketAddrs;
use std::io::{self, ErrorKind};
use std::sync::mpsc::TryRecvError;

use soio::Token;
use soio::Poll;
use soio::Ready;
use soio::PollOpt;
use soio::channel::{self, Receiver, Sender};
use soio::Events;
use soio::Event;
use soio::tcp::TcpListener;
use soio::Evented;

use threading::Pool;

use self::connection::Connection;
pub use self::stream::Stream;

pub mod connection;
pub mod stream;

const SERVER: Token = Token(0);
const CHANNEL: Token = Token(1);

pub type Handle = Box<Fn(Stream) + Send + Sync + 'static>;

pub struct Server {
    listener: TcpListener,
    conns: HashMap<Token, Connection>,
    token: usize,
    handle: Arc<Handle>,
    poll: Poll,
    events: Events,
    thread_pool: Pool,
    tx: Sender<connection::Event>,
    rx: Receiver<connection::Event>,
    run: bool,
}

impl Server {
    pub fn new<A: ToSocketAddrs>(addr: A) -> Result<Server, Box<Error + Send + Sync>> {
        let (tx, rx) = channel::channel::<connection::Event>();

        Ok(Server {
            listener: TcpListener::bind(addr)?,
            conns: HashMap::new(),
            token: 4,
            handle: Arc::new(Box::new(|_| {})),
            poll: Poll::new().unwrap(),
            events: Events::with_capacity(1024),
            thread_pool: Pool::new(),
            tx: tx,
            rx: rx,
            run: true,
        })
    }

    pub fn handle(&mut self, handle: Handle) {
        self.handle = Arc::new(handle);
    }

    fn token(&mut self) -> Token {
        self.token += 1;
        Token(self.token)
    }

    fn accept(&mut self) -> io::Result<()> {
        let (socket, _) = self.listener.accept()?;

        let thread_pool = self.thread_pool.clone();
        let tx = self.tx.clone();
        let token = self.token();

        let handle = self.handle.clone();

        self.poll.register(&socket, token, Ready::readable(), PollOpt::edge() | PollOpt::oneshot())?;
        self.conns.insert(token, Connection::new(socket, token, thread_pool, tx, handle));

        Ok(())
    }

    fn channel(&mut self) -> io::Result<()> {
        loop {
            match self.rx.try_recv() {
                Ok(event) => {
                    match event {
                        connection::Event::Close(token) => {
                            if let Some(conn) = self.conns.remove(&token) {
                                conn.deregister(&self.poll)?;
                            }
                        },
                        connection::Event::Write(token) => {
                            if let Some(conn) = self.conns.get(&token) {
                                conn.reregister(&self.poll, token, Ready::writable(), PollOpt::edge() | PollOpt::oneshot())?;
                            }
                        },
                        connection::Event::Read(token) => {
                            if let Some(conn) = self.conns.get(&token) {
                                conn.reregister(&self.poll, token, Ready::readable(), PollOpt::edge() | PollOpt::oneshot())?;
                            }
                        }
                    }
                },
                Err(err) => {
                    match err {
                        TryRecvError::Empty => break,
                        TryRecvError::Disconnected => return Err(io::Error::new(ErrorKind::ConnectionAborted, err)),
                    }
                }
            }
        }

        Ok(())
    }

    fn connect(&mut self, event: Event ,token: Token) -> io::Result<()> {
        if event.readiness().is_hup() || event.readiness().is_error() {
            if let Some(conn) = self.conns.remove(&token) {
                conn.deregister(&self.poll)?;
            }
        }

        if event.readiness().is_readable() {
            let mut close = false;

            if let Some(mut conn) = self.conns.get_mut(&token) {
                conn.read();

                close = conn.closing;
            }

            if close {
                if let Some(conn) = self.conns.remove(&token) {
                    conn.deregister(&self.poll)?;
                }
            }
        }

        if event.readiness().is_writable() {
            let mut close = false;

            if let Some(mut conn) = self.conns.get_mut(&token) {
                conn.write();

                close =  conn.closing;
            }

            if close {
                if let Some(conn) = self.conns.remove(&token) {
                    conn.deregister(&self.poll)?;
                }
            } else {
                if let Some(conn) = self.conns.get(&token) {
                    conn.reregister(&self.poll, token, Ready::readable(), PollOpt::edge() | PollOpt::oneshot())?;
                }
            }
        }

        Ok(())
    }

    pub fn event(&mut self, event: Event) -> io::Result<()> {
        match event.token() {
            SERVER => {
                self.accept()
            },
            CHANNEL => {
                self.channel()
            },
            token => {
                self.connect(event, token)
            }
        }
    }

    pub fn run_once(&mut self) -> io::Result<()> {
        let size = self.poll.poll(&mut self.events, None)?;

        for i in 0..size {
            let event = self.events.get(i).unwrap();
            self.event(event)?;
        }

        Ok(())
    }

    pub fn run(&mut self, handle: Handle) -> io::Result<()> {
        self.handle = Arc::new(handle);

        self.poll.register(&self.listener, SERVER, Ready::readable(), PollOpt::edge())?;

        self.poll.register(&self.rx, CHANNEL, Ready::readable(), PollOpt::edge())?;

        self.run = true;

        while self.run {
            self.run_once()?;
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>#[cfg(feature="pkg-config")]
extern crate pkg_config;

fn main() {
    if !build_pkgconfig() {
        let target = ::std::env::var("TARGET").expect("Cargo build scripts always have TARGET");
        let target_os = target.splitn(3, "-").nth(2).unwrap();

        if cfg!(feature="use_mac_framework") && target_os == "darwin" {
            println!("cargo:rustc-flags=-l framework=SDL2");
        } else {
            println!("cargo:rustc-flags=-l SDL2");
        }
    }
}

#[cfg(not(feature="pkg-config"))]
fn build_pkgconfig() -> bool {
    false
}

#[cfg(feature="pkg-config")]
fn build_pkgconfig() -> bool {
    if pkg_config::find_library("sdl2").is_err() {
        panic!("Could not find SDL2 via pkgconfig");
    }
    true
}
<commit_msg>Add link directives for iOS frameworks<commit_after>#[cfg(feature="pkg-config")]
extern crate pkg_config;

fn main() {
    let target = ::std::env::var("TARGET").expect("Cargo build scripts always have TARGET");
    let target_os = target.splitn(3, "-").nth(2).unwrap();

    if !build_pkgconfig() {
        if cfg!(feature="use_mac_framework") && target_os == "darwin" {
            println!("cargo:rustc-flags=-l framework=SDL2");
        } else {
            println!("cargo:rustc-flags=-l SDL2");
        }
    }

    if target_os == "ios" {
        println!("cargo:rustc-flags=-l framework=AVFoundation");
        println!("cargo:rustc-flags=-l framework=AudioToolbox");
        println!("cargo:rustc-flags=-l framework=CoreAudio");
        println!("cargo:rustc-flags=-l framework=CoreGraphics");
        println!("cargo:rustc-flags=-l framework=CoreMotion");
        println!("cargo:rustc-flags=-l framework=Foundation");
        println!("cargo:rustc-flags=-l framework=GameController");
        println!("cargo:rustc-flags=-l framework=OpenGLES");
        println!("cargo:rustc-flags=-l framework=QuartzCore");
        println!("cargo:rustc-flags=-l framework=UIKit");
    }
}

#[cfg(not(feature="pkg-config"))]
fn build_pkgconfig() -> bool {
    false
}

#[cfg(feature="pkg-config")]
fn build_pkgconfig() -> bool {
    if pkg_config::find_library("sdl2").is_err() {
        panic!("Could not find SDL2 via pkgconfig");
    }
    true
}
<|endoftext|>


<commit_before>
use winapi::HKEY;
use winreg::{RegKey, EnumKeys};
use winreg::enums::*;

use std::io;
use std::iter;
use std::path::PathBuf;

#[derive(Debug)]
pub struct Installers(RegKey);
#[derive(Debug)]
pub struct AllInstallers(Installers, Installers);

#[derive(Debug)]
pub struct Installer {
    id: String,
    key: RegKey,
}

impl Installer {
    pub fn product_id(&self) -> &str {
        &self.id
    }
    pub fn comments(&self) -> io::Result<String> {
        self.key.get_value("Comments")
    }
    pub fn display_name(&self) -> io::Result<String> {
        self.key.get_value("DisplayName")
    }
    pub fn display_version(&self) -> io::Result<String> {
        self.key.get_value("DisplayVersion")
    }
    pub fn estimated_size_kb(&self) -> io::Result<u32> {
        self.key.get_value("EstimatedSize")
    }
    pub fn install_date(&self) -> io::Result<String> {
        self.key.get_value("InstallDate")
    }
    pub fn install_location(&self) -> io::Result<PathBuf> {
        self.key.get_value("InstallLocation").map(|s: String| s.into())
    }
    pub fn install_source(&self) -> io::Result<PathBuf> {
        self.key.get_value("InstallSource").map(|s: String| s.into())
    }
    pub fn language(&self) -> io::Result<u32> {
        self.key.get_value("Language")
    }
    pub fn publisher(&self) -> io::Result<String> {
        self.key.get_value("Publisher")
    }
    pub fn url_info_about(&self) -> io::Result<String> {
        self.key.get_value("UrlInfoAbout")
    }
    pub fn version(&self) -> io::Result<u32> {
        self.key.get_value("Version")
    }
    pub fn version_major(&self) -> io::Result<u32> {
        self.key.get_value("VersionMajor")
    }
    pub fn version_minor(&self) -> io::Result<u32> {
        self.key.get_value("VersionMinor")
    }
    pub fn system_component(&self) -> bool {
        if let Ok(1u32) = self.key.get_value("SystemComponent") {
            true
        } else {
            false
        }
    }
}

impl<'a> IntoIterator for &'a Installers {
    type IntoIter = InstallerIter<'a>;
    type Item = Installer;

    fn into_iter(self) -> InstallerIter<'a> {
        self.iter()
    }
}

impl AllInstallers {
    pub fn iter(&self) -> iter::Chain<InstallerIter, InstallerIter> {
        self.0.iter().chain(self.1.iter())
    }
}

impl<'a> IntoIterator for &'a AllInstallers {
    type IntoIter = iter::Chain<InstallerIter<'a>, InstallerIter<'a>>;
    type Item = Installer;

    fn into_iter(self) -> iter::Chain<InstallerIter<'a>, InstallerIter<'a>> {
        self.iter()
    }
}

impl Installers {
    pub fn iter(&self) -> InstallerIter {
        InstallerIter(&self.0, self.0.enum_keys())
    }
}

pub struct InstallerIter<'a>(&'a RegKey, EnumKeys<'a>);

impl<'a> Iterator for InstallerIter<'a> {
    type Item = Installer;

    fn next(&mut self) -> Option<Installer> {
        loop {
            let n = self.1.next();

            if let Some(result) = n {
                if let Ok(name) = result {
                    if let Ok(key) = self.0.open_subkey_with_flags(&name, KEY_READ) {
                        if let Ok(1u32) = key.get_value("WindowsInstaller") {
                            return Some(Installer {
                                id: name,
                                key: key,
                            });
                        }
                    }
                }
            } else {
                return None;
            }
        }
    }
}

fn read_installer_registry(key: HKEY) -> io::Result<Installers> {
    let root = RegKey::predef(key);
    let uninstall = try!(root.open_subkey_with_flags("SOFTWARE\\Microsoft\\Windows\\CurrentVersi\
                                                      on\\Uninstall",
                                                     KEY_READ));

    Ok(Installers(uninstall))
}

pub fn local_machine_installers() -> io::Result<Installers> {
    read_installer_registry(HKEY_LOCAL_MACHINE)
}

pub fn current_user_installers() -> io::Result<Installers> {
    read_installer_registry(HKEY_CURRENT_USER)
}

pub fn all_installers() -> io::Result<AllInstallers> {
    Ok(AllInstallers(try!(local_machine_installers()),
                     try!(current_user_installers())))
}
<commit_msg>Remove unused file<commit_after><|endoftext|>


<commit_before>
mod internal
{
  use std::collections::HashMap;
  use std::rc::Rc;
  use std::fmt;
  use crate::*;
  use wtools::error::Error;

  //

  ///
  /// Handle for command routine.
  ///

  pub struct OnCommand( Option<Rc<dyn Fn( &instruction::Instruction ) -> Result<(), Error>>> );

  impl OnCommand
  {
    /// Checks that OnCommand has callback to call.
    pub fn callable( &self ) -> bool
    {
      if self.0.is_some()
      {
        true
      }
      else
      {
        false
      }
    }
    /// Perform callback.
    pub fn perform( &self, instruction : &instruction::Instruction ) -> Result<(), Error>
    {
      if self.0.is_some()
      {
        let r = self.0.as_ref().unwrap();
        return r( instruction );
      }

      Ok( () )
    }
  }

  impl Default for OnCommand
  {
    fn default() -> Self
    {
      Self ( Option::None )
    }
  }

  impl From<&'static dyn Fn( &instruction::Instruction ) -> Result<(), Error>> for OnCommand
  {
    fn from( src : &'static dyn Fn( &instruction::Instruction ) -> Result<(), Error> ) -> Self
    {
      OnCommand( Some( Rc::new( src ) ) )
    }
  }

  impl Clone for OnCommand
  {
    fn clone( &self ) -> Self
    {
      match self
      {
        OnCommand ( Option::None ) => Self ( None ),
        OnCommand ( Option::Some( boxed ) ) => Self ( Some( boxed.clone() ) ),
      }
    }
  }

  impl fmt::Debug for OnCommand
  {
    fn fmt( &self, f: &mut fmt::Formatter<'_> ) -> fmt::Result
    {
      match self
      {
        OnCommand ( Option::None ) => f.write_str( "None" ),
        OnCommand ( Option::Some( _rc ) ) => f.write_str( "OnCommand" ),
      }
    }
  }

  ///
  /// Command descriptor.
  ///

  #[derive( Default, Debug, Clone )]
  pub struct Command
  {
    /// Command common hint.
    pub hint : String,
    /// Command full hint.
    pub long_hint : String,
    /// Phrase descriptor for command.
    pub phrase : String,
    /// Command subject hint.
    pub subject_hint : String,
    /// Hints for command options.
    pub properties_hints : HashMap< String, String >,
    /// Map of aliases.
    pub properties_aliases : HashMap< String, Vec< String > >,
    /// Command routine.
    pub routine : OnCommand,
  }

  impl Command
  {
    /// Execute callback.
    pub fn perform( &self, instruction : &instruction::Instruction ) -> Result<(), Error>
    {
      if self.routine.callable()
      {
        return self.routine.perform( instruction );
      }

      Ok( () )
    }
  }

  ///
  /// Options for command.
  ///

  #[derive( Debug, Clone, Default )]
  pub struct CommandOptions
  {
    ins : Command,
  }

  //

  // ro : null,
  // h : null,
  // lh : null,

  impl CommandOptions
  {
    field_str!{ hint }
    field_str!{ hint, h }
    field_str!{ long_hint }
    field_str!{ long_hint, lh }
    field_str!{ phrase }
    field_str!{ subject_hint }
    field_str!{ subject_hint, sh }
    field_map_str_str!{ properties_hints, property_hint }
    field_map_str_vec_str!{ properties_aliases, property_alias }
    field_routine!{ routine }
    field_routine!{ routine, ro }

    // pub fn hint< Str : AsRef< str > >( &mut self, src : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.hint = src.into();
    //   self
    // }
    // pub fn long_hint< Str : AsRef< str > >( &mut self, src : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.long_hint = src.into();
    //   self
    // }
    // pub fn phrase< Str : AsRef< str > >( &mut self, src : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.phrase = src.into();
    //   self
    // }
    // pub fn subject_hint< Str : AsRef< str > >( &mut self, src : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.subject_hint = src.into();
    //   self
    // }
    // pub fn property_hint< Str : AsRef< str > >( &mut self, property : Str, hint : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.properties_hints.insert( property.into(), hint.into() );
    //   self
    // }
    // pub fn property_alias< Str : AsRef< str > >( &mut self, property : Str, alias : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   let entry = self.ins.properties_aliases.entry( property.into() ).or_insert_with( || -> Vec< String > { vec![] } );
    //   entry.push( alias.into() );
    //   self
    // }
    //
    // pub fn routine( &mut self, routine : &'static dyn Fn() ) -> &mut Self
    // {
    //   self.ins.routine = routine.into();
    //   self
    // }

    /// Command former.
    pub fn form( &self ) -> Command
    {
      self.ins.clone()
    }

  }

  // impl Options for CommandOptions
  // {
  //   type For = Command;
  // }
}

/// Owned namespace of the module.
pub mod own
{
  use super::internal as i;

  pub use i::OnCommand;
  pub use i::Command;
  pub use i::CommandOptions;
}

pub use own::*;

/// Exposed namespace of the module.
pub mod exposed
{
  use super::internal as i;

  pub use i::OnCommand;
  pub use i::Command;
  pub use i::CommandOptions;
}

/// Namespace of the module to include with `use module::*`.
pub mod prelude
{
  use super::internal as i;

  pub use i::OnCommand;
  pub use i::Command;
  pub use i::CommandOptions;
}

<commit_msg>Extend method `perform` of commands, validate subject and properties<commit_after>
mod internal
{
  use std::collections::HashMap;
  use std::rc::Rc;
  use std::fmt;
  use crate::*;
  use wtools::error::Error;

  //

  ///
  /// Handle for command routine.
  ///

  pub struct OnCommand( Option<Rc<dyn Fn( &instruction::Instruction ) -> Result<(), Error>>> );

  impl OnCommand
  {
    /// Checks that OnCommand has callback to call.
    pub fn callable( &self ) -> bool
    {
      if self.0.is_some()
      {
        true
      }
      else
      {
        false
      }
    }
    /// Perform callback.
    pub fn perform( &self, instruction : &instruction::Instruction ) -> Result<(), Error>
    {
      if self.0.is_some()
      {
        let r = self.0.as_ref().unwrap();
        return r( instruction );
      }

      Ok( () )
    }
  }

  impl Default for OnCommand
  {
    fn default() -> Self
    {
      Self ( Option::None )
    }
  }

  impl From<&'static dyn Fn( &instruction::Instruction ) -> Result<(), Error>> for OnCommand
  {
    fn from( src : &'static dyn Fn( &instruction::Instruction ) -> Result<(), Error> ) -> Self
    {
      OnCommand( Some( Rc::new( src ) ) )
    }
  }

  impl Clone for OnCommand
  {
    fn clone( &self ) -> Self
    {
      match self
      {
        OnCommand ( Option::None ) => Self ( None ),
        OnCommand ( Option::Some( boxed ) ) => Self ( Some( boxed.clone() ) ),
      }
    }
  }

  impl fmt::Debug for OnCommand
  {
    fn fmt( &self, f: &mut fmt::Formatter<'_> ) -> fmt::Result
    {
      match self
      {
        OnCommand ( Option::None ) => f.write_str( "None" ),
        OnCommand ( Option::Some( _rc ) ) => f.write_str( "OnCommand" ),
      }
    }
  }

  ///
  /// Command descriptor.
  ///

  #[derive( Default, Debug, Clone )]
  pub struct Command
  {
    /// Command common hint.
    pub hint : String,
    /// Command full hint.
    pub long_hint : String,
    /// Phrase descriptor for command.
    pub phrase : String,
    /// Command subject hint.
    pub subject_hint : String,
    /// Hints for command options.
    pub properties_hints : HashMap< String, String >,
    /// Map of aliases.
    pub properties_aliases : HashMap< String, Vec< String > >,
    /// Command routine.
    pub routine : OnCommand,
  }

  impl Command
  {
    /// Execute callback.
    pub fn perform( &self, instruction : &instruction::Instruction ) -> Result<(), Error>
    {
      if self.subject_hint.len() == 0 && instruction.subject.len() != 0
      {
        return Err( Error::new( "Unexpected subject." ) );
      }

      for ( key, _value ) in &instruction.properties_map
      {
        if self.properties_hints.get( key.as_str() ).is_none()
        {
          return Err( Error::new( "Unknown option." ) );
        }
      }
      if self.routine.callable()
      {
        return self.routine.perform( instruction );
      }

      Ok( () )
    }
  }

  ///
  /// Options for command.
  ///

  #[derive( Debug, Clone, Default )]
  pub struct CommandOptions
  {
    ins : Command,
  }

  //

  // ro : null,
  // h : null,
  // lh : null,

  impl CommandOptions
  {
    field_str!{ hint }
    field_str!{ hint, h }
    field_str!{ long_hint }
    field_str!{ long_hint, lh }
    field_str!{ phrase }
    field_str!{ subject_hint }
    field_str!{ subject_hint, sh }
    field_map_str_str!{ properties_hints, property_hint }
    field_map_str_vec_str!{ properties_aliases, property_alias }
    field_routine!{ routine }
    field_routine!{ routine, ro }

    // pub fn hint< Str : AsRef< str > >( &mut self, src : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.hint = src.into();
    //   self
    // }
    // pub fn long_hint< Str : AsRef< str > >( &mut self, src : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.long_hint = src.into();
    //   self
    // }
    // pub fn phrase< Str : AsRef< str > >( &mut self, src : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.phrase = src.into();
    //   self
    // }
    // pub fn subject_hint< Str : AsRef< str > >( &mut self, src : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.subject_hint = src.into();
    //   self
    // }
    // pub fn property_hint< Str : AsRef< str > >( &mut self, property : Str, hint : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   self.ins.properties_hints.insert( property.into(), hint.into() );
    //   self
    // }
    // pub fn property_alias< Str : AsRef< str > >( &mut self, property : Str, alias : Str ) -> &mut Self
    // where
    //   String : From<Str>
    // {
    //   let entry = self.ins.properties_aliases.entry( property.into() ).or_insert_with( || -> Vec< String > { vec![] } );
    //   entry.push( alias.into() );
    //   self
    // }
    //
    // pub fn routine( &mut self, routine : &'static dyn Fn() ) -> &mut Self
    // {
    //   self.ins.routine = routine.into();
    //   self
    // }

    /// Command former.
    pub fn form( &self ) -> Command
    {
      self.ins.clone()
    }

  }

  // impl Options for CommandOptions
  // {
  //   type For = Command;
  // }
}

/// Owned namespace of the module.
pub mod own
{
  use super::internal as i;

  pub use i::OnCommand;
  pub use i::Command;
  pub use i::CommandOptions;
}

pub use own::*;

/// Exposed namespace of the module.
pub mod exposed
{
  use super::internal as i;

  pub use i::OnCommand;
  pub use i::Command;
  pub use i::CommandOptions;
}

/// Namespace of the module to include with `use module::*`.
pub mod prelude
{
  use super::internal as i;

  pub use i::OnCommand;
  pub use i::Command;
  pub use i::CommandOptions;
}

<|endoftext|>


<commit_before><commit_msg>reference pushdown automata in doc comment<commit_after><|endoftext|>


<commit_before>// https://leetcode.com/problems/number-of-wonderful-substrings/
pub fn wonderful_substrings(word: String) -> i64 {
    todo!()
}

fn main() {
    println!("{}", wonderful_substrings(String::from("aba"))); // 4
    println!("{}", wonderful_substrings(String::from("aabb"))); // 9
    println!("{}", wonderful_substrings(String::from("he"))); // 2
    println!("{}", wonderful_substrings(String::from("aabbc"))); // 12
}
<commit_msg>Solve problem 1915<commit_after>// https://leetcode.com/problems/number-of-wonderful-substrings/
pub fn wonderful_substrings(word: String) -> i64 {
    let mut answer = 0;
    let mut counts = vec![0; 1024]; // 1111111111 = 1023
    counts[0] = 1;
    let chars: Vec<char> = word.chars().collect();
    let mut current = 0;
    for c in chars {
        current ^= 1 << c as i32 - 'a' as i32;
        answer += counts[current];
        for j in 0..10 {
            let n = counts[current ^ (1 << j)];
            answer += n;
        }
        counts[current] += 1;
    }
    answer
}

fn main() {
    println!("{}", wonderful_substrings(String::from("aba"))); // 4
    println!("{}", wonderful_substrings(String::from("aabb"))); // 9
    println!("{}", wonderful_substrings(String::from("he"))); // 2
    println!("{}", wonderful_substrings(String::from("aabbc"))); // 12
}
<|endoftext|>