<commit_before>// Copyright (c) 2018, Ben Boeckel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::convert::TryInto;
use std::ffi::CString;
use std::ptr;

use log::error;
use uninit::out_ref::Out;

use crate::{DefaultKeyring, KeyPermissions, KeyringSerial, TimeoutSeconds};

/// Reexport of `Errno` as `Error`.
type Error = errno::Errno;
/// Simpler `Result` type with the error already set.
type Result<T> = std::result::Result<T, Error>;

fn check_syscall(res: libc::c_long) -> Result<libc::c_long> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(res)
    }
}

static THE_KERNEL_LIED: &str = concat!(
    "It appears as though the kernel made a 64-bit key ID. Please report a bug.\n\n",
    env!("CARGO_PKG_REPOSITORY"),
);
static ZERO_KEY_ID_FOUND: &str = concat!(
    "It appears as though a key ID of zero was found. This is novel and should not happen. Please \
     report a bug.\n\n",
    env!("CARGO_PKG_REPOSITORY"),
);
static BUFFER_OVERFLOW: &str = concat!(
    "The kernel returned a size that could not be represented as a `usize`. This should not be \
     possible. Please report a bug.\n\n",
    env!("CARGO_PKG_REPOSITORY"),
);

fn cstring(s: &str) -> CString {
    CString::new(s.as_bytes()).unwrap()
}

fn opt_cstring(opt: Option<&str>) -> Option<CString> {
    opt.map(cstring)
}

fn opt_cstring_ptr(opt: &Option<CString>) -> *const libc::c_char {
    opt.as_ref().map_or(ptr::null(), |cs| cs.as_ptr())
}

fn opt_key_serial(opt: Option<KeyringSerial>) -> i32 {
    opt.map(KeyringSerial::get).unwrap_or(0)
}

fn keyring_serial(res: libc::c_long) -> KeyringSerial {
    KeyringSerial::new(res.try_into().expect(THE_KERNEL_LIED)).expect(ZERO_KEY_ID_FOUND)
}

fn default_keyring(res: libc::c_long) -> Result<DefaultKeyring> {
    res.try_into().map_err(|err: crate::UnknownDefault| {
        error!(
            concat!(
                "The kernel has returned an unexpected default keyring ID: {}. Please report a \
                 bug.\n\n",
                env!("CARGO_PKG_REPOSITORY"),
            ),
            err.0,
        );
        errno::Errno(libc::EINVAL)
    })
}

fn size(res: libc::c_long) -> usize {
    res.try_into().expect(BUFFER_OVERFLOW)
}

fn ignore(res: libc::c_long) {
    assert_eq!(res, 0);
}

macro_rules! syscall {
    ( $( $arg:expr, )* ) => {
        check_syscall(libc::syscall($( $arg, )*))
    };
}

macro_rules! keyctl {
    ( $( $arg:expr, )* ) => {
        syscall!(libc::SYS_keyctl, $( $arg, )*)
    };
}

pub fn add_key(
    type_: &str,
    description: &str,
    payload: &[u8],
    keyring: KeyringSerial,
) -> Result<KeyringSerial> {
    let type_cstr = cstring(type_);
    let desc_cstr = cstring(description);
    unsafe {
        syscall!(
            libc::SYS_add_key,
            type_cstr.as_ptr(),
            desc_cstr.as_ptr(),
            payload.as_ptr() as *const libc::c_void,
            payload.len(),
            keyring.get(),
        )
    }
    .map(keyring_serial)
}

pub fn request_key(
    type_: &str,
    description: &str,
    callout_info: Option<&str>,
    keyring: Option<KeyringSerial>,
) -> Result<KeyringSerial> {
    let type_cstr = cstring(type_);
    let desc_cstr = cstring(description);
    let callout_cstr = opt_cstring(callout_info);
    let callout_ptr = opt_cstring_ptr(&callout_cstr);

    unsafe {
        syscall!(
            libc::SYS_request_key,
            type_cstr.as_ptr(),
            desc_cstr.as_ptr(),
            callout_ptr,
            opt_key_serial(keyring),
        )
    }
    .map(keyring_serial)
}

pub fn keyctl_get_keyring_id(id: KeyringSerial, create: bool) -> Result<KeyringSerial> {
    unsafe {
        keyctl!(
            libc::KEYCTL_GET_KEYRING_ID,
            id.get(),
            if create { 1 } else { 0 },
        )
    }
    .map(keyring_serial)
}

pub fn keyctl_join_session_keyring(name: Option<&str>) -> Result<KeyringSerial> {
    let name_cstr = opt_cstring(name);
    let name_ptr = opt_cstring_ptr(&name_cstr);

    unsafe { keyctl!(libc::KEYCTL_JOIN_SESSION_KEYRING, name_ptr,) }.map(keyring_serial)
}

pub fn keyctl_update(id: KeyringSerial, payload: &[u8]) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_UPDATE,
            id.get(),
            payload.as_ptr() as *const libc::c_void,
            payload.len(),
        )
    }
    .map(ignore)
}

pub fn keyctl_revoke(id: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_REVOKE, id.get(),) }.map(ignore)
}

pub fn keyctl_chown(
    id: KeyringSerial,
    uid: Option<libc::uid_t>,
    gid: Option<libc::gid_t>,
) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_CHOWN,
            id.get(),
            uid.unwrap_or(!0),
            gid.unwrap_or(!0),
        )
    }
    .map(ignore)
}

pub fn keyctl_setperm(id: KeyringSerial, perm: KeyPermissions) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_SETPERM, id.get(), perm,) }.map(ignore)
}

pub fn keyctl_describe(id: KeyringSerial, mut buffer: Option<Out<[u8]>>) -> Result<usize> {
    unsafe {
        let capacity = buffer.as_mut().map_or(0, |b| b.len());
        keyctl!(
            libc::KEYCTL_DESCRIBE,
            id.get(),
            buffer.as_mut().map_or(ptr::null(), |b| b.as_mut_ptr()),
            capacity,
        )
    }
    .map(size)
}

pub fn keyctl_clear(id: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_CLEAR, id.get(),) }.map(ignore)
}

pub fn keyctl_link(id: KeyringSerial, ringid: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_LINK, id.get(), ringid.get(),) }.map(ignore)
}

pub fn keyctl_unlink(id: KeyringSerial, ringid: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_UNLINK, id.get(), ringid.get(),) }.map(ignore)
}

pub fn keyctl_search(
    ringid: KeyringSerial,
    type_: &str,
    description: &str,
    destringid: Option<KeyringSerial>,
) -> Result<KeyringSerial> {
    let type_cstr = cstring(type_);
    let desc_cstr = cstring(description);
    unsafe {
        keyctl!(
            libc::KEYCTL_SEARCH,
            ringid.get(),
            type_cstr.as_ptr(),
            desc_cstr.as_ptr(),
            opt_key_serial(destringid),
        )
    }
    .map(keyring_serial)
}

pub fn keyctl_read(id: KeyringSerial, mut buffer: Option<Out<[u8]>>) -> Result<usize> {
    unsafe {
        let capacity = buffer.as_mut().map_or(0, |b| b.len());
        keyctl!(
            libc::KEYCTL_READ,
            id.get(),
            buffer.as_mut().map_or(ptr::null(), |b| b.as_mut_ptr()),
            capacity,
        )
    }
    .map(size)
}

pub fn keyctl_instantiate(
    id: KeyringSerial,
    payload: &[u8],
    ringid: Option<KeyringSerial>,
) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_INSTANTIATE,
            id.get(),
            payload.as_ptr() as *const libc::c_void,
            payload.len(),
            opt_key_serial(ringid),
        )
    }
    .map(ignore)
}

pub fn keyctl_negate(
    id: KeyringSerial,
    timeout: TimeoutSeconds,
    ringid: Option<KeyringSerial>,
) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_NEGATE,
            id.get(),
            timeout,
            opt_key_serial(ringid),
        )
    }
    .map(ignore)
}

pub fn keyctl_set_reqkey_keyring(reqkey_defl: DefaultKeyring) -> Result<DefaultKeyring> {
    unsafe { keyctl!(libc::KEYCTL_SET_REQKEY_KEYRING, reqkey_defl,) }.and_then(default_keyring)
}

pub fn keyctl_set_timeout(key: KeyringSerial, timeout: TimeoutSeconds) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_SET_TIMEOUT, key.get(), timeout,) }.map(ignore)
}

pub fn keyctl_assume_authority(key: Option<KeyringSerial>) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_ASSUME_AUTHORITY, opt_key_serial(key),) }.map(ignore)
}

pub fn keyctl_get_security(key: KeyringSerial, mut buffer: Option<Out<[u8]>>) -> Result<usize> {
    unsafe {
        let capacity = buffer.as_mut().map_or(0, |b| b.len());
        keyctl!(
            libc::KEYCTL_GET_SECURITY,
            key.get(),
            buffer.as_mut().map_or(ptr::null(), |b| b.as_mut_ptr()),
            capacity,
        )
    }
    .map(size)
}

pub fn keyctl_reject(
    id: KeyringSerial,
    timeout: TimeoutSeconds,
    error: errno::Errno,
    ringid: Option<KeyringSerial>,
) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_REJECT,
            id.get(),
            timeout,
            error,
            opt_key_serial(ringid),
        )
    }
    .map(ignore)
}

pub fn keyctl_invalidate(id: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_INVALIDATE, id.get(),) }.map(ignore)
}

pub fn keyctl_get_persistent(uid: libc::uid_t, id: KeyringSerial) -> Result<KeyringSerial> {
    unsafe { keyctl!(libc::KEYCTL_GET_PERSISTENT, uid, id.get(),) }.map(keyring_serial)
}

pub fn keyctl_session_to_parent() -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_SESSION_TO_PARENT,) }.map(ignore)
}

pub fn keyctl_dh_compute(
    private: KeyringSerial,
    prime: KeyringSerial,
    base: KeyringSerial,
    mut buffer: Option<Out<[u8]>>,
) -> Result<usize> {
    unsafe {
        let capacity = buffer.as_mut().map_or(0, |b| b.len());
        keyctl!(
            libc::KEYCTL_DH_COMPUTE,
            private.get(),
            prime.get(),
            base.get(),
            buffer.as_mut().map_or(ptr::null(), |b| b.as_mut_ptr()),
            capacity,
        )
    }
    .map(size)
}

pub enum Restriction<'a> {
    AllLinks,
    ByType {
        type_: &'a str,
        restriction: &'a str,
    },
}

pub fn keyctl_restrict_keyring(keyring: KeyringSerial, restriction: Restriction) -> Result<()> {
    let type_cstr;
    let restriction_cstr;

    let (type_ptr, restriction_ptr) = match restriction {
        Restriction::AllLinks => (ptr::null(), ptr::null()),
        Restriction::ByType {
            type_,
            restriction,
        } => {
            type_cstr = cstring(type_);
            restriction_cstr = cstring(restriction);

            (type_cstr.as_ptr(), restriction_cstr.as_ptr())
        },
    };
    unsafe {
        keyctl!(
            libc::KEYCTL_RESTRICT_KEYRING,
            keyring.get(),
            type_ptr,
            restriction_ptr,
        )
    }
    .map(ignore)
}
<commit_msg>keyutils-raw: move capacity computation outside the unsafe block<commit_after>// Copyright (c) 2018, Ben Boeckel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::convert::TryInto;
use std::ffi::CString;
use std::ptr;

use log::error;
use uninit::out_ref::Out;

use crate::{DefaultKeyring, KeyPermissions, KeyringSerial, TimeoutSeconds};

/// Reexport of `Errno` as `Error`.
type Error = errno::Errno;
/// Simpler `Result` type with the error already set.
type Result<T> = std::result::Result<T, Error>;

fn check_syscall(res: libc::c_long) -> Result<libc::c_long> {
    if res == -1 {
        Err(errno::errno())
    } else {
        Ok(res)
    }
}

static THE_KERNEL_LIED: &str = concat!(
    "It appears as though the kernel made a 64-bit key ID. Please report a bug.\n\n",
    env!("CARGO_PKG_REPOSITORY"),
);
static ZERO_KEY_ID_FOUND: &str = concat!(
    "It appears as though a key ID of zero was found. This is novel and should not happen. Please \
     report a bug.\n\n",
    env!("CARGO_PKG_REPOSITORY"),
);
static BUFFER_OVERFLOW: &str = concat!(
    "The kernel returned a size that could not be represented as a `usize`. This should not be \
     possible. Please report a bug.\n\n",
    env!("CARGO_PKG_REPOSITORY"),
);

fn cstring(s: &str) -> CString {
    CString::new(s.as_bytes()).unwrap()
}

fn opt_cstring(opt: Option<&str>) -> Option<CString> {
    opt.map(cstring)
}

fn opt_cstring_ptr(opt: &Option<CString>) -> *const libc::c_char {
    opt.as_ref().map_or(ptr::null(), |cs| cs.as_ptr())
}

fn opt_key_serial(opt: Option<KeyringSerial>) -> i32 {
    opt.map(KeyringSerial::get).unwrap_or(0)
}

fn keyring_serial(res: libc::c_long) -> KeyringSerial {
    KeyringSerial::new(res.try_into().expect(THE_KERNEL_LIED)).expect(ZERO_KEY_ID_FOUND)
}

fn default_keyring(res: libc::c_long) -> Result<DefaultKeyring> {
    res.try_into().map_err(|err: crate::UnknownDefault| {
        error!(
            concat!(
                "The kernel has returned an unexpected default keyring ID: {}. Please report a \
                 bug.\n\n",
                env!("CARGO_PKG_REPOSITORY"),
            ),
            err.0,
        );
        errno::Errno(libc::EINVAL)
    })
}

fn size(res: libc::c_long) -> usize {
    res.try_into().expect(BUFFER_OVERFLOW)
}

fn ignore(res: libc::c_long) {
    assert_eq!(res, 0);
}

macro_rules! syscall {
    ( $( $arg:expr, )* ) => {
        check_syscall(libc::syscall($( $arg, )*))
    };
}

macro_rules! keyctl {
    ( $( $arg:expr, )* ) => {
        syscall!(libc::SYS_keyctl, $( $arg, )*)
    };
}

pub fn add_key(
    type_: &str,
    description: &str,
    payload: &[u8],
    keyring: KeyringSerial,
) -> Result<KeyringSerial> {
    let type_cstr = cstring(type_);
    let desc_cstr = cstring(description);
    unsafe {
        syscall!(
            libc::SYS_add_key,
            type_cstr.as_ptr(),
            desc_cstr.as_ptr(),
            payload.as_ptr() as *const libc::c_void,
            payload.len(),
            keyring.get(),
        )
    }
    .map(keyring_serial)
}

pub fn request_key(
    type_: &str,
    description: &str,
    callout_info: Option<&str>,
    keyring: Option<KeyringSerial>,
) -> Result<KeyringSerial> {
    let type_cstr = cstring(type_);
    let desc_cstr = cstring(description);
    let callout_cstr = opt_cstring(callout_info);
    let callout_ptr = opt_cstring_ptr(&callout_cstr);

    unsafe {
        syscall!(
            libc::SYS_request_key,
            type_cstr.as_ptr(),
            desc_cstr.as_ptr(),
            callout_ptr,
            opt_key_serial(keyring),
        )
    }
    .map(keyring_serial)
}

pub fn keyctl_get_keyring_id(id: KeyringSerial, create: bool) -> Result<KeyringSerial> {
    unsafe {
        keyctl!(
            libc::KEYCTL_GET_KEYRING_ID,
            id.get(),
            if create { 1 } else { 0 },
        )
    }
    .map(keyring_serial)
}

pub fn keyctl_join_session_keyring(name: Option<&str>) -> Result<KeyringSerial> {
    let name_cstr = opt_cstring(name);
    let name_ptr = opt_cstring_ptr(&name_cstr);

    unsafe { keyctl!(libc::KEYCTL_JOIN_SESSION_KEYRING, name_ptr,) }.map(keyring_serial)
}

pub fn keyctl_update(id: KeyringSerial, payload: &[u8]) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_UPDATE,
            id.get(),
            payload.as_ptr() as *const libc::c_void,
            payload.len(),
        )
    }
    .map(ignore)
}

pub fn keyctl_revoke(id: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_REVOKE, id.get(),) }.map(ignore)
}

pub fn keyctl_chown(
    id: KeyringSerial,
    uid: Option<libc::uid_t>,
    gid: Option<libc::gid_t>,
) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_CHOWN,
            id.get(),
            uid.unwrap_or(!0),
            gid.unwrap_or(!0),
        )
    }
    .map(ignore)
}

pub fn keyctl_setperm(id: KeyringSerial, perm: KeyPermissions) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_SETPERM, id.get(), perm,) }.map(ignore)
}

pub fn keyctl_describe(id: KeyringSerial, mut buffer: Option<Out<[u8]>>) -> Result<usize> {
    let capacity = buffer.as_mut().map_or(0, |b| b.len());
    unsafe {
        keyctl!(
            libc::KEYCTL_DESCRIBE,
            id.get(),
            buffer.as_mut().map_or(ptr::null(), |b| b.as_mut_ptr()),
            capacity,
        )
    }
    .map(size)
}

pub fn keyctl_clear(id: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_CLEAR, id.get(),) }.map(ignore)
}

pub fn keyctl_link(id: KeyringSerial, ringid: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_LINK, id.get(), ringid.get(),) }.map(ignore)
}

pub fn keyctl_unlink(id: KeyringSerial, ringid: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_UNLINK, id.get(), ringid.get(),) }.map(ignore)
}

pub fn keyctl_search(
    ringid: KeyringSerial,
    type_: &str,
    description: &str,
    destringid: Option<KeyringSerial>,
) -> Result<KeyringSerial> {
    let type_cstr = cstring(type_);
    let desc_cstr = cstring(description);
    unsafe {
        keyctl!(
            libc::KEYCTL_SEARCH,
            ringid.get(),
            type_cstr.as_ptr(),
            desc_cstr.as_ptr(),
            opt_key_serial(destringid),
        )
    }
    .map(keyring_serial)
}

pub fn keyctl_read(id: KeyringSerial, mut buffer: Option<Out<[u8]>>) -> Result<usize> {
    let capacity = buffer.as_mut().map_or(0, |b| b.len());
    unsafe {
        keyctl!(
            libc::KEYCTL_READ,
            id.get(),
            buffer.as_mut().map_or(ptr::null(), |b| b.as_mut_ptr()),
            capacity,
        )
    }
    .map(size)
}

pub fn keyctl_instantiate(
    id: KeyringSerial,
    payload: &[u8],
    ringid: Option<KeyringSerial>,
) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_INSTANTIATE,
            id.get(),
            payload.as_ptr() as *const libc::c_void,
            payload.len(),
            opt_key_serial(ringid),
        )
    }
    .map(ignore)
}

pub fn keyctl_negate(
    id: KeyringSerial,
    timeout: TimeoutSeconds,
    ringid: Option<KeyringSerial>,
) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_NEGATE,
            id.get(),
            timeout,
            opt_key_serial(ringid),
        )
    }
    .map(ignore)
}

pub fn keyctl_set_reqkey_keyring(reqkey_defl: DefaultKeyring) -> Result<DefaultKeyring> {
    unsafe { keyctl!(libc::KEYCTL_SET_REQKEY_KEYRING, reqkey_defl,) }.and_then(default_keyring)
}

pub fn keyctl_set_timeout(key: KeyringSerial, timeout: TimeoutSeconds) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_SET_TIMEOUT, key.get(), timeout,) }.map(ignore)
}

pub fn keyctl_assume_authority(key: Option<KeyringSerial>) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_ASSUME_AUTHORITY, opt_key_serial(key),) }.map(ignore)
}

pub fn keyctl_get_security(key: KeyringSerial, mut buffer: Option<Out<[u8]>>) -> Result<usize> {
    let capacity = buffer.as_mut().map_or(0, |b| b.len());
    unsafe {
        keyctl!(
            libc::KEYCTL_GET_SECURITY,
            key.get(),
            buffer.as_mut().map_or(ptr::null(), |b| b.as_mut_ptr()),
            capacity,
        )
    }
    .map(size)
}

pub fn keyctl_reject(
    id: KeyringSerial,
    timeout: TimeoutSeconds,
    error: errno::Errno,
    ringid: Option<KeyringSerial>,
) -> Result<()> {
    unsafe {
        keyctl!(
            libc::KEYCTL_REJECT,
            id.get(),
            timeout,
            error,
            opt_key_serial(ringid),
        )
    }
    .map(ignore)
}

pub fn keyctl_invalidate(id: KeyringSerial) -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_INVALIDATE, id.get(),) }.map(ignore)
}

pub fn keyctl_get_persistent(uid: libc::uid_t, id: KeyringSerial) -> Result<KeyringSerial> {
    unsafe { keyctl!(libc::KEYCTL_GET_PERSISTENT, uid, id.get(),) }.map(keyring_serial)
}

pub fn keyctl_session_to_parent() -> Result<()> {
    unsafe { keyctl!(libc::KEYCTL_SESSION_TO_PARENT,) }.map(ignore)
}

pub fn keyctl_dh_compute(
    private: KeyringSerial,
    prime: KeyringSerial,
    base: KeyringSerial,
    mut buffer: Option<Out<[u8]>>,
) -> Result<usize> {
    let capacity = buffer.as_mut().map_or(0, |b| b.len());
    unsafe {
        keyctl!(
            libc::KEYCTL_DH_COMPUTE,
            private.get(),
            prime.get(),
            base.get(),
            buffer.as_mut().map_or(ptr::null(), |b| b.as_mut_ptr()),
            capacity,
        )
    }
    .map(size)
}

pub enum Restriction<'a> {
    AllLinks,
    ByType {
        type_: &'a str,
        restriction: &'a str,
    },
}

pub fn keyctl_restrict_keyring(keyring: KeyringSerial, restriction: Restriction) -> Result<()> {
    let type_cstr;
    let restriction_cstr;

    let (type_ptr, restriction_ptr) = match restriction {
        Restriction::AllLinks => (ptr::null(), ptr::null()),
        Restriction::ByType {
            type_,
            restriction,
        } => {
            type_cstr = cstring(type_);
            restriction_cstr = cstring(restriction);

            (type_cstr.as_ptr(), restriction_cstr.as_ptr())
        },
    };
    unsafe {
        keyctl!(
            libc::KEYCTL_RESTRICT_KEYRING,
            keyring.get(),
            type_ptr,
            restriction_ptr,
        )
    }
    .map(ignore)
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

use std::fmt::{Error, Debug};

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Copy)]
pub enum Status {
    StatusSuccess = 0,

    StatusNoMemory,
    StatusInvalidRestore,
    StatusInvalidPopGroup,
    StatusNoCurrentPoint,
    StatusInvalidMatrix,
    StatusInvalidStatus,
    StatusNullPointer,
    StatusInvalidString,
    StatusInvalidPathData,
    StatusReadError,
    StatusWriteError,
    StatusSurfaceFinished,
    StatusSurfaceTypeMismatch,
    StatusPatternTypeMismatch,
    StatusInvalidContent,
    StatusInvalidFormat,
    StatusInvalidVisual,
    StatusFileNotFound,
    StatusInvalidDash,
    StatusInvalidDscComment,
    StatusInvalidIndex,
    StatusClipNotRepresentable,
    StatusTempFileError,
    StatusInvalidStride,
    StatusFontTypeMismatch,
    StatusUserFontImmutable,
    StatusUserFontError,
    StatusNegativeCount,
    StatusInvalidClusters,
    StatusInvalidSlant,
    StatusInvalidWeight,
    StatusInvalidSize,
    StatusUserFontNotImplemented,
    StatusDeviceTypeMismatch,
    StatusDeviceError,
    StatusInvalidMeshConstruction,
    StatusDeviceFinished,

    StatusLastStatus
}

impl Debug for Status {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), Error> {
        unsafe {
            let char_ptr = super::cairo_status_to_string(*self);
            let tmp = String::from_utf8_lossy(::std::ffi::c_str_to_bytes(&char_ptr)).to_string();

            tmp.fmt(formatter)
        }
    }
}

impl Status {
    pub fn ensure_valid(&self) {
        if *self != Status::StatusSuccess {
            panic!("Cairo error {:?}", *self)
        }
    }
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Antialias {
    AntialiasDefault,

    /* method */
    AntialiasNone,
    AntialiasGray,
    AntialiasSubpixel,

    /* hints */
    AntialiasFast,
    AntialiasGood,
    AntialiasBest
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum FillRule {
    FillRuleWinding,
    FillRuleEvenOdd
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum LineCap {
    LineCapButt,
    LineCapRound,
    LineCapSquare
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum LineJoin {
    LineJoinMiter,
    LineJoinRound,
    LineJoinBevel
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Operator {
    OperatorClear,

    OperatorSource,
    OperatorOver,
    OperatorIn,
    OperatorOut,
    OperatorAtop,

    OperatorDest,
    OperatorDestOver,
    OperatorDestIn,
    OperatorDestOut,
    OperatorDestAtop,

    OperatorXor,
    OperatorAdd,
    OperatorSaturate,

    OperatorMultiply,
    OperatorScreen,
    OperatorOverlay,
    OperatorDarken,
    OperatorLighten,
    OperatorColorDodge,
    OperatorColorBurn,
    OperatorHardLight,
    OperatorSoftLight,
    OperatorDifference,
    OperatorExclusion,
    OperatorHslHue,
    OperatorHslSaturation,
    OperatorHslColor,
    OperatorHslLuminosity
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum PathDataType {
    PathMoveTo,
    PathLineTo,
    PathCurveTo,
    PathClosePath
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Content {
    ContentColor      = 0x1000,
    ContentAlpha      = 0x2000,
    ContentColorAlpha = 0x3000
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Extend {
    ExtendNone,
    ExtendRepeat,
    ExtendReflect,
    ExtendPad
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Filter {
    FilterFast,
    FilterGood,
    FilterBest,
    FilterNearest,
    FilterBilinear,
    FilterGaussian
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum PatternType {
    PatternTypeSolid,
    PatternTypeSurface,
    PatternTypeLinearGradient,
    PatternTypeRadialGradient,
    PatternTypeMesh,
    PatternTypeRasterSource
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum FontSlant {
    FontSlantNormal,
    FontSlantItalic,
    FontSlantOblique
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum FontWeight {
    FontWeightNormal,
    FontWeightBold
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum TextClusterFlags {
    TextClusterFlagNone     = 0x00000000,
    TextClusterFlagBackward = 0x00000001
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum FontType {
    FontTypeToy,
    FontTypeFt,
    FontTypeWin32,
    FontTypeQuartz,
    FontTypeUser
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum SubpixelOrder {
    SubpixelOrderDefault,
    SubpixelOrderRgb,
    SubpixelOrderBgr,
    SubpixelOrderVrgb,
    SubpixelOrderVbgr
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum HintStyle {
    HintStyleDefault,
    HintStyleNone,
    HintStyleSlight,
    HintStyleMedium,
    HintStyleFull
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum HintMetrics {
    HintMetricsDefault,
    HintMetricsOff,
    HintMetricsOn
}
<commit_msg>Replace deprecated c_str_to_bytes use<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

use std::fmt::{Error, Debug};
use std::ffi::CStr;

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Copy)]
pub enum Status {
    StatusSuccess = 0,

    StatusNoMemory,
    StatusInvalidRestore,
    StatusInvalidPopGroup,
    StatusNoCurrentPoint,
    StatusInvalidMatrix,
    StatusInvalidStatus,
    StatusNullPointer,
    StatusInvalidString,
    StatusInvalidPathData,
    StatusReadError,
    StatusWriteError,
    StatusSurfaceFinished,
    StatusSurfaceTypeMismatch,
    StatusPatternTypeMismatch,
    StatusInvalidContent,
    StatusInvalidFormat,
    StatusInvalidVisual,
    StatusFileNotFound,
    StatusInvalidDash,
    StatusInvalidDscComment,
    StatusInvalidIndex,
    StatusClipNotRepresentable,
    StatusTempFileError,
    StatusInvalidStride,
    StatusFontTypeMismatch,
    StatusUserFontImmutable,
    StatusUserFontError,
    StatusNegativeCount,
    StatusInvalidClusters,
    StatusInvalidSlant,
    StatusInvalidWeight,
    StatusInvalidSize,
    StatusUserFontNotImplemented,
    StatusDeviceTypeMismatch,
    StatusDeviceError,
    StatusInvalidMeshConstruction,
    StatusDeviceFinished,

    StatusLastStatus
}

impl Debug for Status {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), Error> {
        unsafe {
            let char_ptr = super::cairo_status_to_string(*self);
            let tmp = String::from_utf8_lossy(CStr::from_ptr(char_ptr).to_bytes()).into_owned();

            tmp.fmt(formatter)
        }
    }
}

impl Status {
    pub fn ensure_valid(&self) {
        if *self != Status::StatusSuccess {
            panic!("Cairo error {:?}", *self)
        }
    }
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Antialias {
    AntialiasDefault,

    /* method */
    AntialiasNone,
    AntialiasGray,
    AntialiasSubpixel,

    /* hints */
    AntialiasFast,
    AntialiasGood,
    AntialiasBest
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum FillRule {
    FillRuleWinding,
    FillRuleEvenOdd
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum LineCap {
    LineCapButt,
    LineCapRound,
    LineCapSquare
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum LineJoin {
    LineJoinMiter,
    LineJoinRound,
    LineJoinBevel
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Operator {
    OperatorClear,

    OperatorSource,
    OperatorOver,
    OperatorIn,
    OperatorOut,
    OperatorAtop,

    OperatorDest,
    OperatorDestOver,
    OperatorDestIn,
    OperatorDestOut,
    OperatorDestAtop,

    OperatorXor,
    OperatorAdd,
    OperatorSaturate,

    OperatorMultiply,
    OperatorScreen,
    OperatorOverlay,
    OperatorDarken,
    OperatorLighten,
    OperatorColorDodge,
    OperatorColorBurn,
    OperatorHardLight,
    OperatorSoftLight,
    OperatorDifference,
    OperatorExclusion,
    OperatorHslHue,
    OperatorHslSaturation,
    OperatorHslColor,
    OperatorHslLuminosity
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum PathDataType {
    PathMoveTo,
    PathLineTo,
    PathCurveTo,
    PathClosePath
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Content {
    ContentColor      = 0x1000,
    ContentAlpha      = 0x2000,
    ContentColorAlpha = 0x3000
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Extend {
    ExtendNone,
    ExtendRepeat,
    ExtendReflect,
    ExtendPad
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum Filter {
    FilterFast,
    FilterGood,
    FilterBest,
    FilterNearest,
    FilterBilinear,
    FilterGaussian
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum PatternType {
    PatternTypeSolid,
    PatternTypeSurface,
    PatternTypeLinearGradient,
    PatternTypeRadialGradient,
    PatternTypeMesh,
    PatternTypeRasterSource
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum FontSlant {
    FontSlantNormal,
    FontSlantItalic,
    FontSlantOblique
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum FontWeight {
    FontWeightNormal,
    FontWeightBold
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum TextClusterFlags {
    TextClusterFlagNone     = 0x00000000,
    TextClusterFlagBackward = 0x00000001
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum FontType {
    FontTypeToy,
    FontTypeFt,
    FontTypeWin32,
    FontTypeQuartz,
    FontTypeUser
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum SubpixelOrder {
    SubpixelOrderDefault,
    SubpixelOrderRgb,
    SubpixelOrderBgr,
    SubpixelOrderVrgb,
    SubpixelOrderVbgr
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum HintStyle {
    HintStyleDefault,
    HintStyleNone,
    HintStyleSlight,
    HintStyleMedium,
    HintStyleFull
}

#[repr(C)]
#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)]
pub enum HintMetrics {
    HintMetricsDefault,
    HintMetricsOff,
    HintMetricsOn
}
<|endoftext|>


<commit_before>// Take a look at the license at the top of the repository in the LICENSE file.

use std::ffi::CStr;

use core_foundation_sys::array::{CFArrayGetCount, CFArrayGetValueAtIndex};
use core_foundation_sys::base::kCFAllocatorDefault;
use core_foundation_sys::string::{
    kCFStringEncodingUTF8, CFStringCreateWithBytes, CFStringGetCStringPtr,
};

use crate::apple::inner::ffi::{
    kHIDPage_AppleVendor, kHIDUsage_AppleVendor_TemperatureSensor, kIOHIDEventTypeTemperature,
    matching, IOHIDEventFieldBase, IOHIDEventGetFloatValue, IOHIDEventSystemClientCopyServices,
    IOHIDEventSystemClientCreate, IOHIDEventSystemClientSetMatching, IOHIDServiceClientCopyEvent,
    IOHIDServiceClientCopyProperty, __IOHIDEventSystemClient, __IOHIDServiceClient,
    HID_DEVICE_PROPERTY_PRODUCT,
};
use crate::sys::macos::utils::CFReleaser;
use crate::ComponentExt;

pub(crate) struct Components {
    pub inner: Vec<Component>,
    client: Option<CFReleaser<__IOHIDEventSystemClient>>,
}

impl Components {
    pub(crate) fn new() -> Self {
        Self {
            inner: vec![],
            client: None,
        }
    }

    pub(crate) fn refresh(&mut self) {
        self.inner.clear();

        unsafe {
            let matches = match CFReleaser::new(matching(
                kHIDPage_AppleVendor,
                kHIDUsage_AppleVendor_TemperatureSensor,
            )) {
                Some(m) => m,
                None => return,
            };

            // FIXME: Do we really need to re-create a new `client` every time?
            let client = match CFReleaser::new(IOHIDEventSystemClientCreate(kCFAllocatorDefault)) {
                Some(c) => c,
                None => return,
            };

            let _ = IOHIDEventSystemClientSetMatching(client.inner(), matches.inner());

            let services = match CFReleaser::new(IOHIDEventSystemClientCopyServices(client.inner()))
            {
                Some(s) => s,
                None => return,
            };

            let key_ref = match CFReleaser::new(CFStringCreateWithBytes(
                kCFAllocatorDefault,
                HID_DEVICE_PROPERTY_PRODUCT.as_ptr(),
                HID_DEVICE_PROPERTY_PRODUCT.len() as _,
                kCFStringEncodingUTF8,
                false as _,
            )) {
                Some(r) => r,
                None => return,
            };

            let count = CFArrayGetCount(services.inner());

            for i in 0..count {
                let service = match CFReleaser::new(
                    CFArrayGetValueAtIndex(services.inner(), i) as *const _
                ) {
                    Some(s) => s,
                    None => continue,
                };

                let name = match CFReleaser::new(IOHIDServiceClientCopyProperty(
                    service.inner(),
                    key_ref.inner(),
                )) {
                    Some(n) => n,
                    None => continue,
                };

                let name_ptr =
                    CFStringGetCStringPtr(name.inner() as *const _, kCFStringEncodingUTF8);
                let name_str = CStr::from_ptr(name_ptr).to_string_lossy().to_string();

                let mut component = Component::new(name_str, None, None, service);
                component.refresh();

                self.inner.push(component);
            }

            // FIXME: Do we really need to re-create a new `client` every time?
            self.client.replace(client);
        }
    }
}

unsafe impl Send for Components {}
unsafe impl Sync for Components {}

#[doc = include_str!("../../../../md_doc/component.md")]
pub struct Component {
    service: CFReleaser<__IOHIDServiceClient>,
    temperature: f32,
    label: String,
    max: f32,
    critical: Option<f32>,
}

impl Component {
    pub(crate) fn new(
        label: String,
        max: Option<f32>,
        critical: Option<f32>,
        service: CFReleaser<__IOHIDServiceClient>,
    ) -> Self {
        Self {
            service,
            label,
            max: max.unwrap_or(0.),
            critical,
            temperature: 0.,
        }
    }
}

unsafe impl Send for Component {}
unsafe impl Sync for Component {}

impl ComponentExt for Component {
    fn temperature(&self) -> f32 {
        self.temperature
    }

    fn max(&self) -> f32 {
        self.max
    }

    fn critical(&self) -> Option<f32> {
        self.critical
    }

    fn label(&self) -> &str {
        &self.label
    }

    fn refresh(&mut self) {
        unsafe {
            let event = match CFReleaser::new(IOHIDServiceClientCopyEvent(
                self.service.inner() as *const _,
                kIOHIDEventTypeTemperature,
                0,
                0,
            )) {
                Some(e) => e,
                None => return,
            };

            self.temperature = IOHIDEventGetFloatValue(
                event.inner(),
                IOHIDEventFieldBase(kIOHIDEventTypeTemperature),
            ) as _;
            if self.temperature > self.max {
                self.max = self.temperature;
            }
        }
    }
}
<commit_msg>fix segfault on m1<commit_after>// Take a look at the license at the top of the repository in the LICENSE file.

use std::ffi::CStr;

use core_foundation_sys::array::{CFArrayGetCount, CFArrayGetValueAtIndex};
use core_foundation_sys::base::{kCFAllocatorDefault, CFRetain};
use core_foundation_sys::string::{
    kCFStringEncodingUTF8, CFStringCreateWithBytes, CFStringGetCStringPtr,
};

use crate::apple::inner::ffi::{
    kHIDPage_AppleVendor, kHIDUsage_AppleVendor_TemperatureSensor, kIOHIDEventTypeTemperature,
    matching, IOHIDEventFieldBase, IOHIDEventGetFloatValue, IOHIDEventSystemClientCopyServices,
    IOHIDEventSystemClientCreate, IOHIDEventSystemClientSetMatching, IOHIDServiceClientCopyEvent,
    IOHIDServiceClientCopyProperty, __IOHIDEventSystemClient, __IOHIDServiceClient,
    HID_DEVICE_PROPERTY_PRODUCT,
};
use crate::sys::macos::utils::CFReleaser;
use crate::ComponentExt;

pub(crate) struct Components {
    pub inner: Vec<Component>,
    client: Option<CFReleaser<__IOHIDEventSystemClient>>,
}

impl Components {
    pub(crate) fn new() -> Self {
        Self {
            inner: vec![],
            client: None,
        }
    }

    pub(crate) fn refresh(&mut self) {
        self.inner.clear();

        unsafe {
            let matches = match CFReleaser::new(matching(
                kHIDPage_AppleVendor,
                kHIDUsage_AppleVendor_TemperatureSensor,
            )) {
                Some(m) => m,
                None => return,
            };

            if self.client.is_none() {
                let client =
                    match CFReleaser::new(IOHIDEventSystemClientCreate(kCFAllocatorDefault)) {
                        Some(c) => c,
                        None => return,
                    };
                // Without this call, client is freed during the execution of the program. It must be kept!
                CFRetain(client.inner() as _);
                self.client = Some(client);
            }

            let client = self.client.as_ref().unwrap();

            let _ = IOHIDEventSystemClientSetMatching(client.inner(), matches.inner());

            let services = match CFReleaser::new(IOHIDEventSystemClientCopyServices(client.inner()))
            {
                Some(s) => s,
                None => return,
            };

            let key_ref = match CFReleaser::new(CFStringCreateWithBytes(
                kCFAllocatorDefault,
                HID_DEVICE_PROPERTY_PRODUCT.as_ptr(),
                HID_DEVICE_PROPERTY_PRODUCT.len() as _,
                kCFStringEncodingUTF8,
                false as _,
            )) {
                Some(r) => r,
                None => return,
            };

            let count = CFArrayGetCount(services.inner());

            for i in 0..count {
                let service = match CFReleaser::new(
                    CFArrayGetValueAtIndex(services.inner(), i) as *const _
                ) {
                    Some(s) => s,
                    None => continue,
                };

                let name = match CFReleaser::new(IOHIDServiceClientCopyProperty(
                    service.inner(),
                    key_ref.inner(),
                )) {
                    Some(n) => n,
                    None => continue,
                };

                let name_ptr =
                    CFStringGetCStringPtr(name.inner() as *const _, kCFStringEncodingUTF8);
                let name_str = CStr::from_ptr(name_ptr).to_string_lossy().to_string();

                let mut component = Component::new(name_str, None, None, service);
                component.refresh();

                self.inner.push(component);
            }
        }
    }
}

unsafe impl Send for Components {}
unsafe impl Sync for Components {}

#[doc = include_str!("../../../../md_doc/component.md")]
pub struct Component {
    service: CFReleaser<__IOHIDServiceClient>,
    temperature: f32,
    label: String,
    max: f32,
    critical: Option<f32>,
}

impl Component {
    pub(crate) fn new(
        label: String,
        max: Option<f32>,
        critical: Option<f32>,
        service: CFReleaser<__IOHIDServiceClient>,
    ) -> Self {
        Self {
            service,
            label,
            max: max.unwrap_or(0.),
            critical,
            temperature: 0.,
        }
    }
}

unsafe impl Send for Component {}
unsafe impl Sync for Component {}

impl ComponentExt for Component {
    fn temperature(&self) -> f32 {
        self.temperature
    }

    fn max(&self) -> f32 {
        self.max
    }

    fn critical(&self) -> Option<f32> {
        self.critical
    }

    fn label(&self) -> &str {
        &self.label
    }

    fn refresh(&mut self) {
        unsafe {
            let event = match CFReleaser::new(IOHIDServiceClientCopyEvent(
                self.service.inner() as *const _,
                kIOHIDEventTypeTemperature,
                0,
                0,
            )) {
                Some(e) => e,
                None => return,
            };

            self.temperature = IOHIDEventGetFloatValue(
                event.inner(),
                IOHIDEventFieldBase(kIOHIDEventTypeTemperature),
            ) as _;
            if self.temperature > self.max {
                self.max = self.temperature;
            }
        }
    }
}
<|endoftext|>


<commit_before>// This powerful wrapper provides the ability to store a positive integer value.
// Rewrite it using generics so that it supports wrapping ANY type.

// I AM NOT DONE
struct Wrapper<u32> {
    value: u32
}

impl<u32> Wrapper<u32> {
    pub fn new(value: u32) -> Self {
        Wrapper { value }
    }
}

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

    #[test]
    fn store_u32_in_wrapper() {
        assert_eq!(Wrapper::new(42).value,  42);
    }

    #[test]
    fn store_str_in_wrapper() {
        // TODO: Delete this assert and uncomment the one  below once you have  finished the exercise.
        assert!(false);
        // assert_eq!(Wrapper::new("Foo").value, "Foo");
    }
}<commit_msg>fix: update generics2       closes #362<commit_after>// This powerful wrapper provides the ability to store a positive integer value.
// Rewrite it using generics so that it supports wrapping ANY type.

// I AM NOT DONE
struct Wrapper {
    value: u32
}

impl Wrapper {
    pub fn new(value: u32) -> Self {
        Wrapper { value }
    }
}

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

    #[test]
    fn store_u32_in_wrapper() {
        assert_eq!(Wrapper::new(42).value,  42);
    }

    #[test]
    fn store_str_in_wrapper() {
        assert_eq!(Wrapper::new("Foo").value, "Foo");
    }
}<|endoftext|>


<commit_before>//! Implements support for the LM4F120 UARTs

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use core::intrinsics::{volatile_store, volatile_load};
use core::ptr::Unique;
use super::registers;
use super::gpio;
use super::pll;

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

/// This chip has 8 UARTs
#[derive(PartialEq, Clone, Copy)]
pub enum UartId {
    Uart0,
    Uart1,
    Uart2,
    Uart3,
    Uart4,
    Uart5,
    Uart6,
    Uart7,
}

/// Controls a single UART
/// Only supports 8/N/1 - who needs anything else?
pub struct Uart {
    id: UartId,
    baud: u32,
    nl_mode: NewlineMode,
    reg: Unique<registers::UartRegisters>,
}

/// writeln!() emits LF chars, so this is useful
/// if you're writing text with your UART
#[derive(PartialEq, Clone, Copy)]
pub enum NewlineMode {
    Binary,
    SwapLFtoCRLF,
}

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

impl Uart {
    pub fn new(id: UartId, baud: u32, nl_mode: NewlineMode) -> Uart {
        let mut uart = Uart {
            id: id,
            baud: baud,
            nl_mode: nl_mode,
            reg: get_uart_registers(id),
        };
        uart.init();
        uart
    }

    fn init(&mut self) -> () {
        // Do GPIO pin muxing
        gpio::enable_uart(self.id);
        // Enable UART module in RCGUART register p306
        unsafe {
            self.enable_uart();
            let uart_reg = self.reg.get_mut();

            // Disable UART and all features
            uart_reg.ctl = 0;
            // Calculate the baud rate values
            // baud_div = CLOCK_RATE / (16 * baud_rate);
            // baud_int = round(baud_div * 64)
            let baud_int: u32 = (((pll::get_clock_hz() * 8) / self.baud) + 1) / 2;
            // Store the upper and lower parts of the divider
            uart_reg.ibrd = (baud_int / 64) as usize;
            uart_reg.fbrd = (baud_int % 64) as usize;
            // Calculate the UART Line Control register value
            // 8N1
            uart_reg.lcrh = registers::UART_LCRH_WLEN_8;
            // Clear the flags
            uart_reg.rf = 0;
            // Enable
            uart_reg.ctl = registers::UART_CTL_RXE | registers::UART_CTL_TXE |
                           registers::UART_CTL_UARTEN;
        }
    }

    unsafe fn enable_uart(&mut self) {
        let mut reg: usize = volatile_load(registers::SYSCTL_RCGCUART_R);
        reg |= match self.id {
            UartId::Uart0 => 1 << 0,
            UartId::Uart1 => 1 << 1,
            UartId::Uart2 => 1 << 2,
            UartId::Uart3 => 1 << 3,
            UartId::Uart4 => 1 << 4,
            UartId::Uart5 => 1 << 5,
            UartId::Uart6 => 1 << 6,
            UartId::Uart7 => 1 << 7,
        };
        volatile_store(registers::SYSCTL_RCGCUART_R, reg);
    }

    fn putc(&mut self, value: u8) {
        unsafe {
            let uart_reg = self.reg.get_mut();
            while (uart_reg.rf & registers::UART_FR_TXFF) != 0 {
                asm!("NOP");
            }
            uart_reg.data = value as usize;
        }
    }
}

impl ::core::fmt::Write for Uart {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        match self.nl_mode {
            NewlineMode::Binary => {
                for byte in s.bytes() {
                    self.putc(byte)
                }
            }
            NewlineMode::SwapLFtoCRLF => {
                for byte in s.bytes() {
                    if byte == 0x0A {
                        // Prefix every \n with a \r
                        self.putc(0x0D)
                    }
                    self.putc(byte)
                }
            }
        }
        Ok(())
    }
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

/// Get a Unique<> wrapped pointer to the UART control registers in the chip.
/// We use the Unique<> wrapper to make it easier to store the pointer in our
/// object.
fn get_uart_registers(uart: UartId) -> Unique<registers::UartRegisters> {
    match uart {
        UartId::Uart0 => unsafe { Unique::new(registers::UART0_DR_R as *mut _) },
        UartId::Uart1 => unsafe { Unique::new(registers::UART1_DR_R as *mut _) },
        UartId::Uart2 => unsafe { Unique::new(registers::UART2_DR_R as *mut _) },
        UartId::Uart3 => unsafe { Unique::new(registers::UART3_DR_R as *mut _) },
        UartId::Uart4 => unsafe { Unique::new(registers::UART4_DR_R as *mut _) },
        UartId::Uart5 => unsafe { Unique::new(registers::UART5_DR_R as *mut _) },
        UartId::Uart6 => unsafe { Unique::new(registers::UART6_DR_R as *mut _) },
        UartId::Uart7 => unsafe { Unique::new(registers::UART7_DR_R as *mut _) },
    }
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<commit_msg>Enable UART FIFO.<commit_after>//! Implements support for the LM4F120 UARTs

// ****************************************************************************
//
// Imports
//
// ****************************************************************************

use core::intrinsics::{volatile_store, volatile_load};
use core::ptr::Unique;
use super::registers;
use super::gpio;
use super::pll;

// ****************************************************************************
//
// Public Types
//
// ****************************************************************************

/// This chip has 8 UARTs
#[derive(PartialEq, Clone, Copy)]
pub enum UartId {
    Uart0,
    Uart1,
    Uart2,
    Uart3,
    Uart4,
    Uart5,
    Uart6,
    Uart7,
}

/// Controls a single UART
/// Only supports 8/N/1 - who needs anything else?
pub struct Uart {
    id: UartId,
    baud: u32,
    nl_mode: NewlineMode,
    reg: Unique<registers::UartRegisters>,
}

/// writeln!() emits LF chars, so this is useful
/// if you're writing text with your UART
#[derive(PartialEq, Clone, Copy)]
pub enum NewlineMode {
    Binary,
    SwapLFtoCRLF,
}

// ****************************************************************************
//
// Private Types
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Data
//
// ****************************************************************************

// None

// ****************************************************************************
//
// Public Functions
//
// ****************************************************************************

impl Uart {
    pub fn new(id: UartId, baud: u32, nl_mode: NewlineMode) -> Uart {
        let mut uart = Uart {
            id: id,
            baud: baud,
            nl_mode: nl_mode,
            reg: get_uart_registers(id),
        };
        uart.init();
        uart
    }

    fn init(&mut self) -> () {
        // Do GPIO pin muxing
        gpio::enable_uart(self.id);
        // Enable UART module in RCGUART register p306
        unsafe {
            self.enable_uart();
            let uart_reg = self.reg.get_mut();

            // Disable UART and all features
            uart_reg.ctl = 0;
            // Calculate the baud rate values
            // baud_div = CLOCK_RATE / (16 * baud_rate);
            // baud_int = round(baud_div * 64)
            let baud_int: u32 = (((pll::get_clock_hz() * 8) / self.baud) + 1) / 2;
            // Store the upper and lower parts of the divider
            uart_reg.ibrd = (baud_int / 64) as usize;
            uart_reg.fbrd = (baud_int % 64) as usize;
            // Set the UART Line Control register value
            // 8N1 + FIFO enabled
            uart_reg.lcrh = registers::UART_LCRH_WLEN_8 | registers::UART_LCRH_FEN;
            // Clear the flags
            uart_reg.rf = 0;
            // Enable
            uart_reg.ctl = registers::UART_CTL_RXE | registers::UART_CTL_TXE |
                           registers::UART_CTL_UARTEN;
        }
    }

    unsafe fn enable_uart(&mut self) {
        let mut reg: usize = volatile_load(registers::SYSCTL_RCGCUART_R);
        reg |= match self.id {
            UartId::Uart0 => 1 << 0,
            UartId::Uart1 => 1 << 1,
            UartId::Uart2 => 1 << 2,
            UartId::Uart3 => 1 << 3,
            UartId::Uart4 => 1 << 4,
            UartId::Uart5 => 1 << 5,
            UartId::Uart6 => 1 << 6,
            UartId::Uart7 => 1 << 7,
        };
        volatile_store(registers::SYSCTL_RCGCUART_R, reg);
    }

    fn putc(&mut self, value: u8) {
        unsafe {
            let uart_reg = self.reg.get_mut();
            while (uart_reg.rf & registers::UART_FR_TXFF) != 0 {
                asm!("NOP");
            }
            uart_reg.data = value as usize;
        }
    }
}

impl ::core::fmt::Write for Uart {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        match self.nl_mode {
            NewlineMode::Binary => {
                for byte in s.bytes() {
                    self.putc(byte)
                }
            }
            NewlineMode::SwapLFtoCRLF => {
                for byte in s.bytes() {
                    if byte == 0x0A {
                        // Prefix every \n with a \r
                        self.putc(0x0D)
                    }
                    self.putc(byte)
                }
            }
        }
        Ok(())
    }
}

// ****************************************************************************
//
// Private Functions
//
// ****************************************************************************

/// Get a Unique<> wrapped pointer to the UART control registers in the chip.
/// We use the Unique<> wrapper to make it easier to store the pointer in our
/// object.
fn get_uart_registers(uart: UartId) -> Unique<registers::UartRegisters> {
    match uart {
        UartId::Uart0 => unsafe { Unique::new(registers::UART0_DR_R as *mut _) },
        UartId::Uart1 => unsafe { Unique::new(registers::UART1_DR_R as *mut _) },
        UartId::Uart2 => unsafe { Unique::new(registers::UART2_DR_R as *mut _) },
        UartId::Uart3 => unsafe { Unique::new(registers::UART3_DR_R as *mut _) },
        UartId::Uart4 => unsafe { Unique::new(registers::UART4_DR_R as *mut _) },
        UartId::Uart5 => unsafe { Unique::new(registers::UART5_DR_R as *mut _) },
        UartId::Uart6 => unsafe { Unique::new(registers::UART6_DR_R as *mut _) },
        UartId::Uart7 => unsafe { Unique::new(registers::UART7_DR_R as *mut _) },
    }
}

// ****************************************************************************
//
// End Of File
//
// ****************************************************************************
<|endoftext|>


<commit_before>use super::ssz::decode::{
    decode_length,
    Decodable,
};
use super::utils::hash::canonical_hash;
use super::block::{
    MIN_SSZ_BLOCK_LENGTH,
    MAX_SSZ_BLOCK_LENGTH,
};
use super::attestation_record::MIN_SSZ_ATTESTION_RECORD_LENGTH;

#[derive(Debug, PartialEq)]
pub enum BlockValidatorError {
    TooShort,
    TooLong,
    BadPowHash,
    SlotTooLow,
    SlotTooHigh,
}

const LENGTH_BYTES: usize = 4;

/// Allows for reading of block values directly from serialized
/// ssz bytes.
///
/// Use this to perform intial checks before we fully de-serialize
/// a block. It should only really be used to verify blocks that come
/// in from the network, for internal operations we should use a full
/// `Block`.
#[derive(Debug, PartialEq)]
pub struct SszBlock<'a> {
    ssz: &'a [u8],
    attestation_len: usize,
    pub len: usize,
}

impl<'a> SszBlock<'a> {
    /// Create a new instance from a slice reference.
    ///
    /// This function will validate the length of the ssz
    /// string, however it will not validate the contents.
    ///
    /// The slice will not be copied, instead referenced.
    pub fn from_slice(vec: &'a [u8])
        -> Result<Self, BlockValidatorError>
    {
        let untrimmed_ssz = &vec[..];
        /*
         * Ensure the SSZ is long enough to be a block with
         * one attestation record (not necessarily a valid
         * attestation record).
         */
        if vec.len() < MIN_SSZ_BLOCK_LENGTH + MIN_SSZ_ATTESTION_RECORD_LENGTH {
            return Err(BlockValidatorError::TooShort);
        }
        /*
         * Ensure the SSZ slice isn't longer than is possible for a block.
         */
        if vec.len() > MAX_SSZ_BLOCK_LENGTH {
            return Err(BlockValidatorError::TooLong);
        }
        /*
         * Determine how many bytes are used to store attestation records.
         */
        let attestation_len = decode_length(untrimmed_ssz, 80, LENGTH_BYTES)
            .map_err(|_| BlockValidatorError::TooShort)?;
        /*
         * The block only has one variable field, `attestations`, therefore
         * the size of the block must be the minimum size, plus the length
         * of the attestations.
         */
        let block_ssz_len = {
            MIN_SSZ_BLOCK_LENGTH + attestation_len
        };
        if vec.len() < block_ssz_len {
            return Err(BlockValidatorError::TooShort);
        }
        Ok(Self{
            ssz: &untrimmed_ssz[0..block_ssz_len],
            attestation_len,
            len: block_ssz_len,
        })
    }

    /// Return the canonical hash for this block.
    pub fn block_hash(&self) -> Vec<u8> {
        canonical_hash(self.ssz)
    }

    /// Return the `parent_hash` field.
    pub fn parent_hash(&self) -> &[u8] {
        &self.ssz[4..36]
    }

    /// Return the `slot_number` field.
    pub fn slot_number(&self) -> u64 {
        /*
         * An error should be unreachable from this decode
         * because we checked the length of the array at
         * the initalization of this struct.
         *
         * If you can make this function panic, please report
         * it to paul@sigmaprime.io
         */
        if let Ok((n, _)) = u64::ssz_decode(&self.ssz, 36) {
            n
        } else {
            unreachable!();
        }
    }

    /// Return the `randao_reveal` field.
    pub fn randao_reveal(&self) -> &[u8] {
        &self.ssz[48..80]
    }

    /// Return the `attestations` field.
    pub fn attestations(&self) -> &[u8] {
        let start = 80 + LENGTH_BYTES;
        &self.ssz[start..(start + self.attestation_len)]
    }

    /// Return the `pow_chain_ref` field.
    pub fn pow_chain_ref(&self) -> &[u8] {
        let start = self.len - (32 + LENGTH_BYTES + 32 + LENGTH_BYTES + 32);
        &self.ssz[start..(start + 32)]
    }

    /// Return the `active_state_root` field.
    pub fn act_state_root(&self) -> &[u8] {
        let start = self.len - (32 + LENGTH_BYTES + 32);
        &self.ssz[start..(start + 32)]
    }

    /// Return the `active_state_root` field.
    pub fn cry_state_root(&self) -> &[u8] {
        let start = self.len - 32;
        &self.ssz[start..(start + 32)]
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::block::Block;
    use super::super::attestation_record::AttestationRecord;
    use super::super::ssz::SszStream;
    use super::super::utils::types::Hash256;

    fn get_block_ssz(b: &Block) -> Vec<u8> {
        let mut ssz_stream = SszStream::new();
        ssz_stream.append(b);
        ssz_stream.drain()
    }

    fn get_attestation_record_ssz(ar: &AttestationRecord) -> Vec<u8> {
        let mut ssz_stream = SszStream::new();
        ssz_stream.append(ar);
        ssz_stream.drain()
    }

    #[test]
    fn test_ssz_block_zero_attestation_records() {
        let mut b = Block::zero();
        b.attestations = vec![];
        let ssz = get_block_ssz(&b);

        assert_eq!(
            SszBlock::from_slice(&ssz[..]),
            Err(BlockValidatorError::TooShort)
        );
    }

    #[test]
    fn test_ssz_block_single_attestation_record_one_byte_short() {
        let mut b = Block::zero();
        b.attestations = vec![AttestationRecord::zero()];
        let ssz = get_block_ssz(&b);

        assert_eq!(
            SszBlock::from_slice(&ssz[0..(ssz.len() - 1)]),
            Err(BlockValidatorError::TooShort)
        );
    }

    #[test]
    fn test_ssz_block_single_attestation_record_one_byte_long() {
        let mut b = Block::zero();
        b.attestations = vec![AttestationRecord::zero()];
        let mut ssz = get_block_ssz(&b);
        let original_len = ssz.len();
        ssz.push(42);

        let ssz_block = SszBlock::from_slice(&ssz[..]).unwrap();

        assert_eq!(ssz_block.len, original_len);
    }

    #[test]
    fn test_ssz_block_single_attestation_record() {
        let mut b = Block::zero();
        b.attestations = vec![AttestationRecord::zero()];
        let ssz = get_block_ssz(&b);

        assert!(SszBlock::from_slice(&ssz[..]).is_ok());
    }

    #[test]
    fn test_ssz_block_block_hash() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();
        let hash = ssz_block.block_hash();
        // Note: this hash was not generated by some external program,
        // it was simply printed then copied into the code. This test
        // will tell us if the hash changes, not that it matches some
        // canonical reference.
        let expected_hash = [
            28, 184, 51, 12, 226, 15, 73, 50, 66, 19, 168, 149,
            229, 122, 141, 111, 42, 236, 137, 157, 230, 90, 149,
            58, 145, 52, 47, 62, 158, 131, 46, 147
        ];
        assert_eq!(hash, expected_hash);

        /*
         * Test if you give the SszBlock too many ssz bytes
         */
        let mut too_long = serialized.clone();
        too_long.push(42);
        let ssz_block = SszBlock::from_slice(&too_long).unwrap();
        let hash = ssz_block.block_hash();
        assert_eq!(hash, expected_hash);
    }

    #[test]
    fn test_ssz_block_parent_hash() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.parent_hash = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.parent_hash(), &reference_hash.to_vec()[..]);
    }

    #[test]
    fn test_ssz_block_slot_number() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        block.slot_number = 42;

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.slot_number(), 42);
    }

    #[test]
    fn test_ssz_block_randao_reveal() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.randao_reveal = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.randao_reveal(), &reference_hash.to_vec()[..]);
    }

    #[test]
    fn test_ssz_block_attestations() {
        /*
         * Single AttestationRecord
         */
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();
        let ssz_ar = get_attestation_record_ssz(&AttestationRecord::zero());

        assert_eq!(ssz_block.attestations(), &ssz_ar[..]);

        /*
         * Multiple AttestationRecords
         */
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        block.attestations.push(AttestationRecord::zero());

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();
        let mut ssz_ar = get_attestation_record_ssz(&AttestationRecord::zero());
        ssz_ar.append(&mut get_attestation_record_ssz(&AttestationRecord::zero()));

        assert_eq!(ssz_block.attestations(), &ssz_ar[..]);
    }

    #[test]
    fn test_ssz_block_pow_chain_ref() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.pow_chain_ref = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.pow_chain_ref(), &reference_hash.to_vec()[..]);
    }

    #[test]
    fn test_ssz_block_act_state_root() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.active_state_root = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.act_state_root(), &reference_hash.to_vec()[..]);
    }

    #[test]
    fn test_ssz_block_cry_state_root() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.crystallized_state_root = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.cry_state_root(), &reference_hash.to_vec()[..]);
    }
}
<commit_msg>Update SszBlock doc comments<commit_after>use super::ssz::decode::{
    decode_length,
    Decodable,
};
use super::utils::hash::canonical_hash;
use super::block::{
    MIN_SSZ_BLOCK_LENGTH,
    MAX_SSZ_BLOCK_LENGTH,
};
use super::attestation_record::MIN_SSZ_ATTESTION_RECORD_LENGTH;

#[derive(Debug, PartialEq)]
pub enum BlockValidatorError {
    TooShort,
    TooLong,
    BadPowHash,
    SlotTooLow,
    SlotTooHigh,
}

const LENGTH_BYTES: usize = 4;

/// Allows for reading of block values directly from serialized ssz bytes.
///
/// The purpose of this struct is to provide the functionality to read block fields directly from
/// some serialized SSZ slice, effectively allowing us to read the block without fully
/// de-serializing it.
///
/// This struct should be as "zero-copy" as possible. The `ssz` field is a reference to some slice
/// and each function reads from that slice.
///
/// Use this to perform intial checks before we fully de-serialize a block. It should only really
/// be used to verify blocks that come in from the network, for internal operations we should use a
/// full `Block`.
#[derive(Debug, PartialEq)]
pub struct SszBlock<'a> {
    ssz: &'a [u8],
    attestation_len: usize,
    pub len: usize,
}

impl<'a> SszBlock<'a> {
    /// Create a new instance from a slice reference.
    ///
    /// This function will validate the length of the ssz string, however it will not validate the
    /// contents.
    ///
    /// The returned `SszBlock` instance will contain a `len` field which can be used to determine
    /// how many bytes were read from the slice. In the case of multiple, sequentually serialized
    /// blocks `len` can be used to assume the location of the next serialized block.
    pub fn from_slice(vec: &'a [u8])
        -> Result<Self, BlockValidatorError>
    {
        let untrimmed_ssz = &vec[..];
        /*
         * Ensure the SSZ is long enough to be a block with
         * one attestation record (not necessarily a valid
         * attestation record).
         */
        if vec.len() < MIN_SSZ_BLOCK_LENGTH + MIN_SSZ_ATTESTION_RECORD_LENGTH {
            return Err(BlockValidatorError::TooShort);
        }
        /*
         * Ensure the SSZ slice isn't longer than is possible for a block.
         */
        if vec.len() > MAX_SSZ_BLOCK_LENGTH {
            return Err(BlockValidatorError::TooLong);
        }
        /*
         * Determine how many bytes are used to store attestation records.
         */
        let attestation_len = decode_length(untrimmed_ssz, 80, LENGTH_BYTES)
            .map_err(|_| BlockValidatorError::TooShort)?;
        /*
         * The block only has one variable field, `attestations`, therefore
         * the size of the block must be the minimum size, plus the length
         * of the attestations.
         */
        let block_ssz_len = {
            MIN_SSZ_BLOCK_LENGTH + attestation_len
        };
        if vec.len() < block_ssz_len {
            return Err(BlockValidatorError::TooShort);
        }
        Ok(Self{
            ssz: &untrimmed_ssz[0..block_ssz_len],
            attestation_len,
            len: block_ssz_len,
        })
    }

    /// Return the canonical hash for this block.
    pub fn block_hash(&self) -> Vec<u8> {
        canonical_hash(self.ssz)
    }

    /// Return the `parent_hash` field.
    pub fn parent_hash(&self) -> &[u8] {
        &self.ssz[4..36]
    }

    /// Return the `slot_number` field.
    pub fn slot_number(&self) -> u64 {
        /*
         * An error should be unreachable from this decode
         * because we checked the length of the array at
         * the initalization of this struct.
         *
         * If you can make this function panic, please report
         * it to paul@sigmaprime.io
         */
        if let Ok((n, _)) = u64::ssz_decode(&self.ssz, 36) {
            n
        } else {
            unreachable!();
        }
    }

    /// Return the `randao_reveal` field.
    pub fn randao_reveal(&self) -> &[u8] {
        &self.ssz[48..80]
    }

    /// Return the `attestations` field.
    pub fn attestations(&self) -> &[u8] {
        let start = 80 + LENGTH_BYTES;
        &self.ssz[start..(start + self.attestation_len)]
    }

    /// Return the `pow_chain_ref` field.
    pub fn pow_chain_ref(&self) -> &[u8] {
        let start = self.len - (32 + LENGTH_BYTES + 32 + LENGTH_BYTES + 32);
        &self.ssz[start..(start + 32)]
    }

    /// Return the `active_state_root` field.
    pub fn act_state_root(&self) -> &[u8] {
        let start = self.len - (32 + LENGTH_BYTES + 32);
        &self.ssz[start..(start + 32)]
    }

    /// Return the `active_state_root` field.
    pub fn cry_state_root(&self) -> &[u8] {
        let start = self.len - 32;
        &self.ssz[start..(start + 32)]
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::block::Block;
    use super::super::attestation_record::AttestationRecord;
    use super::super::ssz::SszStream;
    use super::super::utils::types::Hash256;

    fn get_block_ssz(b: &Block) -> Vec<u8> {
        let mut ssz_stream = SszStream::new();
        ssz_stream.append(b);
        ssz_stream.drain()
    }

    fn get_attestation_record_ssz(ar: &AttestationRecord) -> Vec<u8> {
        let mut ssz_stream = SszStream::new();
        ssz_stream.append(ar);
        ssz_stream.drain()
    }

    #[test]
    fn test_ssz_block_zero_attestation_records() {
        let mut b = Block::zero();
        b.attestations = vec![];
        let ssz = get_block_ssz(&b);

        assert_eq!(
            SszBlock::from_slice(&ssz[..]),
            Err(BlockValidatorError::TooShort)
        );
    }

    #[test]
    fn test_ssz_block_single_attestation_record_one_byte_short() {
        let mut b = Block::zero();
        b.attestations = vec![AttestationRecord::zero()];
        let ssz = get_block_ssz(&b);

        assert_eq!(
            SszBlock::from_slice(&ssz[0..(ssz.len() - 1)]),
            Err(BlockValidatorError::TooShort)
        );
    }

    #[test]
    fn test_ssz_block_single_attestation_record_one_byte_long() {
        let mut b = Block::zero();
        b.attestations = vec![AttestationRecord::zero()];
        let mut ssz = get_block_ssz(&b);
        let original_len = ssz.len();
        ssz.push(42);

        let ssz_block = SszBlock::from_slice(&ssz[..]).unwrap();

        assert_eq!(ssz_block.len, original_len);
    }

    #[test]
    fn test_ssz_block_single_attestation_record() {
        let mut b = Block::zero();
        b.attestations = vec![AttestationRecord::zero()];
        let ssz = get_block_ssz(&b);

        assert!(SszBlock::from_slice(&ssz[..]).is_ok());
    }

    #[test]
    fn test_ssz_block_block_hash() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();
        let hash = ssz_block.block_hash();
        // Note: this hash was not generated by some external program,
        // it was simply printed then copied into the code. This test
        // will tell us if the hash changes, not that it matches some
        // canonical reference.
        let expected_hash = [
            28, 184, 51, 12, 226, 15, 73, 50, 66, 19, 168, 149,
            229, 122, 141, 111, 42, 236, 137, 157, 230, 90, 149,
            58, 145, 52, 47, 62, 158, 131, 46, 147
        ];
        assert_eq!(hash, expected_hash);

        /*
         * Test if you give the SszBlock too many ssz bytes
         */
        let mut too_long = serialized.clone();
        too_long.push(42);
        let ssz_block = SszBlock::from_slice(&too_long).unwrap();
        let hash = ssz_block.block_hash();
        assert_eq!(hash, expected_hash);
    }

    #[test]
    fn test_ssz_block_parent_hash() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.parent_hash = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.parent_hash(), &reference_hash.to_vec()[..]);
    }

    #[test]
    fn test_ssz_block_slot_number() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        block.slot_number = 42;

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.slot_number(), 42);
    }

    #[test]
    fn test_ssz_block_randao_reveal() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.randao_reveal = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.randao_reveal(), &reference_hash.to_vec()[..]);
    }

    #[test]
    fn test_ssz_block_attestations() {
        /*
         * Single AttestationRecord
         */
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();
        let ssz_ar = get_attestation_record_ssz(&AttestationRecord::zero());

        assert_eq!(ssz_block.attestations(), &ssz_ar[..]);

        /*
         * Multiple AttestationRecords
         */
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        block.attestations.push(AttestationRecord::zero());

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();
        let mut ssz_ar = get_attestation_record_ssz(&AttestationRecord::zero());
        ssz_ar.append(&mut get_attestation_record_ssz(&AttestationRecord::zero()));

        assert_eq!(ssz_block.attestations(), &ssz_ar[..]);
    }

    #[test]
    fn test_ssz_block_pow_chain_ref() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.pow_chain_ref = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.pow_chain_ref(), &reference_hash.to_vec()[..]);
    }

    #[test]
    fn test_ssz_block_act_state_root() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.active_state_root = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.act_state_root(), &reference_hash.to_vec()[..]);
    }

    #[test]
    fn test_ssz_block_cry_state_root() {
        let mut block = Block::zero();
        block.attestations.push(AttestationRecord::zero());
        let reference_hash = Hash256::from([42_u8; 32]);
        block.crystallized_state_root = reference_hash.clone();

        let serialized = get_block_ssz(&block);
        let ssz_block = SszBlock::from_slice(&serialized).unwrap();

        assert_eq!(ssz_block.cry_state_root(), &reference_hash.to_vec()[..]);
    }
}
<|endoftext|>


<commit_before>use gc::Address;
use gc::swiper::old::OldGen;
use gc::swiper::Region;
use gc::swiper::young::YoungGen;

use object::Obj;

pub struct Verifier<'a> {
    young: &'a YoungGen,
    old: &'a OldGen,

    old_region: Region,
    young_region: Region,
}

impl<'a> Verifier<'a> {
    pub fn new(young: &'a YoungGen, old: &'a OldGen) -> Verifier<'a> {
        Verifier {
            young: young,
            old: old,

            young_region: young.used_region(),
            old_region: old.used_region(),
        }
    }

    pub fn verify(&mut self) {
        self.verify_young();
        self.verify_old();
    }

    fn verify_young(&mut self) {
        let region = self.young_region.clone();
        self.verify_objects(region);
    }

    fn verify_old(&mut self) {
        let region = self.old_region.clone();
        self.verify_objects(region);
    }

    fn verify_objects(&mut self, region: Region) {
        let mut ptr = region.start;

        while ptr < region.end {
            let object = unsafe { &mut *ptr.to_mut_ptr::<Obj>() };

            object.visit_reference_fields(|child| {
                let child_ptr = child.get();
                self.verify_reference(child_ptr);
            });

            ptr = ptr.offset(object.size());
        }

        assert!(ptr == region.end, "object doesn't end at region end");
    }

    fn verify_reference(&mut self, obj: *mut Obj) {
        let addr = Address::from_ptr(obj);

        if obj.is_null() || self.old_region.contains(addr) || self.young_region.contains(addr) {
            return;
        }

        println!(
            "YNG: {:x}-{:x} active {:x}-{:x}",
            self.young.total.start.to_usize(),
            self.young.total.start.to_usize(),
            self.young_region.start.to_usize(),
            self.young_region.end.to_usize()
        );
        println!(
            "OLD: {:x}-{:x} active {:x}-{:x}",
            self.old.total.start.to_usize(),
            self.old.total.end.to_usize(),
            self.old_region.start.to_usize(),
            self.old_region.end.to_usize()
        );
        println!("found reference: {:x}", addr.to_usize());

        panic!("reference neither pointing into young or old generation.");
    }
}
<commit_msg>swiper: check references by determining object size<commit_after>use gc::Address;
use gc::swiper::old::OldGen;
use gc::swiper::Region;
use gc::swiper::young::YoungGen;

use object::Obj;

pub struct Verifier<'a> {
    young: &'a YoungGen,
    old: &'a OldGen,

    old_region: Region,
    young_region: Region,
}

impl<'a> Verifier<'a> {
    pub fn new(young: &'a YoungGen, old: &'a OldGen) -> Verifier<'a> {
        Verifier {
            young: young,
            old: old,

            young_region: young.used_region(),
            old_region: old.used_region(),
        }
    }

    pub fn verify(&mut self) {
        self.verify_young();
        self.verify_old();
    }

    fn verify_young(&mut self) {
        let region = self.young_region.clone();
        self.verify_objects(region);
    }

    fn verify_old(&mut self) {
        let region = self.old_region.clone();
        self.verify_objects(region);
    }

    fn verify_objects(&mut self, region: Region) {
        let mut ptr = region.start;

        while ptr < region.end {
            let object = unsafe { &mut *ptr.to_mut_ptr::<Obj>() };

            object.visit_reference_fields(|child| {
                let child_ptr = child.get();
                self.verify_reference(child_ptr);
            });

            ptr = ptr.offset(object.size());
        }

        assert!(ptr == region.end, "object doesn't end at region end");
    }

    fn verify_reference(&mut self, obj: *mut Obj) {
        let addr = Address::from_ptr(obj);

        if obj.is_null() {
            return;
        }

        if self.old_region.contains(addr) || self.young_region.contains(addr) {
            let object = unsafe { &mut *obj };

            // Verify that the address is the start of an object, for this access its size.
            // To make sure this isn't optimized out by the compiler, make sure that the size doesn't equal 1.
            assert!(object.size() != 1, "object size shouldn't be 1");
            return;
        }

        println!(
            "YNG: {:x}-{:x}; active: {:x}-{:x}",
            self.young.total.start.to_usize(),
            self.young.total.end.to_usize(),
            self.young_region.start.to_usize(),
            self.young_region.end.to_usize()
        );
        println!(
            "OLD: {:x}-{:x}; active: {:x}-{:x}",
            self.old.total.start.to_usize(),
            self.old.total.end.to_usize(),
            self.old_region.start.to_usize(),
            self.old_region.end.to_usize()
        );
        println!("found reference: {:x}", addr.to_usize());

        panic!("reference neither pointing into young nor old generation.");
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

// xfail-test
fn id<T>(t: T) -> T { t }

fn f<T>(v: &'r T) -> &'r fn()->T { id::<&'r fn()->T>(|| *v) } //~ ERROR ???

fn main() {
    let v = &5;
    io::println(fmt!("%d", f(v)()));
}
<commit_msg>testsuite: Update and un-xfail test for #4335<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn id<T>(t: T) -> T { t }

fn f<'r, T>(v: &'r T) -> &'r fn()->T { id::<&'r fn()->T>(|| *v) } //~ ERROR cannot infer an appropriate lifetime due to conflicting requirements

fn main() {
    let v = &5;
    io::println(fmt!("%d", f(v)()));
}
<|endoftext|>


<commit_before>import swappable::{swappable, methods};

fn main() {
    let d = swappable(3);
    assert d.get() == 3;
    d.set(4);
    assert d.get() == 4;
    d.swap { |i| i + 1 };
    assert d.get() == 5;
    assert d.with { |i| i + 1 } == 6;
    assert d.get() == 5;
    assert swappable::unwrap(d) == 5;
}<commit_msg>test: Remove swappable-test<commit_after><|endoftext|>


<commit_before>use crate::faker::finance::raw::*;
use crate::locales::Data;
use crate::{Dummy, Fake};
use rand::seq::SliceRandom;
use rand::Rng;

const ALPHABET: &[char; 26] = &[
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
    'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
];

const ISO3166: &[&str] = &[
    "AC", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW",
    "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ",
    "BR", "BS", "BT", "BU", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CE", "CF", "CG", "CH", "CI",
    "CK", "CL", "CM", "CN", "CO", "CP", "CR", "CS", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DD",
    "DE", "DG", "DJ", "DK", "DM", "DO", "DZ", "EA", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "EU",
    "FI", "FJ", "FK", "FM", "FO", "FR", "FX", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL",
    "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU",
    "IC", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE",
    "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR",
    "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN",
    "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF",
    "NG", "NI", "NL", "NO", "NP", "NR", "NT", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK",
    "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB",
    "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SU",
    "SV", "SX", "SY", "SZ", "TA", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO",
    "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI",
    "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZR", "ZW",
];

const VOWELS: &[char; 5] = &['A', 'E', 'I', 'O', 'U'];

impl<L: Data> Dummy<Bic<L>> for String {
    fn dummy_with_rng<R: Rng + ?Sized>(_: &Bic<L>, rng: &mut R) -> Self {
        let prob: i8 = (0..100).fake_with_rng(rng);
        let sufix;
        if prob < 10 {
            sufix = format!(
                "{}{}{}",
                *ALPHABET.choose(rng).unwrap(),
                *VOWELS.choose(rng).unwrap(),
                *ALPHABET.choose(rng).unwrap()
            );
        } else if prob < 40 {
            let first: String = (0..9).fake_with_rng(rng);
            let second: String = (0..9).fake_with_rng(rng);
            let third: String = (0..9).fake_with_rng(rng);
            sufix = format!("{}{}{}", first, second, third);
        } else {
            sufix = "".to_string();
        }
        format!(
            "{}{}{}{}{}{}1{}",
            *ALPHABET.choose(rng).unwrap(),
            *ALPHABET.choose(rng).unwrap(),
            *ALPHABET.choose(rng).unwrap(),
            *VOWELS.choose(rng).unwrap(),
            *ISO3166.choose(rng).unwrap(),
            *ALPHABET.choose(rng).unwrap(),
            sufix
        )
    }
}
<commit_msg>remove unnecessary allocation in finance<commit_after>use crate::faker::finance::raw::*;
use crate::locales::Data;
use crate::{Dummy, Fake};
use rand::seq::SliceRandom;
use rand::Rng;

const ALPHABET: &[char; 26] = &[
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
    'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
];

const ISO3166: &[&str] = &[
    "AC", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW",
    "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BQ",
    "BR", "BS", "BT", "BU", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CE", "CF", "CG", "CH", "CI",
    "CK", "CL", "CM", "CN", "CO", "CP", "CR", "CS", "CS", "CU", "CV", "CW", "CX", "CY", "CZ", "DD",
    "DE", "DG", "DJ", "DK", "DM", "DO", "DZ", "EA", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "EU",
    "FI", "FJ", "FK", "FM", "FO", "FR", "FX", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", "GL",
    "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU",
    "IC", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", "JM", "JO", "JP", "KE",
    "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR",
    "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN",
    "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF",
    "NG", "NI", "NL", "NO", "NP", "NR", "NT", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK",
    "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB",
    "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SU",
    "SV", "SX", "SY", "SZ", "TA", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO",
    "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI",
    "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZR", "ZW",
];

const VOWELS: &[char; 5] = &['A', 'E', 'I', 'O', 'U'];

impl<L: Data> Dummy<Bic<L>> for String {
    fn dummy_with_rng<R: Rng + ?Sized>(_: &Bic<L>, rng: &mut R) -> Self {
        let prob: i8 = (0..100).fake_with_rng(rng);
        let suffix = if prob < 50 {
            return format!(
                "{}{}{}{}{}{}1",
                *ALPHABET.choose(rng).unwrap(),
                *ALPHABET.choose(rng).unwrap(),
                *ALPHABET.choose(rng).unwrap(),
                *VOWELS.choose(rng).unwrap(),
                *ISO3166.choose(rng).unwrap(),
                *ALPHABET.choose(rng).unwrap(),
            );
        } else if prob < 90 {
            (
                rng.gen_range('0'..'9'),
                rng.gen_range('0'..'9'),
                rng.gen_range('0'..'9'),
            )
        } else {
            (
                *ALPHABET.choose(rng).unwrap(),
                *VOWELS.choose(rng).unwrap(),
                *ALPHABET.choose(rng).unwrap(),
            )
        };
        format!(
            "{}{}{}{}{}{}1{}{}{}",
            *ALPHABET.choose(rng).unwrap(),
            *ALPHABET.choose(rng).unwrap(),
            *ALPHABET.choose(rng).unwrap(),
            *VOWELS.choose(rng).unwrap(),
            *ISO3166.choose(rng).unwrap(),
            *ALPHABET.choose(rng).unwrap(),
            suffix.0,
            suffix.1,
            suffix.2,
        )
    }
}
<|endoftext|>