<commit_before>use std::{ u8, u16, u32 };
use std::num::Int;

pub enum Either<Left, Right> {
    Left(Left),
    Right(Right),
}

pub trait Halveable {
    type HalfSize: ExtInt;
    fn split(self) -> (Self::HalfSize, Self::HalfSize);
    fn join(h1: Self::HalfSize, h2: Self::HalfSize) -> Self;
}

pub trait To64 { fn to64(self) -> u64; }
pub trait From { fn from<T: To64>(n: T) -> Self; }
pub trait BitLength { fn bits(self) -> usize; }
pub trait ExtInt: Int + To64 + From + BitLength { }

impl Halveable for u64 {
    type HalfSize = u32;
    fn split(self) -> (u32, u32) {
        ((self >> u32::BITS) as u32, self as u32)
    }
    fn join(h1: u32, h2: u32) -> u64 {
        ((h1 as u64) << u32::BITS as u64) + (h2 as u64)
    }
}
impl Halveable for u32 {
    type HalfSize = u16;
    fn split(self) -> (u16, u16) {
        ((self >> u16::BITS) as u16, self as u16)
    }
    fn join(h1: u16, h2: u16) -> u32 {
        ((h1 as u32) << u16::BITS as u32) + (h2 as u32)
    }
}
impl Halveable for u16 {
    type HalfSize = u8;
    fn split(self) -> (u8, u8) {
        ((self >> u8::BITS) as u8, self as u8)
    }
    fn join(h1: u8, h2: u8) -> u16 {
        ((h1 as u16) << u8::BITS as u16) + (h2 as u16)
    }
}

impl To64 for usize { #[inline] fn to64(self) -> u64 { self as u64 } }
impl To64 for u64 { #[inline] fn to64(self) -> u64 { self } }
impl To64 for u32 { #[inline] fn to64(self) -> u64 { self as u64 } }
impl To64 for u16 { #[inline] fn to64(self) -> u64 { self as u64 } }
impl To64 for u8 { #[inline] fn to64(self) -> u64 { self as u64 } }

impl From for usize { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() as usize } }
impl From for u64 { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() } }
impl From for u32 { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() as u32 } }
impl From for u16 { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() as u16 } }
impl From for u8 { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() as u8 } }

impl BitLength for u64 { #[inline] fn bits(self) -> usize { 64us } }
impl BitLength for u32 { #[inline] fn bits(self) -> usize { 32us } }
impl BitLength for u16 { #[inline] fn bits(self) -> usize { 16us } }
impl BitLength for u8 { #[inline] fn bits(self) -> usize { 8us } }

impl ExtInt for u64 { }
impl ExtInt for u32 { }
impl ExtInt for u16 { }
impl ExtInt for u8 { }

pub fn cast<T: To64, U: From>(n: T) -> U {
    From::from(n)
}

pub fn bits<T: BitLength + Int>() -> usize {
    let zero: T = Int::zero();
    BitLength::bits(zero)
}
<commit_msg>Single line some code<commit_after>use std::{ u8, u16, u32 };
use std::num::Int;

pub enum Either<Left, Right> { Left(Left), Right(Right) }

pub trait Halveable {
    type HalfSize: ExtInt;

    fn split(self) -> (Self::HalfSize, Self::HalfSize);
    fn join(h1: Self::HalfSize, h2: Self::HalfSize) -> Self;
}

pub trait To64 { fn to64(self) -> u64; }
pub trait From { fn from<T: To64>(n: T) -> Self; }
pub trait BitLength { fn bits(self) -> usize; }
pub trait ExtInt: Int + To64 + From + BitLength { }

impl Halveable for u64 {
    type HalfSize = u32;

    fn split(self) -> (u32, u32) { ((self >> u32::BITS) as u32, self as u32) }
    fn join(h1: u32, h2: u32) -> u64 { ((h1 as u64) << u32::BITS as u64) + (h2 as u64) }
}
impl Halveable for u32 {
    type HalfSize = u16;

    fn split(self) -> (u16, u16) { ((self >> u16::BITS) as u16, self as u16) }
    fn join(h1: u16, h2: u16) -> u32 { ((h1 as u32) << u16::BITS as u32) + (h2 as u32) }
}
impl Halveable for u16 {
    type HalfSize = u8;

    fn split(self) -> (u8, u8) { ((self >> u8::BITS) as u8, self as u8) }
    fn join(h1: u8, h2: u8) -> u16 { ((h1 as u16) << u8::BITS as u16) + (h2 as u16) }
}

impl To64 for usize { #[inline] fn to64(self) -> u64 { self as u64 } }
impl To64 for u64 { #[inline] fn to64(self) -> u64 { self } }
impl To64 for u32 { #[inline] fn to64(self) -> u64 { self as u64 } }
impl To64 for u16 { #[inline] fn to64(self) -> u64 { self as u64 } }
impl To64 for u8 { #[inline] fn to64(self) -> u64 { self as u64 } }

impl From for usize { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() as usize } }
impl From for u64 { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() } }
impl From for u32 { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() as u32 } }
impl From for u16 { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() as u16 } }
impl From for u8 { #[inline] fn from<T: To64>(n: T) -> Self { n.to64() as u8 } }

impl BitLength for u64 { #[inline] fn bits(self) -> usize { 64us } }
impl BitLength for u32 { #[inline] fn bits(self) -> usize { 32us } }
impl BitLength for u16 { #[inline] fn bits(self) -> usize { 16us } }
impl BitLength for u8 { #[inline] fn bits(self) -> usize { 8us } }

impl ExtInt for u64 { }
impl ExtInt for u32 { }
impl ExtInt for u16 { }
impl ExtInt for u8 { }

pub fn cast<T: To64, U: From>(n: T) -> U {
    From::from(n)
}

pub fn bits<T: BitLength + Int>() -> usize {
    let zero: T = Int::zero();
    BitLength::bits(zero)
}
<|endoftext|>


<commit_before>
use std::{ fs, io };
use std::fs::{ PathExt, ReadDir, DirEntry };
use std::path::Path;

// Source for walk_dir func, struct, and iterator implementation
// copied from rust nightly source. As of now, it is unstable.
pub fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<WalkDir> {
    let start = try!(fs::read_dir(path));
    Ok(WalkDir { cur: Some(start), stack: Vec::new() })
}

pub struct WalkDir {
    cur: Option<ReadDir>,
    stack: Vec<io::Result<ReadDir>>,
}

impl Iterator for WalkDir {
    type Item = io::Result<DirEntry>;

    fn next(&mut self) -> Option<io::Result<DirEntry>> {
        loop {
            if let Some(ref mut cur) = self.cur {
                match cur.next() {
                    Some(Err(e)) => return Some(Err(e)),
                    Some(Ok(next)) => {
                        let path = next.path();
                        if path.is_dir() {
                            self.stack.push(fs::read_dir(&*path));
                        }
                        return Some(Ok(next))
                    }
                    None => {}
                }
            }
            self.cur = None;
            match self.stack.pop() {
                Some(Err(e)) => return Some(Err(e)),
                Some(Ok(next)) => self.cur = Some(next),
                None => return None,
            }
        }
    }
}

// Source for relative_from copied from rust nightly source.

pub trait RelativeFrom {
    fn my_relative_from<'a, P: ?Sized + AsRef<Path>>(&'a self, base: &'a P) -> Option<&Path>;
}

impl RelativeFrom for Path {
    fn my_relative_from<'a, P: ?Sized + AsRef<Path>>(&'a self, base: &'a P) -> Option<&Path> {
        iter_after(self.components(), base.as_ref().components()).map(|c| c.as_path())
    }

}

fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I> where
    I: Iterator<Item=A> + Clone, J: Iterator<Item=A>, A: PartialEq
{
    loop {
        let mut iter_next = iter.clone();
        match (iter_next.next(), prefix.next()) {
            (Some(x), Some(y)) => {
                if x != y { return None }
            }
            (Some(_), None) => return Some(iter),
            (None, None) => return Some(iter),
            (None, Some(_)) => return None,
        }
        iter = iter_next;
    }
}

//pub fn relative_from<P: AsRef<Path>>(full: &P, base: &P) -> Option<&Path> {
//}
<commit_msg>cleanup<commit_after>
use std::{ fs, io };
use std::fs::{ PathExt, ReadDir, DirEntry };
use std::path::Path;

// Source for walk_dir func, struct, and iterator implementation
// copied from rust nightly source. As of now, it is unstable.
pub fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<WalkDir> {
    let start = try!(fs::read_dir(path));
    Ok(WalkDir { cur: Some(start), stack: Vec::new() })
}

pub struct WalkDir {
    cur: Option<ReadDir>,
    stack: Vec<io::Result<ReadDir>>,
}

impl Iterator for WalkDir {
    type Item = io::Result<DirEntry>;

    fn next(&mut self) -> Option<io::Result<DirEntry>> {
        loop {
            if let Some(ref mut cur) = self.cur {
                match cur.next() {
                    Some(Err(e)) => return Some(Err(e)),
                    Some(Ok(next)) => {
                        let path = next.path();
                        if path.is_dir() {
                            self.stack.push(fs::read_dir(&*path));
                        }
                        return Some(Ok(next))
                    }
                    None => {}
                }
            }
            self.cur = None;
            match self.stack.pop() {
                Some(Err(e)) => return Some(Err(e)),
                Some(Ok(next)) => self.cur = Some(next),
                None => return None,
            }
        }
    }
}

// Source for relative_from copied from rust nightly source.
pub trait RelativeFrom {
    fn my_relative_from<'a, P: ?Sized + AsRef<Path>>(&'a self, base: &'a P) -> Option<&Path>;
}

impl RelativeFrom for Path {
    fn my_relative_from<'a, P: ?Sized + AsRef<Path>>(&'a self, base: &'a P) -> Option<&Path> {
        iter_after(self.components(), base.as_ref().components()).map(|c| c.as_path())
    }

}

fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I> where
    I: Iterator<Item=A> + Clone, J: Iterator<Item=A>, A: PartialEq
{
    loop {
        let mut iter_next = iter.clone();
        match (iter_next.next(), prefix.next()) {
            (Some(x), Some(y)) => {
                if x != y { return None }
            }
            (Some(_), None) => return Some(iter),
            (None, None) => return Some(iter),
            (None, Some(_)) => return None,
        }
        iter = iter_next;
    }
}

<|endoftext|>


<commit_before>use std::ffi::CString;
use std::ffi::OsStr;
use std::io;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::ptr;

use libc::{ssize_t, ENOATTR, ERANGE};

#[allow(dead_code)]
pub fn name_to_c(name: &OsStr) -> io::Result<CString> {
    match CString::new(name.as_bytes()) {
        Ok(name) => Ok(name),
        Err(_) => Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "name must not contain null bytes",
        )),
    }
}

pub fn path_to_c(path: &Path) -> io::Result<CString> {
    match CString::new(path.as_os_str().as_bytes()) {
        Ok(name) => Ok(name),
        Err(_) => Err(io::Error::new(io::ErrorKind::NotFound, "file not found")),
    }
}

pub fn extract_noattr(result: io::Result<Vec<u8>>) -> io::Result<Option<Vec<u8>>> {
    result.map(|v| Some(v)).or_else(|e| match e.raw_os_error() {
        Some(ENOATTR) => Ok(None),
        _ => Err(e),
    })
}

pub unsafe fn allocate_loop<F: FnMut(*mut u8, usize) -> ssize_t>(mut f: F) -> io::Result<Vec<u8>> {
    let mut vec: Vec<u8> = Vec::new();
    loop {
        let ret = (f)(ptr::null_mut(), 0);
        if ret < 0 {
            return Err(io::Error::last_os_error());
        } else if ret == 0 {
            break;
        }
        vec.reserve_exact(ret as usize);

        let ret = (f)(vec.as_mut_ptr(), vec.capacity());
        if ret >= 0 {
            vec.set_len(ret as usize);
            break;
        } else {
            let error = io::Error::last_os_error();
            if error.raw_os_error() == Some(ERANGE) {
                continue;
            }
            return Err(error);
        }
    }
    vec.shrink_to_fit();
    Ok(vec)
}
<commit_msg>clippy lint<commit_after>use std::ffi::CString;
use std::ffi::OsStr;
use std::io;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::ptr;

use libc::{ssize_t, ENOATTR, ERANGE};

#[allow(dead_code)]
pub fn name_to_c(name: &OsStr) -> io::Result<CString> {
    match CString::new(name.as_bytes()) {
        Ok(name) => Ok(name),
        Err(_) => Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "name must not contain null bytes",
        )),
    }
}

pub fn path_to_c(path: &Path) -> io::Result<CString> {
    match CString::new(path.as_os_str().as_bytes()) {
        Ok(name) => Ok(name),
        Err(_) => Err(io::Error::new(io::ErrorKind::NotFound, "file not found")),
    }
}

pub fn extract_noattr(result: io::Result<Vec<u8>>) -> io::Result<Option<Vec<u8>>> {
    result.map(Some).or_else(|e| match e.raw_os_error() {
        Some(ENOATTR) => Ok(None),
        _ => Err(e),
    })
}

pub unsafe fn allocate_loop<F: FnMut(*mut u8, usize) -> ssize_t>(mut f: F) -> io::Result<Vec<u8>> {
    let mut vec: Vec<u8> = Vec::new();
    loop {
        let ret = (f)(ptr::null_mut(), 0);
        if ret < 0 {
            return Err(io::Error::last_os_error());
        } else if ret == 0 {
            break;
        }
        vec.reserve_exact(ret as usize);

        let ret = (f)(vec.as_mut_ptr(), vec.capacity());
        if ret >= 0 {
            vec.set_len(ret as usize);
            break;
        } else {
            let error = io::Error::last_os_error();
            if error.raw_os_error() == Some(ERANGE) {
                continue;
            }
            return Err(error);
        }
    }
    vec.shrink_to_fit();
    Ok(vec)
}
<|endoftext|>


<commit_before>#[macro_use]
pub mod reply_markup;

use serde::de::DeserializeOwned;
use serde::ser::{Serialize, Serializer, Error};
use serde_json;

use types::*;

pub use self::reply_markup::*;

pub trait Response {
    type Raw: DeserializeOwned;
    type Type;

    fn map(Self::Raw) -> Self::Type;
}

pub struct IdResponse<T> {
    _phantom: ::std::marker::PhantomData<T>
}

impl<T: DeserializeOwned> Response for IdResponse<T> {
    type Raw = T;
    type Type = T;

    fn map(value: Self::Raw) -> Self::Type {
        value
    }
}

pub struct TrueToUnitResponse;

impl Response for TrueToUnitResponse {
    type Raw = True;
    type Type = ();

    fn map(_: Self::Raw) -> Self::Type {
        ()
    }
}

/// Request corresponds to the specific Telegram API method.
pub trait Request: Serialize {
    type Response: Response + Send + 'static;

    /// Name of the method.
    fn name(&self) -> &'static str;

    fn detach(&self) -> DetachedRequest<Self::Response> {
        DetachedRequest {
            name: self.name(),
            encoded: serde_json::to_vec(self).map_err(|err| format!("{}", err)),
            phantom: ::std::marker::PhantomData,
        }
    }
}

impl<'a, Req: Request> Request for &'a Req {
    type Response = Req::Response;

    fn name(&self) -> &'static str {
        (*self).name()
    }
}

impl<'a, Req: Request> Request for &'a mut Req {
    type Response = Req::Response;

    fn name(&self) -> &'static str {
        (**self).name()
    }
}

pub struct DetachedRequest<Resp> {
    name: &'static str,
    encoded: Result<Vec<u8>, String>,
    phantom: ::std::marker::PhantomData<Resp>,
}

impl<Resp: Response + Send + 'static> Request for DetachedRequest<Resp> {
    type Response = Resp;

    fn name(&self) -> &'static str {
        self.name
    }
}

impl<Resp> Serialize for DetachedRequest<Resp> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {

        match self.encoded {
            Ok(ref string) => serializer.serialize_bytes(string.as_ref()),
            Err(ref err) => Err(S::Error::custom(err)),
        }
    }
}

pub trait ToRequest<'b, 'c> {
    type Request: Request;
    fn to_request<C>(&'b self, chat: C) -> Self::Request where C: ToChatRef<'c>;
}

pub trait ToReplyRequest<'b, 'c> {
    type Request: Request;
    fn to_reply_request(&'b self, message: &Message) -> Self::Request;
}

/// Strongly typed ParseMode.
/// See [documentation](https://core.telegram.org/bots/api#formatting-options) for details.
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize)]
pub enum ParseMode {
    /// Use markdown formatting.
    Markdown,
    /// Use HTML formatting.
    #[serde(rename = "HTML")]
    Html,
}
<commit_msg>fix: use serde_json::Value as intermediate request representation for DetachedRequest<commit_after>#[macro_use]
pub mod reply_markup;

use serde::de::DeserializeOwned;
use serde::ser::{Serialize, Serializer, Error};
use serde_json::{Value, to_value};

use types::*;

pub use self::reply_markup::*;

pub trait Response {
    type Raw: DeserializeOwned;
    type Type;

    fn map(Self::Raw) -> Self::Type;
}

pub struct IdResponse<T> {
    _phantom: ::std::marker::PhantomData<T>
}

impl<T: DeserializeOwned> Response for IdResponse<T> {
    type Raw = T;
    type Type = T;

    fn map(value: Self::Raw) -> Self::Type {
        value
    }
}

pub struct TrueToUnitResponse;

impl Response for TrueToUnitResponse {
    type Raw = True;
    type Type = ();

    fn map(_: Self::Raw) -> Self::Type {
        ()
    }
}

/// Request corresponds to the specific Telegram API method.
pub trait Request: Serialize {
    type Response: Response + Send + 'static;

    /// Name of the method.
    fn name(&self) -> &'static str;

    fn detach(&self) -> DetachedRequest<Self::Response> {
        DetachedRequest {
            name: self.name(),
            encoded: to_value(self).map_err(|err| format!("{}", err)),
            phantom: ::std::marker::PhantomData,
        }
    }
}

impl<'a, Req: Request> Request for &'a Req {
    type Response = Req::Response;

    fn name(&self) -> &'static str {
        (*self).name()
    }
}

impl<'a, Req: Request> Request for &'a mut Req {
    type Response = Req::Response;

    fn name(&self) -> &'static str {
        (**self).name()
    }
}

pub struct DetachedRequest<Resp> {
    name: &'static str,
    encoded: Result<Value, String>,
    phantom: ::std::marker::PhantomData<Resp>,
}

impl<Resp: Response + Send + 'static> Request for DetachedRequest<Resp> {
    type Response = Resp;

    fn name(&self) -> &'static str {
        self.name
    }
}

impl<Resp> Serialize for DetachedRequest<Resp> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {

        match self.encoded {
            Ok(ref value) => value.serialize(serializer),
            Err(ref err) => Err(S::Error::custom(err)),
        }
    }
}

pub trait ToRequest<'b, 'c> {
    type Request: Request;
    fn to_request<C>(&'b self, chat: C) -> Self::Request where C: ToChatRef<'c>;
}

pub trait ToReplyRequest<'b, 'c> {
    type Request: Request;
    fn to_reply_request(&'b self, message: &Message) -> Self::Request;
}

/// Strongly typed ParseMode.
/// See [documentation](https://core.telegram.org/bots/api#formatting-options) for details.
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize)]
pub enum ParseMode {
    /// Use markdown formatting.
    Markdown,
    /// Use HTML formatting.
    #[serde(rename = "HTML")]
    Html,
}
<|endoftext|>


<commit_before>use crate::transform::{MirPass, MirSource};
use crate::util::patch::MirPatch;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_target::spec::PanicStrategy;

/// A pass that removes noop landing pads and replaces jumps to them with
/// `None`. This is important because otherwise LLVM generates terrible
/// code for these.
pub struct RemoveNoopLandingPads;

pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
    if tcx.sess.panic_strategy() == PanicStrategy::Abort {
        return;
    }
    debug!("remove_noop_landing_pads({:?})", body);

    RemoveNoopLandingPads.remove_nop_landing_pads(body)
}

impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
        remove_noop_landing_pads(tcx, body);
    }
}

impl RemoveNoopLandingPads {
    fn is_nop_landing_pad(
        &self,
        bb: BasicBlock,
        body: &Body<'_>,
        nop_landing_pads: &BitSet<BasicBlock>,
    ) -> bool {
        for stmt in &body[bb].statements {
            match &stmt.kind {
                StatementKind::FakeRead(..)
                | StatementKind::StorageLive(_)
                | StatementKind::StorageDead(_)
                | StatementKind::AscribeUserType(..)
                | StatementKind::Coverage(..)
                | StatementKind::Nop => {
                    // These are all nops in a landing pad
                }

                StatementKind::Assign(box (place, Rvalue::Use(_))) => {
                    if place.as_local().is_some() {
                        // Writing to a local (e.g., a drop flag) does not
                        // turn a landing pad to a non-nop
                    } else {
                        return false;
                    }
                }

                StatementKind::Assign { .. }
                | StatementKind::SetDiscriminant { .. }
                | StatementKind::LlvmInlineAsm { .. }
                | StatementKind::Retag { .. } => {
                    return false;
                }
            }
        }

        let terminator = body[bb].terminator();
        match terminator.kind {
            TerminatorKind::Goto { .. }
            | TerminatorKind::Resume
            | TerminatorKind::SwitchInt { .. }
            | TerminatorKind::FalseEdge { .. }
            | TerminatorKind::FalseUnwind { .. } => {
                terminator.successors().all(|&succ| nop_landing_pads.contains(succ))
            }
            TerminatorKind::GeneratorDrop
            | TerminatorKind::Yield { .. }
            | TerminatorKind::Return
            | TerminatorKind::Abort
            | TerminatorKind::Unreachable
            | TerminatorKind::Call { .. }
            | TerminatorKind::Assert { .. }
            | TerminatorKind::DropAndReplace { .. }
            | TerminatorKind::Drop { .. }
            | TerminatorKind::InlineAsm { .. } => false,
        }
    }

    fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
        // make sure there's a single resume block
        let resume_block = {
            let patch = MirPatch::new(body);
            let resume_block = patch.resume_block();
            patch.apply(body);
            resume_block
        };
        debug!("remove_noop_landing_pads: resume block is {:?}", resume_block);

        let mut jumps_folded = 0;
        let mut landing_pads_removed = 0;
        let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks().len());

        // This is a post-order traversal, so that if A post-dominates B
        // then A will be visited before B.
        let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect();
        for bb in postorder {
            debug!("  processing {:?}", bb);
            for target in body[bb].terminator_mut().successors_mut() {
                if *target != resume_block && nop_landing_pads.contains(*target) {
                    debug!("    folding noop jump to {:?} to resume block", target);
                    *target = resume_block;
                    jumps_folded += 1;
                }
            }

            if let Some(unwind) = body[bb].terminator_mut().unwind_mut() {
                if *unwind == Some(resume_block) {
                    debug!("    removing noop landing pad");
                    jumps_folded -= 1;
                    landing_pads_removed += 1;
                    *unwind = None;
                }
            }

            let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads);
            if is_nop_landing_pad {
                nop_landing_pads.insert(bb);
            }
            debug!("    is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad);
        }

        debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed);
    }
}
<commit_msg>Fix underflow when calculating the number of no-op jumps folded<commit_after>use crate::transform::{MirPass, MirSource};
use crate::util::patch::MirPatch;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_target::spec::PanicStrategy;

/// A pass that removes noop landing pads and replaces jumps to them with
/// `None`. This is important because otherwise LLVM generates terrible
/// code for these.
pub struct RemoveNoopLandingPads;

pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
    if tcx.sess.panic_strategy() == PanicStrategy::Abort {
        return;
    }
    debug!("remove_noop_landing_pads({:?})", body);

    RemoveNoopLandingPads.remove_nop_landing_pads(body)
}

impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
        remove_noop_landing_pads(tcx, body);
    }
}

impl RemoveNoopLandingPads {
    fn is_nop_landing_pad(
        &self,
        bb: BasicBlock,
        body: &Body<'_>,
        nop_landing_pads: &BitSet<BasicBlock>,
    ) -> bool {
        for stmt in &body[bb].statements {
            match &stmt.kind {
                StatementKind::FakeRead(..)
                | StatementKind::StorageLive(_)
                | StatementKind::StorageDead(_)
                | StatementKind::AscribeUserType(..)
                | StatementKind::Coverage(..)
                | StatementKind::Nop => {
                    // These are all nops in a landing pad
                }

                StatementKind::Assign(box (place, Rvalue::Use(_))) => {
                    if place.as_local().is_some() {
                        // Writing to a local (e.g., a drop flag) does not
                        // turn a landing pad to a non-nop
                    } else {
                        return false;
                    }
                }

                StatementKind::Assign { .. }
                | StatementKind::SetDiscriminant { .. }
                | StatementKind::LlvmInlineAsm { .. }
                | StatementKind::Retag { .. } => {
                    return false;
                }
            }
        }

        let terminator = body[bb].terminator();
        match terminator.kind {
            TerminatorKind::Goto { .. }
            | TerminatorKind::Resume
            | TerminatorKind::SwitchInt { .. }
            | TerminatorKind::FalseEdge { .. }
            | TerminatorKind::FalseUnwind { .. } => {
                terminator.successors().all(|&succ| nop_landing_pads.contains(succ))
            }
            TerminatorKind::GeneratorDrop
            | TerminatorKind::Yield { .. }
            | TerminatorKind::Return
            | TerminatorKind::Abort
            | TerminatorKind::Unreachable
            | TerminatorKind::Call { .. }
            | TerminatorKind::Assert { .. }
            | TerminatorKind::DropAndReplace { .. }
            | TerminatorKind::Drop { .. }
            | TerminatorKind::InlineAsm { .. } => false,
        }
    }

    fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
        // make sure there's a single resume block
        let resume_block = {
            let patch = MirPatch::new(body);
            let resume_block = patch.resume_block();
            patch.apply(body);
            resume_block
        };
        debug!("remove_noop_landing_pads: resume block is {:?}", resume_block);

        let mut jumps_folded = 0;
        let mut landing_pads_removed = 0;
        let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks().len());

        // This is a post-order traversal, so that if A post-dominates B
        // then A will be visited before B.
        let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect();
        for bb in postorder {
            debug!("  processing {:?}", bb);
            if let Some(unwind) = body[bb].terminator_mut().unwind_mut() {
                if let Some(unwind_bb) = *unwind {
                    if nop_landing_pads.contains(unwind_bb) {
                        debug!("    removing noop landing pad");
                        landing_pads_removed += 1;
                        *unwind = None;
                    }
                }
            }

            for target in body[bb].terminator_mut().successors_mut() {
                if *target != resume_block && nop_landing_pads.contains(*target) {
                    debug!("    folding noop jump to {:?} to resume block", target);
                    *target = resume_block;
                    jumps_folded += 1;
                }
            }

            let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads);
            if is_nop_landing_pad {
                nop_landing_pads.insert(bb);
            }
            debug!("    is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad);
        }

        debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed);
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2017-2018 Sebastian Dröge <sebastian@centricular.com>
//
// 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.
//! Module that contains the basic infrastructure for subclassing `GObject`
use ffi;
use gobject_ffi;

use std::mem;
use std::ops;
use std::ptr;

use translate::*;
use wrapper::Wrapper;
use {IsA, IsClassFor, Object, StaticType, Type};

use super::object::ObjectImpl;

/// A newly registered `glib::Type` that is currently still being initialized
///
/// This allows running additional type-setup functions, e.g. for implementing
/// interfaces on the type
#[derive(Debug, PartialEq, Eq)]
pub struct InitializingType(Type);

impl ops::Deref for InitializingType {
    type Target = Type;

    fn deref(&self) -> &Type {
        &self.0
    }
}

/// Trait implemented by structs that implement a `GObject` C instance struct
///
/// The struct must be `#[repr(C)]` and have the parent type's instance struct
/// as the first field.
///
/// See [`simple::InstanceStruct`] for a basic implementation of this that can
/// be used most of the time and should only not be used if additional fields are
/// required in the instance struct.
///
/// [`simple::InstanceStruct`]: ../simple/struct.InstanceStruct.html
pub unsafe trait InstanceStruct: Sized + 'static {
    /// Corresponding object subclass type for this instance struct
    type Type: ObjectSubclass;

    /// Returns the implementation for from this instance struct, that
    /// is the implementor of [`ObjectImpl`] or subtraits.
    ///
    /// [`ObjectImpl`]: ../object/trait.ObjectImpl.html
    fn get_impl(&self) -> &Self::Type {
        unsafe {
            let data = Self::Type::type_data();
            let private_offset = data.as_ref().private_offset;
            let ptr: *const u8 = self as *const _ as *const u8;
            let priv_ptr = ptr.offset(private_offset);
            let imp = priv_ptr as *const Option<Self::Type>;

            (*imp).as_ref().expect("No private struct")
        }
    }

    /// Returns the class struct for this specific instance
    fn get_class(&self) -> &<Self::Type as ObjectSubclass>::Class {
        unsafe { &**(self as *const _ as *const *const <Self::Type as ObjectSubclass>::Class) }
    }
}

/// Trait implemented by structs that implement a `GObject` C class struct
///
/// The struct must be `#[repr(C)]` and have the parent type's class struct
/// as the first field.
///
/// See [`simple::ClassStruct`] for a basic implementation of this that can
/// be used most of the time and should only not be used if additional fields are
/// required in the class struct, e.g. for declaring new virtual methods.
///
/// [`simple::ClassStruct`]: ../simple/struct.ClassStruct.html
pub unsafe trait ClassStruct: Sized + 'static {
    /// Corresponding object subclass type for this class struct
    type Type: ObjectSubclass;

    fn override_vfuncs(&mut self)
    where
        <<Self::Type as ObjectSubclass>::ParentType as Wrapper>::RustClassType: IsSubclassable<Self::Type>,
    {
        unsafe {
            let base = &mut *(self as *mut _
                as *mut <<Self::Type as ObjectSubclass>::ParentType as Wrapper>::RustClassType);
            base.override_vfuncs();
        }
    }
}

/// Trait for subclassable class structs
pub unsafe trait IsSubclassable<T: ObjectSubclass>: IsClassFor {
    /// Override the virtual methods of this class for the given subclass
    fn override_vfuncs(&mut self);
}

/// Type-specific data that is filled in during type creation
pub struct TypeData {
    #[doc(hidden)]
    pub type_: Type,
    #[doc(hidden)]
    pub parent_class: ffi::gpointer,
    #[doc(hidden)]
    pub interfaces: *const Vec<(ffi::GType, ffi::gpointer)>,
    #[doc(hidden)]
    pub private_offset: isize,
}

unsafe impl Send for TypeData {}
unsafe impl Sync for TypeData {}

impl TypeData {
    /// Returns the type ID
    pub fn get_type(&self) -> Type {
        self.type_
    }

    /// Returns a pointer to the native parent class
    ///
    /// This is used for chaining up to the parent class' implementation
    /// of virtual methods
    pub fn get_parent_class(&self) -> ffi::gpointer {
        self.parent_class
    }

    /// Returns a pointer to the interface implementation
    ///
    /// This is used for calling the interface method implementations
    pub fn get_interface(&self, type_: ffi::GType) -> ffi::gpointer {
        unsafe {
            if self.interfaces.is_null() {
                return ptr::null_mut();
            }

            for &(t, p) in &(*self.interfaces) {
                if t == type_ {
                    return p;
                }
            }

            ptr::null_mut()
        }
    }

    /// Returns the offset of the private struct in bytes relative to the
    /// beginning of the instance struct
    pub fn get_private_offset(&self) -> isize {
        self.private_offset
    }
}

#[macro_export]
/// Macro for boilerplate of [`ObjectSubclass`] implementations
///
/// [`ObjectSubclass`]: subclass/types/trait.ObjectSubclass.html
macro_rules! glib_object_subclass {
    () => {
        fn type_data() -> ::std::ptr::NonNull<$crate::subclass::TypeData> {
            static mut DATA: $crate::subclass::TypeData = $crate::subclass::TypeData {
                type_: $crate::Type::Invalid,
                parent_class: ::std::ptr::null_mut(),
                interfaces: ::std::ptr::null_mut(),
                private_offset: 0,
            };

            unsafe { ::std::ptr::NonNull::new_unchecked(&mut DATA) }
        }
    };
}

/// The central trait for subclassing a `GObject` type
///
/// Links together the type name, parent type and the instance and
/// class structs for type registration and allows subclasses to
/// hook into various steps of the type registration and initialization.
///
/// See [`register_type`] for registering an implementation of this trait
/// with the type system.
///
/// [`register_type`]: fn.register_type.html
pub trait ObjectSubclass: ObjectImpl + Sized + 'static {
    /// `GObject` type name.
    ///
    /// This must be unique in the whole process.
    const NAME: &'static str;

    /// Parent Rust type to inherit from
    type ParentType: IsA<Object> + FromGlibPtrBorrow<*mut <Self::ParentType as Wrapper>::GlibType>;

    /// The C instance struct
    ///
    /// See [`simple::InstanceStruct`] for an basic instance struct that should be
    /// used in most cases
    ///
    /// [`simple::InstanceStruct`]: ../simple/struct.InstanceStruct.html
    // TODO: Should default to simple::InstanceStruct<Self> once associated
    // type defaults are stabilized https://github.com/rust-lang/rust/issues/29661
    type Instance: InstanceStruct<Type = Self>;

    /// The C class struct
    ///
    /// See [`simple::ClassStruct`] for an basic instance struct that should be
    /// used in most cases
    ///
    /// [`simple::ClassStruct`]: ../simple/struct.ClassStruct.html
    // TODO: Should default to simple::ClassStruct<Self> once associated
    // type defaults are stabilized https://github.com/rust-lang/rust/issues/29661
    type Class: ClassStruct<Type = Self>;

    /// Storage for the type-specific data used during registration
    ///
    /// This is usually generated by the [`object_subclass!`] macro.
    ///
    /// [`object_subclass!`]: ../../macro.glib_object_subclass.html
    fn type_data() -> ptr::NonNull<TypeData>;

    /// Returns the `glib::Type` ID of the subclass
    ///
    /// This will panic if called before the type was registered at
    /// runtime with the `GObject` type system.
    fn static_type() -> Type {
        unsafe {
            let data = Self::type_data();
            let type_ = data.as_ref().get_type();
            assert_ne!(type_, Type::Invalid);

            type_
        }
    }

    /// Additional type initialization
    ///
    /// This is called right after the type was registered and allows
    /// subclasses to do additional type-specific initialization, e.g.
    /// for implementing `GObject` interfaces.
    ///
    /// Optional
    fn type_init(_type_: &InitializingType) {}

    /// Class initialization
    ///
    /// This is called after `type_init` and before the first instance
    /// of the subclass is created. Subclasses can use this to do class-
    /// specific initialization, e.g. for installing properties or signals
    /// on the class or calling class methods.
    ///
    /// Optional
    fn class_init(_klass: &mut Self::Class) {}

    /// Constructor
    ///
    /// This is called during object instantiation before further subclasses
    /// are initialized, and should return a new instance of the subclass
    /// private struct.
    fn new(obj: &Self::ParentType) -> Self;
}

unsafe extern "C" fn class_init<T: ObjectSubclass>(
    klass: ffi::gpointer,
    _klass_data: ffi::gpointer,
) {
    let mut data = T::type_data();

    // We have to update the private struct offset once the class is actually
    // being initialized
    {
        let mut private_offset = data.as_ref().private_offset as i32;
        gobject_ffi::g_type_class_adjust_private_offset(klass, &mut private_offset);
        (*data.as_mut()).private_offset = private_offset as isize;
    }

    // Set trampolines for the basic GObject virtual methods
    {
        let gobject_klass = &mut *(klass as *mut gobject_ffi::GObjectClass);

        gobject_klass.finalize = Some(finalize::<T>);
    }

    // And finally peek the parent class struct (containing the parent class'
    // implementations of virtual methods for chaining up), and call the subclass'
    // class initialization function
    {
        let klass = &mut *(klass as *mut T::Class);
        let parent_class = gobject_ffi::g_type_class_peek_parent(klass as *mut _ as ffi::gpointer)
            as *mut <T::ParentType as Wrapper>::GlibClassType;
        assert!(!parent_class.is_null());

        (*data.as_mut()).parent_class = parent_class as ffi::gpointer;

        T::class_init(klass);
    }
}

unsafe extern "C" fn instance_init<T: ObjectSubclass>(
    obj: *mut gobject_ffi::GTypeInstance,
    _klass: ffi::gpointer,
) {
    glib_floating_reference_guard!(obj);
    let rs_instance: T::ParentType =
        from_glib_borrow(obj as *mut <T::ParentType as Wrapper>::GlibType);

    // Get offset to the storage of our private struct, create it
    // and actually store it in that place
    let mut data = T::type_data();
    let private_offset = (*data.as_mut()).private_offset;
    let ptr: *mut u8 = obj as *mut _ as *mut u8;
    let priv_ptr = ptr.offset(private_offset);
    let imp_storage = priv_ptr as *mut Option<T>;

    let imp = T::new(&rs_instance);

    ptr::write(imp_storage, Some(imp));
}

unsafe extern "C" fn finalize<T: ObjectSubclass>(obj: *mut gobject_ffi::GObject) {
    glib_floating_reference_guard!(obj);

    // Retrieve the private struct, take it out of its storage and
    // drop it for freeing all associated memory
    let mut data = T::type_data();
    let private_offset = (*data.as_mut()).private_offset;
    let ptr: *mut u8 = obj as *mut _ as *mut u8;
    let priv_ptr = ptr.offset(private_offset);
    let imp_storage = priv_ptr as *mut Option<T>;

    let imp = (*imp_storage).take().expect("No private struct");
    drop(imp);

    // Chain up to the parent class' finalize implementation, if any
    let parent_class = &*(data.as_ref().get_parent_class() as *const gobject_ffi::GObjectClass);
    if let Some(ref func) = parent_class.finalize {
        func(obj);
    }
}

#[macro_export]
/// Macro for defining a `get_type` function
///
/// This returns a `glib::Type` and registers `Self` via [`register_type`]
/// the first time it is called.
///
/// [`register_type`]: subclass/types/fn.register_type.html
macro_rules! glib_object_get_type {
    () => {
        pub fn get_type() -> $crate::Type {
            use std::sync::Once;
            static ONCE: Once = Once::new();

            ONCE.call_once(|| {
                $crate::subclass::register_type::<Self>();
            });

            Self::static_type()
        }
    };
}

/// Register a `glib::Type` ID for `T`
///
/// This must be called only once and will panic on a second call.
///
/// See [`object_get_type!`] for defining a function that ensures that
/// this is only called once and returns the type id.
///
/// [`object_get_type!`]: ../../macro.glib_object_get_type.html
pub fn register_type<T: ObjectSubclass>() -> Type {
    unsafe {
        use std::ffi::CString;

        let type_info = gobject_ffi::GTypeInfo {
            class_size: mem::size_of::<T::Class>() as u16,
            base_init: None,
            base_finalize: None,
            class_init: Some(class_init::<T>),
            class_finalize: None,
            class_data: ptr::null_mut(),
            instance_size: mem::size_of::<T::Instance>() as u16,
            n_preallocs: 0,
            instance_init: Some(instance_init::<T>),
            value_table: ptr::null(),
        };

        let type_name = CString::new(T::NAME).unwrap();
        assert_eq!(
            gobject_ffi::g_type_from_name(type_name.as_ptr()),
            gobject_ffi::G_TYPE_INVALID
        );

        let type_ = from_glib(gobject_ffi::g_type_register_static(
            <T::ParentType as StaticType>::static_type().to_glib(),
            type_name.as_ptr(),
            &type_info,
            0,
        ));

        let mut data = T::type_data();
        (*data.as_mut()).type_ = type_;
        let private_offset =
            gobject_ffi::g_type_add_instance_private(type_.to_glib(), mem::size_of::<Option<T>>());
        (*data.as_mut()).private_offset = private_offset as isize;

        T::type_init(&InitializingType(type_));

        type_
    }
}
<commit_msg>Don't use floating reference guard for finalize<commit_after>// Copyright (C) 2017-2018 Sebastian Dröge <sebastian@centricular.com>
//
// 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.
//! Module that contains the basic infrastructure for subclassing `GObject`
use ffi;
use gobject_ffi;

use std::mem;
use std::ops;
use std::ptr;

use translate::*;
use wrapper::Wrapper;
use {IsA, IsClassFor, Object, StaticType, Type};

use super::object::ObjectImpl;

/// A newly registered `glib::Type` that is currently still being initialized
///
/// This allows running additional type-setup functions, e.g. for implementing
/// interfaces on the type
#[derive(Debug, PartialEq, Eq)]
pub struct InitializingType(Type);

impl ops::Deref for InitializingType {
    type Target = Type;

    fn deref(&self) -> &Type {
        &self.0
    }
}

/// Trait implemented by structs that implement a `GObject` C instance struct
///
/// The struct must be `#[repr(C)]` and have the parent type's instance struct
/// as the first field.
///
/// See [`simple::InstanceStruct`] for a basic implementation of this that can
/// be used most of the time and should only not be used if additional fields are
/// required in the instance struct.
///
/// [`simple::InstanceStruct`]: ../simple/struct.InstanceStruct.html
pub unsafe trait InstanceStruct: Sized + 'static {
    /// Corresponding object subclass type for this instance struct
    type Type: ObjectSubclass;

    /// Returns the implementation for from this instance struct, that
    /// is the implementor of [`ObjectImpl`] or subtraits.
    ///
    /// [`ObjectImpl`]: ../object/trait.ObjectImpl.html
    fn get_impl(&self) -> &Self::Type {
        unsafe {
            let data = Self::Type::type_data();
            let private_offset = data.as_ref().private_offset;
            let ptr: *const u8 = self as *const _ as *const u8;
            let priv_ptr = ptr.offset(private_offset);
            let imp = priv_ptr as *const Option<Self::Type>;

            (*imp).as_ref().expect("No private struct")
        }
    }

    /// Returns the class struct for this specific instance
    fn get_class(&self) -> &<Self::Type as ObjectSubclass>::Class {
        unsafe { &**(self as *const _ as *const *const <Self::Type as ObjectSubclass>::Class) }
    }
}

/// Trait implemented by structs that implement a `GObject` C class struct
///
/// The struct must be `#[repr(C)]` and have the parent type's class struct
/// as the first field.
///
/// See [`simple::ClassStruct`] for a basic implementation of this that can
/// be used most of the time and should only not be used if additional fields are
/// required in the class struct, e.g. for declaring new virtual methods.
///
/// [`simple::ClassStruct`]: ../simple/struct.ClassStruct.html
pub unsafe trait ClassStruct: Sized + 'static {
    /// Corresponding object subclass type for this class struct
    type Type: ObjectSubclass;

    fn override_vfuncs(&mut self)
    where
        <<Self::Type as ObjectSubclass>::ParentType as Wrapper>::RustClassType: IsSubclassable<Self::Type>,
    {
        unsafe {
            let base = &mut *(self as *mut _
                as *mut <<Self::Type as ObjectSubclass>::ParentType as Wrapper>::RustClassType);
            base.override_vfuncs();
        }
    }
}

/// Trait for subclassable class structs
pub unsafe trait IsSubclassable<T: ObjectSubclass>: IsClassFor {
    /// Override the virtual methods of this class for the given subclass
    fn override_vfuncs(&mut self);
}

/// Type-specific data that is filled in during type creation
pub struct TypeData {
    #[doc(hidden)]
    pub type_: Type,
    #[doc(hidden)]
    pub parent_class: ffi::gpointer,
    #[doc(hidden)]
    pub interfaces: *const Vec<(ffi::GType, ffi::gpointer)>,
    #[doc(hidden)]
    pub private_offset: isize,
}

unsafe impl Send for TypeData {}
unsafe impl Sync for TypeData {}

impl TypeData {
    /// Returns the type ID
    pub fn get_type(&self) -> Type {
        self.type_
    }

    /// Returns a pointer to the native parent class
    ///
    /// This is used for chaining up to the parent class' implementation
    /// of virtual methods
    pub fn get_parent_class(&self) -> ffi::gpointer {
        self.parent_class
    }

    /// Returns a pointer to the interface implementation
    ///
    /// This is used for calling the interface method implementations
    pub fn get_interface(&self, type_: ffi::GType) -> ffi::gpointer {
        unsafe {
            if self.interfaces.is_null() {
                return ptr::null_mut();
            }

            for &(t, p) in &(*self.interfaces) {
                if t == type_ {
                    return p;
                }
            }

            ptr::null_mut()
        }
    }

    /// Returns the offset of the private struct in bytes relative to the
    /// beginning of the instance struct
    pub fn get_private_offset(&self) -> isize {
        self.private_offset
    }
}

#[macro_export]
/// Macro for boilerplate of [`ObjectSubclass`] implementations
///
/// [`ObjectSubclass`]: subclass/types/trait.ObjectSubclass.html
macro_rules! glib_object_subclass {
    () => {
        fn type_data() -> ::std::ptr::NonNull<$crate::subclass::TypeData> {
            static mut DATA: $crate::subclass::TypeData = $crate::subclass::TypeData {
                type_: $crate::Type::Invalid,
                parent_class: ::std::ptr::null_mut(),
                interfaces: ::std::ptr::null_mut(),
                private_offset: 0,
            };

            unsafe { ::std::ptr::NonNull::new_unchecked(&mut DATA) }
        }
    };
}

/// The central trait for subclassing a `GObject` type
///
/// Links together the type name, parent type and the instance and
/// class structs for type registration and allows subclasses to
/// hook into various steps of the type registration and initialization.
///
/// See [`register_type`] for registering an implementation of this trait
/// with the type system.
///
/// [`register_type`]: fn.register_type.html
pub trait ObjectSubclass: ObjectImpl + Sized + 'static {
    /// `GObject` type name.
    ///
    /// This must be unique in the whole process.
    const NAME: &'static str;

    /// Parent Rust type to inherit from
    type ParentType: IsA<Object> + FromGlibPtrBorrow<*mut <Self::ParentType as Wrapper>::GlibType>;

    /// The C instance struct
    ///
    /// See [`simple::InstanceStruct`] for an basic instance struct that should be
    /// used in most cases
    ///
    /// [`simple::InstanceStruct`]: ../simple/struct.InstanceStruct.html
    // TODO: Should default to simple::InstanceStruct<Self> once associated
    // type defaults are stabilized https://github.com/rust-lang/rust/issues/29661
    type Instance: InstanceStruct<Type = Self>;

    /// The C class struct
    ///
    /// See [`simple::ClassStruct`] for an basic instance struct that should be
    /// used in most cases
    ///
    /// [`simple::ClassStruct`]: ../simple/struct.ClassStruct.html
    // TODO: Should default to simple::ClassStruct<Self> once associated
    // type defaults are stabilized https://github.com/rust-lang/rust/issues/29661
    type Class: ClassStruct<Type = Self>;

    /// Storage for the type-specific data used during registration
    ///
    /// This is usually generated by the [`object_subclass!`] macro.
    ///
    /// [`object_subclass!`]: ../../macro.glib_object_subclass.html
    fn type_data() -> ptr::NonNull<TypeData>;

    /// Returns the `glib::Type` ID of the subclass
    ///
    /// This will panic if called before the type was registered at
    /// runtime with the `GObject` type system.
    fn static_type() -> Type {
        unsafe {
            let data = Self::type_data();
            let type_ = data.as_ref().get_type();
            assert_ne!(type_, Type::Invalid);

            type_
        }
    }

    /// Additional type initialization
    ///
    /// This is called right after the type was registered and allows
    /// subclasses to do additional type-specific initialization, e.g.
    /// for implementing `GObject` interfaces.
    ///
    /// Optional
    fn type_init(_type_: &InitializingType) {}

    /// Class initialization
    ///
    /// This is called after `type_init` and before the first instance
    /// of the subclass is created. Subclasses can use this to do class-
    /// specific initialization, e.g. for installing properties or signals
    /// on the class or calling class methods.
    ///
    /// Optional
    fn class_init(_klass: &mut Self::Class) {}

    /// Constructor
    ///
    /// This is called during object instantiation before further subclasses
    /// are initialized, and should return a new instance of the subclass
    /// private struct.
    fn new(obj: &Self::ParentType) -> Self;
}

unsafe extern "C" fn class_init<T: ObjectSubclass>(
    klass: ffi::gpointer,
    _klass_data: ffi::gpointer,
) {
    let mut data = T::type_data();

    // We have to update the private struct offset once the class is actually
    // being initialized
    {
        let mut private_offset = data.as_ref().private_offset as i32;
        gobject_ffi::g_type_class_adjust_private_offset(klass, &mut private_offset);
        (*data.as_mut()).private_offset = private_offset as isize;
    }

    // Set trampolines for the basic GObject virtual methods
    {
        let gobject_klass = &mut *(klass as *mut gobject_ffi::GObjectClass);

        gobject_klass.finalize = Some(finalize::<T>);
    }

    // And finally peek the parent class struct (containing the parent class'
    // implementations of virtual methods for chaining up), and call the subclass'
    // class initialization function
    {
        let klass = &mut *(klass as *mut T::Class);
        let parent_class = gobject_ffi::g_type_class_peek_parent(klass as *mut _ as ffi::gpointer)
            as *mut <T::ParentType as Wrapper>::GlibClassType;
        assert!(!parent_class.is_null());

        (*data.as_mut()).parent_class = parent_class as ffi::gpointer;

        T::class_init(klass);
    }
}

unsafe extern "C" fn instance_init<T: ObjectSubclass>(
    obj: *mut gobject_ffi::GTypeInstance,
    _klass: ffi::gpointer,
) {
    glib_floating_reference_guard!(obj);
    let rs_instance: T::ParentType =
        from_glib_borrow(obj as *mut <T::ParentType as Wrapper>::GlibType);

    // Get offset to the storage of our private struct, create it
    // and actually store it in that place
    let mut data = T::type_data();
    let private_offset = (*data.as_mut()).private_offset;
    let ptr: *mut u8 = obj as *mut _ as *mut u8;
    let priv_ptr = ptr.offset(private_offset);
    let imp_storage = priv_ptr as *mut Option<T>;

    let imp = T::new(&rs_instance);

    ptr::write(imp_storage, Some(imp));
}

unsafe extern "C" fn finalize<T: ObjectSubclass>(obj: *mut gobject_ffi::GObject) {
    // Retrieve the private struct, take it out of its storage and
    // drop it for freeing all associated memory
    let mut data = T::type_data();
    let private_offset = (*data.as_mut()).private_offset;
    let ptr: *mut u8 = obj as *mut _ as *mut u8;
    let priv_ptr = ptr.offset(private_offset);
    let imp_storage = priv_ptr as *mut Option<T>;

    let imp = (*imp_storage).take().expect("No private struct");
    drop(imp);

    // Chain up to the parent class' finalize implementation, if any
    let parent_class = &*(data.as_ref().get_parent_class() as *const gobject_ffi::GObjectClass);
    if let Some(ref func) = parent_class.finalize {
        func(obj);
    }
}

#[macro_export]
/// Macro for defining a `get_type` function
///
/// This returns a `glib::Type` and registers `Self` via [`register_type`]
/// the first time it is called.
///
/// [`register_type`]: subclass/types/fn.register_type.html
macro_rules! glib_object_get_type {
    () => {
        pub fn get_type() -> $crate::Type {
            use std::sync::Once;
            static ONCE: Once = Once::new();

            ONCE.call_once(|| {
                $crate::subclass::register_type::<Self>();
            });

            Self::static_type()
        }
    };
}

/// Register a `glib::Type` ID for `T`
///
/// This must be called only once and will panic on a second call.
///
/// See [`object_get_type!`] for defining a function that ensures that
/// this is only called once and returns the type id.
///
/// [`object_get_type!`]: ../../macro.glib_object_get_type.html
pub fn register_type<T: ObjectSubclass>() -> Type {
    unsafe {
        use std::ffi::CString;

        let type_info = gobject_ffi::GTypeInfo {
            class_size: mem::size_of::<T::Class>() as u16,
            base_init: None,
            base_finalize: None,
            class_init: Some(class_init::<T>),
            class_finalize: None,
            class_data: ptr::null_mut(),
            instance_size: mem::size_of::<T::Instance>() as u16,
            n_preallocs: 0,
            instance_init: Some(instance_init::<T>),
            value_table: ptr::null(),
        };

        let type_name = CString::new(T::NAME).unwrap();
        assert_eq!(
            gobject_ffi::g_type_from_name(type_name.as_ptr()),
            gobject_ffi::G_TYPE_INVALID
        );

        let type_ = from_glib(gobject_ffi::g_type_register_static(
            <T::ParentType as StaticType>::static_type().to_glib(),
            type_name.as_ptr(),
            &type_info,
            0,
        ));

        let mut data = T::type_data();
        (*data.as_mut()).type_ = type_;
        let private_offset =
            gobject_ffi::g_type_add_instance_private(type_.to_glib(), mem::size_of::<Option<T>>());
        (*data.as_mut()).private_offset = private_offset as isize;

        T::type_init(&InitializingType(type_));

        type_
    }
}
<|endoftext|>


<commit_before>use cocoa::base::id;

pub struct ParallelRenderCommandEncoder(id);

impl_from_into_raw!(ParallelRenderCommandEncoder, of protocol "MTLRenderCommandEncoder");
<commit_msg>Actually implement ParallelRenderCommandEncoder<commit_after>use cocoa::base::id;
use std::mem;
use std::ops::{Deref, DerefMut};
use {CommandEncoder, StoreAction, RenderCommandEncoder};

#[derive(Debug)]
pub struct ParallelRenderCommandEncoder(id);

unsafe impl Send for ParallelRenderCommandEncoder {}

impl Deref for ParallelRenderCommandEncoder {
    type Target = CommandEncoder;
    fn deref(&self) -> &Self::Target {
        unsafe { mem::transmute(&self.0) }
    }
}

impl DerefMut for ParallelRenderCommandEncoder {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { mem::transmute(&mut self.0) }
    }
}

impl ParallelRenderCommandEncoder {
    pub fn render_command_encoder(&self) -> RenderCommandEncoder {
        unimplemented!()
    }

    pub fn set_color_store_action_at(&self, store_action: StoreAction, index: usize) {
        unimplemented!()
    }

    pub fn set_depth_store_action(self, store_action: StoreAction) {
        unimplemented!()
    }

    pub fn set_stencil_store_action(self, store_action: StoreAction) {
        unimplemented!()
    }
}

impl_from_into_raw!(ParallelRenderCommandEncoder, of protocol "MTLRenderCommandEncoder");
<|endoftext|>


<commit_before>use std::borrow::ToOwned;
use std::process;

use workdir::Workdir;

macro_rules! stats_tests {
    ($name:ident, $field:expr, $rows:expr, $expect:expr) => (
        stats_tests!($name, $field, $rows, $expect, false);
    );
    ($name:ident, $field:expr, $rows:expr, $expect:expr, $nulls:expr) => (
        mod $name {
            use super::test_stats;

            stats_test_headers!($name, $field, $rows, $expect, $nulls);
            stats_test_no_headers!($name, $field, $rows, $expect, $nulls);
        }
    );
}

macro_rules! stats_test_headers {
    ($name:ident, $field:expr, $rows:expr, $expect:expr) => (
        stats_test_headers!($name, $field, $rows, $expect, false);
    );
    ($name:ident, $field:expr, $rows:expr, $expect:expr, $nulls:expr) => (
        #[test]
        fn headers_no_index() {
            let name = concat!(stringify!($name), "_headers_no_index");
            test_stats(name, $field, $rows, $expect, true, false, $nulls);
        }

        #[test]
        fn headers_index() {
            let name = concat!(stringify!($name), "_headers_index");
            test_stats(name, $field, $rows, $expect, true, true, $nulls);
        }
    );
}

macro_rules! stats_test_no_headers {
    ($name:ident, $field:expr, $rows:expr, $expect:expr) => (
        stats_test_no_headers!($name, $field, $rows, $expect, false);
    );
    ($name:ident, $field:expr, $rows:expr, $expect:expr, $nulls:expr) => (
        #[test]
        fn no_headers_no_index() {
            let name = concat!(stringify!($name), "_no_headers_no_index");
            test_stats(name, $field, $rows, $expect, false, false, $nulls);
        }

        #[test]
        fn no_headers_index() {
            let name = concat!(stringify!($name), "_no_headers_index");
            test_stats(name, $field, $rows, $expect, false, true, $nulls);
        }
    );
}

fn test_stats<S>(name: S, field: &str, rows: &[&str], expected: &str,
                 headers: bool, use_index: bool, nulls: bool)
        where S: ::std::ops::Deref<Target=str> {
    let (wrk, mut cmd) = setup(name, rows, headers, use_index, nulls);
    let field_val = get_field_value(&wrk, &mut cmd, field);
    assert_eq!(field_val, expected.to_owned());
}

fn setup<S>(name: S, rows: &[&str], headers: bool,
            use_index: bool, nulls: bool) -> (Workdir, process::Command)
        where S: ::std::ops::Deref<Target=str> {
    let wrk = Workdir::new(&name);
    let mut data: Vec<Vec<String>> =
        rows.iter().map(|&s| vec![s.to_owned()]).collect();
    if headers { data.insert(0, svec!["header"]); }
    if use_index {
        wrk.create_indexed("in.csv", data);
    } else {
        wrk.create("in.csv", data);
    }

    let mut cmd = wrk.command("stats");
    cmd.arg("in.csv");
    if !headers { cmd.arg("--no-headers"); }
    if nulls { cmd.arg("--nulls"); }

    (wrk, cmd)
}

fn get_field_value(wrk: &Workdir, cmd: &mut process::Command, field: &str)
                  -> String {
    if field == "median" { cmd.arg("--median"); }
    if field == "cardinality" { cmd.arg("--cardinality"); }
    if field == "mode" { cmd.arg("--mode"); }

    let mut rows: Vec<Vec<String>> = wrk.read_stdout(cmd);
    let headers = rows.remove(0);
    for row in rows.iter() {
        for (h, val) in headers.iter().zip(row.iter()) {
            if &**h == field {
                return val.clone();
            }
        }
    }
    panic!("BUG: Could not find field '{}' in headers '{:?}' \
            for command '{:?}'.", field, headers, cmd);
}

stats_tests!(stats_infer_unicode, "type", &["a"], "Unicode");
stats_tests!(stats_infer_int, "type", &["1"], "Integer");
stats_tests!(stats_infer_float, "type", &["1.2"], "Float");
stats_tests!(stats_infer_null, "type", &[""], "NULL");
stats_tests!(stats_infer_unicode_null, "type", &["a", ""], "Unicode");
stats_tests!(stats_infer_int_null, "type", &["1", ""], "Integer");
stats_tests!(stats_infer_float_null, "type", &["1.2", ""], "Float");
stats_tests!(stats_infer_null_unicode, "type", &["", "a"], "Unicode");
stats_tests!(stats_infer_null_int, "type", &["", "1"], "Integer");
stats_tests!(stats_infer_null_float, "type", &["", "1.2"], "Float");
stats_tests!(stats_infer_int_unicode, "type", &["1", "a"], "Unicode");
stats_tests!(stats_infer_unicode_int, "type", &["a", "1"], "Unicode");
stats_tests!(stats_infer_int_float, "type", &["1", "1.2"], "Float");
stats_tests!(stats_infer_float_int, "type", &["1.2", "1"], "Float");
stats_tests!(stats_infer_null_int_float_unicode, "type",
             &["", "1", "1.2", "a"], "Unicode");

stats_tests!(stats_no_mean, "mean", &["a"], "");
stats_tests!(stats_no_stddev, "stddev", &["a"], "");
stats_tests!(stats_no_median, "median", &["a"], "");
stats_tests!(stats_no_mode, "mode", &["a", "b"], "N/A");

stats_tests!(stats_null_mean, "mean", &[""], "");
stats_tests!(stats_null_stddev, "stddev", &[""], "");
stats_tests!(stats_null_median, "median", &[""], "");
stats_tests!(stats_null_mode, "mode", &[""], "N/A");

stats_tests!(stats_includenulls_null_mean, "mean", &[""], "", true);
stats_tests!(stats_includenulls_null_stddev, "stddev", &[""], "", true);
stats_tests!(stats_includenulls_null_median, "median", &[""], "", true);
stats_tests!(stats_includenulls_null_mode, "mode", &[""], "N/A", true);

stats_tests!(stats_includenulls_mean,
             "mean", &["5", "", "15", "10"], "7.5", true);

stats_tests!(stats_min, "min", &["2", "1.1"], "1.1");
stats_tests!(stats_max, "max", &["2", "1.1"], "2");
stats_tests!(stats_min_mix, "min", &["2", "a", "1.1"], "1.1");
stats_tests!(stats_max_mix, "max", &["2", "a", "1.1"], "a");
stats_tests!(stats_min_null, "min", &["", "2", "1.1"], "1.1");
stats_tests!(stats_max_null, "max", &["2", "1.1", ""], "2");

stats_tests!(stats_len_min, "min_length", &["aa", "a"], "1");
stats_tests!(stats_len_max, "max_length", &["a", "aa"], "2");
stats_tests!(stats_len_min_null, "min_length", &["", "aa", "a"], "0");
stats_tests!(stats_len_max_null, "max_length", &["a", "aa", ""], "2");

stats_tests!(stats_mean, "mean", &["5", "15", "10"], "10");
stats_tests!(stats_stddev, "stddev", &["1", "2", "3"], "0.816496580927726");
stats_tests!(stats_mean_null, "mean", &["", "5", "15", "10"], "10");
stats_tests!(stats_stddev_null, "stddev", &["1", "2", "3", ""],
             "0.816496580927726");
stats_tests!(stats_mean_mix, "mean", &["5", "15.1", "9.9"], "10");
stats_tests!(stats_stddev_mix, "stddev", &["1", "2.1", "2.9"],
             "0.7788880963698614");

stats_tests!(stats_cardinality, "cardinality", &["a", "b", "a"], "2");
stats_tests!(stats_mode, "mode", &["a", "b", "a"], "a");
stats_tests!(stats_mode_null, "mode", &["", "a", "b", "a"], "a");
stats_tests!(stats_median, "median", &["1", "2", "3"], "2");
stats_tests!(stats_median_null, "median", &["", "1", "2", "3"], "2");
stats_tests!(stats_median_even, "median", &["1", "2", "3", "4"], "2.5");
stats_tests!(stats_median_even_null, "median",
             &["", "1", "2", "3", "4"], "2.5");
stats_tests!(stats_median_mix, "median", &["1", "2.5", "3"], "2.5");

mod stats_infer_nothing {
    // Only test CSV data with headers.
    // Empty CSV data with no headers won't produce any statistical analysis.
    use super::test_stats;
    stats_test_headers!(stats_infer_nothing, "type", &[], "NULL");
}

mod stats_zero_cardinality {
    use super::test_stats;
    stats_test_headers!(stats_zero_cardinality, "cardinality", &[], "0");
}

mod stats_zero_mode {
    use super::test_stats;
    stats_test_headers!(stats_zero_mode, "mode", &[], "N/A");
}

mod stats_zero_mean {
    use super::test_stats;
    stats_test_headers!(stats_zero_mean, "mean", &[], "");
}

mod stats_zero_median {
    use super::test_stats;
    stats_test_headers!(stats_zero_median, "median", &[], "");
}

mod stats_header_fields {
    use super::test_stats;
    stats_test_headers!(stats_header_field_name, "field", &["a"], "header");
    stats_test_no_headers!(stats_header_no_field_name, "field", &["a"], "0");
}
<commit_msg>Be more liberal when comparing statistical values.<commit_after>use std::borrow::ToOwned;
use std::cmp;
use std::process;

use workdir::Workdir;

macro_rules! stats_tests {
    ($name:ident, $field:expr, $rows:expr, $expect:expr) => (
        stats_tests!($name, $field, $rows, $expect, false);
    );
    ($name:ident, $field:expr, $rows:expr, $expect:expr, $nulls:expr) => (
        mod $name {
            use super::test_stats;

            stats_test_headers!($name, $field, $rows, $expect, $nulls);
            stats_test_no_headers!($name, $field, $rows, $expect, $nulls);
        }
    );
}

macro_rules! stats_test_headers {
    ($name:ident, $field:expr, $rows:expr, $expect:expr) => (
        stats_test_headers!($name, $field, $rows, $expect, false);
    );
    ($name:ident, $field:expr, $rows:expr, $expect:expr, $nulls:expr) => (
        #[test]
        fn headers_no_index() {
            let name = concat!(stringify!($name), "_headers_no_index");
            test_stats(name, $field, $rows, $expect, true, false, $nulls);
        }

        #[test]
        fn headers_index() {
            let name = concat!(stringify!($name), "_headers_index");
            test_stats(name, $field, $rows, $expect, true, true, $nulls);
        }
    );
}

macro_rules! stats_test_no_headers {
    ($name:ident, $field:expr, $rows:expr, $expect:expr) => (
        stats_test_no_headers!($name, $field, $rows, $expect, false);
    );
    ($name:ident, $field:expr, $rows:expr, $expect:expr, $nulls:expr) => (
        #[test]
        fn no_headers_no_index() {
            let name = concat!(stringify!($name), "_no_headers_no_index");
            test_stats(name, $field, $rows, $expect, false, false, $nulls);
        }

        #[test]
        fn no_headers_index() {
            let name = concat!(stringify!($name), "_no_headers_index");
            test_stats(name, $field, $rows, $expect, false, true, $nulls);
        }
    );
}

fn test_stats<S>(name: S, field: &str, rows: &[&str], expected: &str,
                 headers: bool, use_index: bool, nulls: bool)
        where S: ::std::ops::Deref<Target=str> {
    let (wrk, mut cmd) = setup(name, rows, headers, use_index, nulls);
    let field_val = get_field_value(&wrk, &mut cmd, field);
    // Only compare the first few bytes since floating point arithmetic
    // can mess with exact comparisons.
    let len = cmp::min(10, cmp::min(field_val.len(), expected.len()));
    assert_eq!(&field_val[0..len], &expected[0..len]);
}

fn setup<S>(name: S, rows: &[&str], headers: bool,
            use_index: bool, nulls: bool) -> (Workdir, process::Command)
        where S: ::std::ops::Deref<Target=str> {
    let wrk = Workdir::new(&name);
    let mut data: Vec<Vec<String>> =
        rows.iter().map(|&s| vec![s.to_owned()]).collect();
    if headers { data.insert(0, svec!["header"]); }
    if use_index {
        wrk.create_indexed("in.csv", data);
    } else {
        wrk.create("in.csv", data);
    }

    let mut cmd = wrk.command("stats");
    cmd.arg("in.csv");
    if !headers { cmd.arg("--no-headers"); }
    if nulls { cmd.arg("--nulls"); }

    (wrk, cmd)
}

fn get_field_value(wrk: &Workdir, cmd: &mut process::Command, field: &str)
                  -> String {
    if field == "median" { cmd.arg("--median"); }
    if field == "cardinality" { cmd.arg("--cardinality"); }
    if field == "mode" { cmd.arg("--mode"); }

    let mut rows: Vec<Vec<String>> = wrk.read_stdout(cmd);
    let headers = rows.remove(0);
    for row in rows.iter() {
        for (h, val) in headers.iter().zip(row.iter()) {
            if &**h == field {
                return val.clone();
            }
        }
    }
    panic!("BUG: Could not find field '{}' in headers '{:?}' \
            for command '{:?}'.", field, headers, cmd);
}

stats_tests!(stats_infer_unicode, "type", &["a"], "Unicode");
stats_tests!(stats_infer_int, "type", &["1"], "Integer");
stats_tests!(stats_infer_float, "type", &["1.2"], "Float");
stats_tests!(stats_infer_null, "type", &[""], "NULL");
stats_tests!(stats_infer_unicode_null, "type", &["a", ""], "Unicode");
stats_tests!(stats_infer_int_null, "type", &["1", ""], "Integer");
stats_tests!(stats_infer_float_null, "type", &["1.2", ""], "Float");
stats_tests!(stats_infer_null_unicode, "type", &["", "a"], "Unicode");
stats_tests!(stats_infer_null_int, "type", &["", "1"], "Integer");
stats_tests!(stats_infer_null_float, "type", &["", "1.2"], "Float");
stats_tests!(stats_infer_int_unicode, "type", &["1", "a"], "Unicode");
stats_tests!(stats_infer_unicode_int, "type", &["a", "1"], "Unicode");
stats_tests!(stats_infer_int_float, "type", &["1", "1.2"], "Float");
stats_tests!(stats_infer_float_int, "type", &["1.2", "1"], "Float");
stats_tests!(stats_infer_null_int_float_unicode, "type",
             &["", "1", "1.2", "a"], "Unicode");

stats_tests!(stats_no_mean, "mean", &["a"], "");
stats_tests!(stats_no_stddev, "stddev", &["a"], "");
stats_tests!(stats_no_median, "median", &["a"], "");
stats_tests!(stats_no_mode, "mode", &["a", "b"], "N/A");

stats_tests!(stats_null_mean, "mean", &[""], "");
stats_tests!(stats_null_stddev, "stddev", &[""], "");
stats_tests!(stats_null_median, "median", &[""], "");
stats_tests!(stats_null_mode, "mode", &[""], "N/A");

stats_tests!(stats_includenulls_null_mean, "mean", &[""], "", true);
stats_tests!(stats_includenulls_null_stddev, "stddev", &[""], "", true);
stats_tests!(stats_includenulls_null_median, "median", &[""], "", true);
stats_tests!(stats_includenulls_null_mode, "mode", &[""], "N/A", true);

stats_tests!(stats_includenulls_mean,
             "mean", &["5", "", "15", "10"], "7.5", true);

stats_tests!(stats_min, "min", &["2", "1.1"], "1.1");
stats_tests!(stats_max, "max", &["2", "1.1"], "2");
stats_tests!(stats_min_mix, "min", &["2", "a", "1.1"], "1.1");
stats_tests!(stats_max_mix, "max", &["2", "a", "1.1"], "a");
stats_tests!(stats_min_null, "min", &["", "2", "1.1"], "1.1");
stats_tests!(stats_max_null, "max", &["2", "1.1", ""], "2");

stats_tests!(stats_len_min, "min_length", &["aa", "a"], "1");
stats_tests!(stats_len_max, "max_length", &["a", "aa"], "2");
stats_tests!(stats_len_min_null, "min_length", &["", "aa", "a"], "0");
stats_tests!(stats_len_max_null, "max_length", &["a", "aa", ""], "2");

stats_tests!(stats_mean, "mean", &["5", "15", "10"], "10");
stats_tests!(stats_stddev, "stddev", &["1", "2", "3"], "0.816496580927726");
stats_tests!(stats_mean_null, "mean", &["", "5", "15", "10"], "10");
stats_tests!(stats_stddev_null, "stddev", &["1", "2", "3", ""],
             "0.816496580927726");
stats_tests!(stats_mean_mix, "mean", &["5", "15.1", "9.9"], "10");
stats_tests!(stats_stddev_mix, "stddev", &["1", "2.1", "2.9"],
             "0.7788880963698614");

stats_tests!(stats_cardinality, "cardinality", &["a", "b", "a"], "2");
stats_tests!(stats_mode, "mode", &["a", "b", "a"], "a");
stats_tests!(stats_mode_null, "mode", &["", "a", "b", "a"], "a");
stats_tests!(stats_median, "median", &["1", "2", "3"], "2");
stats_tests!(stats_median_null, "median", &["", "1", "2", "3"], "2");
stats_tests!(stats_median_even, "median", &["1", "2", "3", "4"], "2.5");
stats_tests!(stats_median_even_null, "median",
             &["", "1", "2", "3", "4"], "2.5");
stats_tests!(stats_median_mix, "median", &["1", "2.5", "3"], "2.5");

mod stats_infer_nothing {
    // Only test CSV data with headers.
    // Empty CSV data with no headers won't produce any statistical analysis.
    use super::test_stats;
    stats_test_headers!(stats_infer_nothing, "type", &[], "NULL");
}

mod stats_zero_cardinality {
    use super::test_stats;
    stats_test_headers!(stats_zero_cardinality, "cardinality", &[], "0");
}

mod stats_zero_mode {
    use super::test_stats;
    stats_test_headers!(stats_zero_mode, "mode", &[], "N/A");
}

mod stats_zero_mean {
    use super::test_stats;
    stats_test_headers!(stats_zero_mean, "mean", &[], "");
}

mod stats_zero_median {
    use super::test_stats;
    stats_test_headers!(stats_zero_median, "median", &[], "");
}

mod stats_header_fields {
    use super::test_stats;
    stats_test_headers!(stats_header_field_name, "field", &["a"], "header");
    stats_test_no_headers!(stats_header_no_field_name, "field", &["a"], "0");
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate tempfile;
#[macro_use]
extern crate wayland_client;
extern crate wayland_protocols;
extern crate wayland_window;

use byteorder::{NativeEndian, WriteBytesExt};
use std::cmp;
use std::fs::File;
use std::io::{Seek, SeekFrom, Write};
use std::os::unix::io::AsRawFd;
use tempfile::tempfile;
use wayland_client::{EnvHandler, Proxy, StateToken};
use wayland_client::protocol::{wl_buffer, wl_compositor, wl_shell, wl_shm, wl_shm_pool, wl_subcompositor,
                               wl_surface};
use wayland_protocols::unstable::xdg_shell::v6::client::zxdg_shell_v6::{self, ZxdgShellV6};
use wayland_window::create_frame;

wayland_env!(
    WaylandEnv,
    compositor: wl_compositor::WlCompositor,
    subcompositor: wl_subcompositor::WlSubcompositor,
    shm: wl_shm::WlShm
);

struct Window {
    s: wl_surface::WlSurface,
    tmp: File,
    pool: wl_shm_pool::WlShmPool,
    pool_size: usize,
    buf: wl_buffer::WlBuffer,
    newsize: Option<(i32, i32)>,
    closed: bool,
    refresh: bool,
}

fn window_implementation() -> wayland_window::FrameImplementation<StateToken<Window>> {
    wayland_window::FrameImplementation {
        configure: |evqh, token, config, newsize| {
            if let Some((w, h)) = newsize {
                println!("configure newsize: {:?}", (w, h));
                evqh.state().get_mut(token).newsize = Some((w, h))
            }
            println!("configure metadata: {:?}", config);
            evqh.state().get_mut(token).refresh = true;
        },
        close: |evqh, token| {
            println!("close window");
            evqh.state().get_mut(token).closed = true;
        },
        refresh: |evqh, token| {
            evqh.state().get_mut(token).refresh = true;
        },
    }
}

impl Window {
    fn new(surface: wl_surface::WlSurface, shm: &wl_shm::WlShm) -> Window {
        // create a tempfile to write the contents of the window on
        let mut tmp = tempfile().ok().expect("Unable to create a tempfile.");
        // write the contents to it, lets put everything in dark red
        for _ in 0..16 {
            let _ = tmp.write_u32::<NativeEndian>(0xFF880000);
        }
        let _ = tmp.flush();
        let pool = shm.create_pool(tmp.as_raw_fd(), 64);
        let buffer = pool.create_buffer(0, 4, 4, 16, wl_shm::Format::Argb8888)
            .expect("I didn't destroy the pool!");
        Window {
            s: surface,
            tmp: tmp,
            pool: pool,
            pool_size: 64,
            buf: buffer,
            newsize: Some((200, 150)),
            closed: false,
            refresh: false,
        }
    }
    fn resize(&mut self, width: i32, height: i32) {
        // write the contents to it, lets put a nice color gradient
        self.tmp.seek(SeekFrom::Start(0)).unwrap();
        for i in 0..(width * height) {
            let x = (i % width) as u32;
            let y = (i / width) as u32;
            let w = width as u32;
            let h = height as u32;
            let r: u32 = cmp::min(((w - x) * 0xFF) / w, ((h - y) * 0xFF) / h);
            let g: u32 = cmp::min((x * 0xFF) / w, ((h - y) * 0xFF) / h);
            let b: u32 = cmp::min(((w - x) * 0xFF) / w, (y * 0xFF) / h);
            self.tmp
                .write_u32::<NativeEndian>((0xFF << 24) + (r << 16) + (g << 8) + b)
                .unwrap();
        }
        if (width * height * 4) as usize > self.pool_size {
            // the buffer has grown, notify the compositor
            self.pool.resize(width * height * 4);
            self.pool_size = (width * height * 4) as usize;
        }
        self.buf.destroy();
        self.buf = self.pool
            .create_buffer(0, width, height, width * 4, wl_shm::Format::Argb8888)
            .expect("Pool should not be dead!");
        self.s.attach(Some(&self.buf), 0, 0);
        self.s.commit();
    }
}

fn main() {
    let (display, mut event_queue) = match wayland_client::default_connect() {
        Ok(ret) => ret,
        Err(e) => panic!("Cannot connect to wayland server: {:?}", e),
    };

    let registry = display.get_registry();
    let env_token = EnvHandler::<WaylandEnv>::init(&mut event_queue, &registry);
    event_queue.sync_roundtrip().unwrap();

    // Use `xdg-shell` if its available. Otherwise, fall back to `wl-shell`.
    let (mut xdg_shell, mut wl_shell) = (None, None);
    {
        let state = event_queue.state();
        let env = state.get(&env_token);
        for &(name, ref interface, version) in env.globals() {
            if interface == ZxdgShellV6::interface_name() {
                xdg_shell = Some(registry.bind::<ZxdgShellV6>(version, name));
                break;
            }
        }

        if xdg_shell.is_none() {
            for &(name, ref interface, version) in env.globals() {
                if interface == wl_shell::WlShell::interface_name() {
                    wl_shell = Some(registry.bind::<wl_shell::WlShell>(version, name));
                    break;
                }
            }
        }
    }

    let shell = match (xdg_shell, wl_shell) {
        (Some(shell), _) => {
            // If using xdg-shell, we'll need to answer the pings.
            let shell_implementation = zxdg_shell_v6::Implementation {
                ping: |_, _, shell, serial| {
                    shell.pong(serial);
                },
            };
            event_queue.register(&shell, shell_implementation, ());
            wayland_window::Shell::Xdg(shell)
        }
        (_, Some(shell)) => wayland_window::Shell::Wl(shell),
        _ => panic!("No available shell"),
    };

    // get the env
    let env = event_queue.state().get(&env_token).clone_inner().unwrap();

    // prepare the Window
    let wl_surface = env.compositor.create_surface();
    let window_token = event_queue
        .state()
        .insert(Window::new(wl_surface.clone().unwrap(), &env.shm));

    // find the seat if any
    let seat = event_queue.state().with_value(&env_token, |_, env| {
        for &(id, ref interface, _) in env.globals() {
            if interface == "wl_seat" {
                return Some(registry.bind(1, id));
            }
        }
        None
    });

    let mut frame = create_frame(
        &mut event_queue,
        window_implementation(),
        window_token.clone(),
        &wl_surface,
        16,
        16,
        &env.compositor,
        &env.subcompositor,
        &env.shm,
        &shell,
        seat,
    ).unwrap();

    frame.set_title("My example window".into());
    frame.set_decorate(true);
    frame.set_min_size(Some((10, 10)));
    frame.refresh();

    loop {
        display.flush().unwrap();
        event_queue.dispatch().unwrap();

        // resize if needed
        let keep_going = event_queue.state().with_value(&window_token, |_, window| {
            if let Some((w, h)) = window.newsize.take() {
                frame.resize(w, h);
                window.resize(w, h);
                frame.refresh();
            } else if window.refresh {
                frame.refresh();
            }
            window.refresh = false;
            !window.closed
        });

        if !keep_going {
            break;
        }
    }
}
<commit_msg>missing flush in example<commit_after>extern crate byteorder;
extern crate tempfile;
#[macro_use]
extern crate wayland_client;
extern crate wayland_protocols;
extern crate wayland_window;

use byteorder::{NativeEndian, WriteBytesExt};
use std::cmp;
use std::fs::File;
use std::io::{Seek, SeekFrom, Write};
use std::os::unix::io::AsRawFd;
use tempfile::tempfile;
use wayland_client::{EnvHandler, Proxy, StateToken};
use wayland_client::protocol::{wl_buffer, wl_compositor, wl_shell, wl_shm, wl_shm_pool, wl_subcompositor,
                               wl_surface};
use wayland_protocols::unstable::xdg_shell::v6::client::zxdg_shell_v6::{self, ZxdgShellV6};
use wayland_window::create_frame;

wayland_env!(
    WaylandEnv,
    compositor: wl_compositor::WlCompositor,
    subcompositor: wl_subcompositor::WlSubcompositor,
    shm: wl_shm::WlShm
);

struct Window {
    s: wl_surface::WlSurface,
    tmp: File,
    pool: wl_shm_pool::WlShmPool,
    pool_size: usize,
    buf: wl_buffer::WlBuffer,
    newsize: Option<(i32, i32)>,
    closed: bool,
    refresh: bool,
}

fn window_implementation() -> wayland_window::FrameImplementation<StateToken<Window>> {
    wayland_window::FrameImplementation {
        configure: |evqh, token, config, newsize| {
            if let Some((w, h)) = newsize {
                println!("configure newsize: {:?}", (w, h));
                evqh.state().get_mut(token).newsize = Some((w, h))
            }
            println!("configure metadata: {:?}", config);
            evqh.state().get_mut(token).refresh = true;
        },
        close: |evqh, token| {
            println!("close window");
            evqh.state().get_mut(token).closed = true;
        },
        refresh: |evqh, token| {
            evqh.state().get_mut(token).refresh = true;
        },
    }
}

impl Window {
    fn new(surface: wl_surface::WlSurface, shm: &wl_shm::WlShm) -> Window {
        // create a tempfile to write the contents of the window on
        let mut tmp = tempfile().ok().expect("Unable to create a tempfile.");
        // write the contents to it, lets put everything in dark red
        for _ in 0..16 {
            let _ = tmp.write_u32::<NativeEndian>(0xFF880000);
        }
        let _ = tmp.flush();
        let pool = shm.create_pool(tmp.as_raw_fd(), 64);
        let buffer = pool.create_buffer(0, 4, 4, 16, wl_shm::Format::Argb8888)
            .expect("I didn't destroy the pool!");
        Window {
            s: surface,
            tmp: tmp,
            pool: pool,
            pool_size: 64,
            buf: buffer,
            newsize: Some((200, 150)),
            closed: false,
            refresh: false,
        }
    }
    fn resize(&mut self, width: i32, height: i32) {
        // write the contents to it, lets put a nice color gradient
        self.tmp.seek(SeekFrom::Start(0)).unwrap();
        for i in 0..(width * height) {
            let x = (i % width) as u32;
            let y = (i / width) as u32;
            let w = width as u32;
            let h = height as u32;
            let r: u32 = cmp::min(((w - x) * 0xFF) / w, ((h - y) * 0xFF) / h);
            let g: u32 = cmp::min((x * 0xFF) / w, ((h - y) * 0xFF) / h);
            let b: u32 = cmp::min(((w - x) * 0xFF) / w, (y * 0xFF) / h);
            self.tmp
                .write_u32::<NativeEndian>((0xFF << 24) + (r << 16) + (g << 8) + b)
                .unwrap();
        }
        self.tmp.flush().unwrap();
        if (width * height * 4) as usize > self.pool_size {
            // the buffer has grown, notify the compositor
            self.pool.resize(width * height * 4);
            self.pool_size = (width * height * 4) as usize;
        }
        self.buf.destroy();
        self.buf = self.pool
            .create_buffer(0, width, height, width * 4, wl_shm::Format::Argb8888)
            .expect("Pool should not be dead!");
        self.s.attach(Some(&self.buf), 0, 0);
        self.s.commit();
    }
}

fn main() {
    let (display, mut event_queue) = match wayland_client::default_connect() {
        Ok(ret) => ret,
        Err(e) => panic!("Cannot connect to wayland server: {:?}", e),
    };

    let registry = display.get_registry();
    let env_token = EnvHandler::<WaylandEnv>::init(&mut event_queue, &registry);
    event_queue.sync_roundtrip().unwrap();

    // Use `xdg-shell` if its available. Otherwise, fall back to `wl-shell`.
    let (mut xdg_shell, mut wl_shell) = (None, None);
    {
        let state = event_queue.state();
        let env = state.get(&env_token);
        for &(name, ref interface, version) in env.globals() {
            if interface == ZxdgShellV6::interface_name() {
                xdg_shell = Some(registry.bind::<ZxdgShellV6>(version, name));
                break;
            }
        }

        if xdg_shell.is_none() {
            for &(name, ref interface, version) in env.globals() {
                if interface == wl_shell::WlShell::interface_name() {
                    wl_shell = Some(registry.bind::<wl_shell::WlShell>(version, name));
                    break;
                }
            }
        }
    }

    let shell = match (xdg_shell, wl_shell) {
        (Some(shell), _) => {
            // If using xdg-shell, we'll need to answer the pings.
            let shell_implementation = zxdg_shell_v6::Implementation {
                ping: |_, _, shell, serial| {
                    shell.pong(serial);
                },
            };
            event_queue.register(&shell, shell_implementation, ());
            wayland_window::Shell::Xdg(shell)
        }
        (_, Some(shell)) => wayland_window::Shell::Wl(shell),
        _ => panic!("No available shell"),
    };

    // get the env
    let env = event_queue.state().get(&env_token).clone_inner().unwrap();

    // prepare the Window
    let wl_surface = env.compositor.create_surface();
    let window_token = event_queue
        .state()
        .insert(Window::new(wl_surface.clone().unwrap(), &env.shm));

    // find the seat if any
    let seat = event_queue.state().with_value(&env_token, |_, env| {
        for &(id, ref interface, _) in env.globals() {
            if interface == "wl_seat" {
                return Some(registry.bind(1, id));
            }
        }
        None
    });

    let mut frame = create_frame(
        &mut event_queue,
        window_implementation(),
        window_token.clone(),
        &wl_surface,
        16,
        16,
        &env.compositor,
        &env.subcompositor,
        &env.shm,
        &shell,
        seat,
    ).unwrap();

    frame.set_title("My example window".into());
    frame.set_decorate(true);
    frame.set_min_size(Some((10, 10)));
    frame.refresh();

    loop {
        display.flush().unwrap();
        event_queue.dispatch().unwrap();

        // resize if needed
        let keep_going = event_queue.state().with_value(&window_token, |_, window| {
            if let Some((w, h)) = window.newsize.take() {
                frame.resize(w, h);
                window.resize(w, h);
                frame.refresh();
            } else if window.refresh {
                frame.refresh();
            }
            window.refresh = false;
            !window.closed
        });

        if !keep_going {
            break;
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use super::super::{Align, Fmt};

#[test]
fn test_fmt_align() {
    let mut vars: HashMap<String, String> = HashMap::new();
    vars.insert("x".to_string(), "X".to_string());
    vars.insert("long".to_string(), "tooooloong".to_string());

    let mut fmt = Fmt {
        identifier: "x",
        fill: None,
        align: Align::None,
        width: None,
        precision: None,
    };

    // test basic
    let mut s = String::new();
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "X");

    // test alignment
    s.clear();
    fmt.width = Some(5);
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "    X");

    s.clear();
    fmt.align = Align::Right;
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "    X");

    s.clear();
    fmt.align = Align::Center;
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "  X  ");

    s.clear();
    fmt.align = Align::Left;
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "X    ");

    // more center tests
    s.clear();
    fmt.align = Align::Center;
    fmt.width = Some(6);
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "  X   ");

    // with precision

    // normally is ignored
    s.clear();
    fmt.width = Some(5);
    fmt.align = Align::None;
    fmt.precision = Some(6);
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "    X");

    // unless width is < len
    s.clear();
    fmt.identifier = "long";
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "tooool");
}

#[test]
fn test_fmt_from_str() {
    let mut expected = Fmt {
        identifier: "x",
        fill: None,
        align: Align::None,
        width: None,
        precision: None,
    };
    let mut result: Fmt;
    assert!(Fmt::from_str("x").unwrap() == expected);
    assert!(Fmt::from_str("x:").unwrap() == expected);

    expected.fill = Some('3');
    expected.align = Align::Left;
    result = Fmt::from_str("x:3<").unwrap();
    println!("result: {:?}", result);
    assert!(result == expected);

    expected.precision = Some(5);
    expected.width = Some(3);
    result = Fmt::from_str("x:3<3.5").unwrap();
    println!("result: {:?}", result);
    assert!(result == expected);

    assert!(Fmt::from_str("{x:<.3}").is_ok());
    assert!(Fmt::from_str("{xxx: <88.3}").is_ok());
    assert!(Fmt::from_str("{xxx:  <88.3}").is_err());
}
<commit_msg>Fmt::from_str is working!<commit_after>use std::collections::HashMap;
use super::super::{Align, Fmt};

#[test]
fn test_fmt_align() {
    let mut vars: HashMap<String, String> = HashMap::new();
    vars.insert("x".to_string(), "X".to_string());
    vars.insert("long".to_string(), "tooooloong".to_string());

    let mut fmt = Fmt {
        identifier: "x",
        fill: None,
        align: Align::None,
        width: None,
        precision: None,
    };

    // test basic
    let mut s = String::new();
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "X");

    // test alignment
    s.clear();
    fmt.width = Some(5);
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "    X");

    s.clear();
    fmt.align = Align::Right;
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "    X");

    s.clear();
    fmt.align = Align::Center;
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "  X  ");

    s.clear();
    fmt.align = Align::Left;
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "X    ");

    // more center tests
    s.clear();
    fmt.align = Align::Center;
    fmt.width = Some(6);
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "  X   ");

    // with precision

    // normally is ignored
    s.clear();
    fmt.width = Some(5);
    fmt.align = Align::None;
    fmt.precision = Some(6);
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "    X");

    // unless width is < len
    s.clear();
    fmt.identifier = "long";
    fmt.write(&mut s, &vars);
    println!("out: {:?}", s);
    assert!(s == "tooool");
}

#[test]
fn test_fmt_from_str() {
    let mut expected = Fmt {
        identifier: "x",
        fill: None,
        align: Align::None,
        width: None,
        precision: None,
    };
    let mut result: Fmt;
    assert!(Fmt::from_str("x").unwrap() == expected);
    assert!(Fmt::from_str("x:").unwrap() == expected);

    expected.fill = Some('3');
    expected.align = Align::Left;
    result = Fmt::from_str("x:3<").unwrap();
    println!("result: {:?}", result);
    assert!(result == expected);

    expected.precision = Some(5);
    expected.width = Some(3);
    result = Fmt::from_str("x:3<3.5").unwrap();
    println!("result: {:?}", result);
    assert!(result == expected);

    expected.precision = Some(5);
    expected.width = Some(33);
    expected.align = Align::None;
    result = Fmt::from_str("x:33.5").unwrap();
    println!("result: {:?}", result);
    assert!(result == expected);

    assert!(Fmt::from_str("{x:<.3}").is_ok());
    assert!(Fmt::from_str("{xxx: <88.3}").is_ok());
    assert!(Fmt::from_str("{xxx:  <88.3}").is_err());
}
<|endoftext|>


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

fn call(number: &str) -> &str {
    match number {
        "798-1364" => "We're sorry, the call cannot be completed as dialed.
            Please hang up and try again.",
        "645-7689" => "Hello, this is Mr. Awesome's Pizza. My name is Fred.
            What can I get for you today?",
        _ => "Hi! Who is this again?"
    }
}

fn main() {
    let mut contacts = HashMap::new();

    contacts.insert("Daniel", "798-1364");
    contacts.insert("Ashley", "645-7689");
    contacts.insert("Katie", "435-8291");
    contacts.insert("Robert", "956-1745");

    // Takes a reference and returns Option<&V>
    match contacts.get(&"Daniel") {
        Some(&number) => println!("Calling Daniel: {}", call(number)),
        _ => println!("Don't have Daniel's number."),
    }

    // `HashMap::insert()` returns `None`
    // if the inserted value is new, `Some(value)` otherwise
    contacts.insert("Daniel", "164-6743");

    match contacts.get(&"Ashley") {
        Some(&number) => println!("Calling Ashley: {}", call(number)),
        _ => println!("Don't have Ashley's number."),
    }

    contacts.remove(&("Ashley"));

    // `HashMap::iter()` returns an iterator that yields
    // (&'a key, &'a value) pairs in arbitrary order.
    for (contact, &number) in contacts.iter() {
        println!("Calling {}: {}", contact, call(number));
    }
}
<commit_msg>Translate examples/std/hash/hash.rs<commit_after>use std::collections::HashMap;

fn call(number: &str) -> &str {
    match number {
        "798-1364" => "We're sorry, the call cannot be completed as dialed.
            Please hang up and try again.",
        "645-7689" => "Hello, this is Mr. Awesome's Pizza. My name is Fred.
            What can I get for you today?",
        _ => "Hi! Who is this again?"
    }
}

fn main() {
    let mut contacts = HashMap::new();

    contacts.insert("Daniel", "798-1364");
    contacts.insert("Ashley", "645-7689");
    contacts.insert("Katie", "435-8291");
    contacts.insert("Robert", "956-1745");

    // 接受一个引用并返回 Option<&V>
    match contacts.get(&"Daniel") {
        Some(&number) => println!("Calling Daniel: {}", call(number)),
        _ => println!("Don't have Daniel's number."),
    }

    // 如果被插入的值为新内容，那么 `HashMap::insert()` 返回 `None`，
    // 否则返回 `Some(value)`
    contacts.insert("Daniel", "164-6743");

    match contacts.get(&"Ashley") {
        Some(&number) => println!("Calling Ashley: {}", call(number)),
        _ => println!("Don't have Ashley's number."),
    }

    contacts.remove(&("Ashley"));

    // `HashMap::iter()` 返回一个迭代器，该迭代器获得
    // 任意顺序的 (&'a key, &'a value) 对。
    // （原文：`HashMap::iter()` returns an iterator that yields
    // (&'a key, &'a value) pairs in arbitrary order.）
    for (contact, &number) in contacts.iter() {
        println!("Calling {}: {}", contact, call(number));
    }
}
<|endoftext|>