<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "grust-Gio-2_0"]
#![crate_type = "lib"]

#![feature(core)]

#[macro_use]
extern crate grust;

#[macro_use]
#[no_link]
extern crate bitflags;

extern crate "gio-2_0-sys" as ffi;
extern crate "glib-2_0-sys" as glib_ffi;
extern crate "gobject-2_0-sys" as gobject_ffi;
extern crate "grust-GLib-2_0" as glib;
extern crate "grust-GObject-2_0" as gobject;

use grust::enumeration;
use grust::enumeration::IntrospectedEnum as _grust_IntrospectedEnumTrait;
use grust::error;
use grust::gstr;
use grust::gtype::GType;
use grust::marker;
use grust::object;
use grust::quark;
use grust::refcount;
use grust::types::{gint, gpointer};
use grust::wrap;

use std::fmt;
use std::mem;
use std::num;
use std::ptr;
use std::result;

#[repr(C)]
pub struct AsyncResult {
    raw: ffi::GAsyncResult,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for AsyncResult {
    type Raw = ffi::GAsyncResult;
}

#[repr(C)]
pub struct File {
    raw: ffi::GFile,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for File {
    type Raw = ffi::GFile;
}

#[repr(C)]
pub struct Cancellable {
    raw: ffi::GCancellable,
    _marker: marker::ObjectMarker
}

unsafe impl Send for Cancellable { }
unsafe impl Sync for Cancellable { }
unsafe impl wrap::Wrapper for Cancellable {
    type Raw = ffi::GCancellable;
}

#[repr(C)]
pub struct InputStream {
    raw: ffi::GInputStream,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for InputStream {
    type Raw = ffi::GInputStream;
}

#[repr(C)]
pub struct FileInputStream {
    raw: ffi::GFileInputStream,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for FileInputStream {
    type Raw = ffi::GFileInputStream;
}

#[derive(Copy, PartialEq, Eq, FromPrimitive, Debug)]
#[repr(C)]
pub enum IOErrorEnum {
    Failed = 0,
    NotFound = 1,
    Exists = 2,
    // ...
}

impl enumeration::IntrospectedEnum for IOErrorEnum {

    fn from_int(v: gint) -> Result<Self, enumeration::UnknownValue> {
        num::from_i32(v as i32)
            .ok_or_else(|| enumeration::UnknownValue(v))
    }

    fn to_int(&self) -> gint {
        *self as gint
    }

    fn name(&self) -> &'static str {
        match *self {
            IOErrorEnum::Failed => "failed",
            IOErrorEnum::NotFound => "not-found",
            IOErrorEnum::Exists   => "exists",
            // ...
        }
    }
}

impl enumeration::EnumType for IOErrorEnum {
    fn get_type() -> GType {
        unsafe { GType::from_raw(ffi::g_io_error_enum_get_type()) }
    }
}

impl error::Domain for IOErrorEnum {
    fn domain() -> quark::Quark {
        g_static_quark!(b"g-io-error-quark\0")
    }
}

impl fmt::Display for IOErrorEnum {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.name())
    }
}

pub mod flags {

    pub mod file_attribute_info {
        use grust::flags::prelude::*;
        use ffi;
        use std::fmt;

        bitflags! {
            flags Flags: guint {
                const NONE            = 0,
                const COPY_WITH_FILE  = 1,
                const COPY_WHEN_MOVED = 2,
            }
        }

        impl IntrospectedFlags for Flags {

            fn from_uint(v: guint) -> Result<Flags, UnknownFlags> {
                Flags::from_bits(v)
                    .ok_or_else(|| UnknownFlags::new(v, Flags::all().bits()))
            }

            #[inline]
            fn to_uint(&self) -> guint {
                self.bits()
            }
        }

        impl FlagsType for Flags {
            fn get_type() -> GType {
                unsafe {
                    let raw = ffi::g_file_attribute_info_flags_get_type();
                    GType::from_raw(raw)
                }
            }
        }

        impl fmt::Debug for Flags {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                const FLAG_INFO: &'static [(Flags, &'static str)] = &[
                    (COPY_WITH_FILE,  "COPY_WITH_FILE"),
                    (COPY_WHEN_MOVED, "COPY_WHEN_MOVED")
                ];
                let mut contents = String::new();
                for &(flag, name) in FLAG_INFO.iter() {
                    if self.contains(flag) {
                        if contents.is_empty() {
                            contents.push_str(name);
                        } else {
                            contents.push('|');
                            contents.push_str(name);
                        }
                    }
                }
                write!(f, "FileAttributeInfoFlags({})", contents)
            }
        }
    }
}

pub use flags::file_attribute_info::Flags as FileAttributeInfoFlags;

mod async {
    use ffi;
    use gobject_ffi;
    use gobject;

    use grust::types::gpointer;
    use grust::wrap;
    use std::mem;

    pub extern "C" fn async_ready_callback<F>(source_object: *mut gobject_ffi::GObject,
                                              res: *mut ffi::GAsyncResult,
                                              user_data: gpointer)
        where F: FnOnce(&gobject::Object, &super::AsyncResult)
    {
        let cb: Box<F> = unsafe { mem::transmute(user_data) };
        let arg1 = unsafe { wrap::from_raw::<gobject::Object>(source_object) };
        let arg2 = unsafe { wrap::from_raw::<super::AsyncResult>(res) };
        cb(arg1, arg2);
    }
}

pub mod cast {
    use grust::object;

    use gobject;

    pub trait AsAsyncResult {
        fn as_async_result(&self) -> &super::AsyncResult;
    }

    impl<T> AsAsyncResult for T where T: object::Upcast<super::AsyncResult> {

        #[inline]
        fn as_async_result(&self) -> &super::AsyncResult {
            self.upcast()
        }
    }

    pub trait AsCancellable : gobject::cast::AsObject {
        fn as_cancellable(&self) -> &super::Cancellable;
    }

    impl<T> AsCancellable for T
        where T: object::Upcast<super::Cancellable>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_cancellable(&self) -> &super::Cancellable {
            self.upcast()
        }
    }

    pub trait AsInputStream : gobject::cast::AsObject {
        fn as_input_stream(&self) -> &super::InputStream;
    }

    impl<T> AsInputStream for T
        where T: object::Upcast<super::InputStream>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_input_stream(&self) -> &super::InputStream {
            self.upcast()
        }
    }

    pub trait AsFileInputStream : AsInputStream {
        fn as_file_input_stream(&self) -> &super::FileInputStream;
    }

    impl<T> AsFileInputStream for T
        where T: object::Upcast<super::FileInputStream>,
              T: object::Upcast<super::InputStream>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_file_input_stream(&self) -> &super::FileInputStream {
            self.upcast()
        }
    }

    pub trait AsFile {
        fn as_file(&self) -> &super::File;
    }

    impl<T> AsFile for T where T: object::Upcast<super::File> {

        #[inline]
        fn as_file(&self) -> &super::File {
            self.upcast()
        }
    }
}

impl File {

    pub fn new_for_path(path: &gstr::Utf8) -> refcount::Ref<File> {
        unsafe {
            let ret = ffi::g_file_new_for_path(path.as_ptr());
            refcount::Ref::from_raw(ret)
        }
    }

    pub fn get_path(&self) -> gstr::OwnedGStr {
        unsafe {
            use grust::wrap::Wrapper;
            let ret = ffi::g_file_get_path(self.as_mut_ptr());
            gstr::OwnedGStr::from_ptr(ret)
        }
    }

    pub fn read_async<F>(&self,
                         io_priority: gint,
                         cancellable: Option<&Cancellable>,
                         callback: F)
        where F: FnOnce(&gobject::Object, &AsyncResult),
              F: 'static
    {
        unsafe {
            use grust::wrap::Wrapper;
            let self_raw = self.as_mut_ptr();
            let cancellable = {
                match cancellable {
                    Some(c) => c.as_mut_ptr(),
                    None    => std::ptr::null_mut()
                }
            };
            let callback: gpointer = mem::transmute(Box::new(callback));

            ffi::g_file_read_async(self_raw,
                                   io_priority,
                                   cancellable,
                                   async::async_ready_callback::<F>,
                                   callback);
        }
    }

    pub fn read_finish(&self, res: &AsyncResult)
                      -> result::Result<refcount::Ref<FileInputStream>,
                                        error::Error> {
        let mut err: *mut glib_ffi::GError = ptr::null_mut();
        let ret = unsafe {
            use grust::wrap::Wrapper;
            ffi::g_file_read_finish(self.as_mut_ptr(),
                                    res.as_mut_ptr(),
                                    &mut err)
        };
        if err.is_null() {
            Ok(unsafe { refcount::Ref::from_raw(ret) })
        } else {
            Err(unsafe { error::Error::from_raw(err) })
        }
    }
}

unsafe impl object::ObjectType for AsyncResult {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_async_result_get_type())
        }
    }
}

unsafe impl object::ObjectType for File {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_file_get_type())
        }
    }
}

unsafe impl object::ObjectType for InputStream {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_input_stream_get_type())
        }
    }
}

unsafe impl object::ObjectType for FileInputStream {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_file_input_stream_get_type())
        }
    }
}

impl object::Upcast<gobject::Object> for Cancellable {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<gobject::Object> for InputStream {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<InputStream> for FileInputStream {

    #[inline]
    fn upcast(&self) -> &InputStream {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<gobject::Object> for FileInputStream {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        use cast::AsInputStream;
        self.as_input_stream().upcast()
    }
}
<commit_msg>Allow unstable features in the fake gio crate<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2013, 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#![crate_name = "grust-Gio-2_0"]
#![crate_type = "lib"]

#![allow(unstable_features)]

#![feature(core)]

#[macro_use]
extern crate grust;

#[macro_use]
#[no_link]
extern crate bitflags;

extern crate "gio-2_0-sys" as ffi;
extern crate "glib-2_0-sys" as glib_ffi;
extern crate "gobject-2_0-sys" as gobject_ffi;
extern crate "grust-GLib-2_0" as glib;
extern crate "grust-GObject-2_0" as gobject;

use grust::enumeration;
use grust::enumeration::IntrospectedEnum as _grust_IntrospectedEnumTrait;
use grust::error;
use grust::gstr;
use grust::gtype::GType;
use grust::marker;
use grust::object;
use grust::quark;
use grust::refcount;
use grust::types::{gint, gpointer};
use grust::wrap;

use std::fmt;
use std::mem;
use std::num;
use std::ptr;
use std::result;

#[repr(C)]
pub struct AsyncResult {
    raw: ffi::GAsyncResult,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for AsyncResult {
    type Raw = ffi::GAsyncResult;
}

#[repr(C)]
pub struct File {
    raw: ffi::GFile,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for File {
    type Raw = ffi::GFile;
}

#[repr(C)]
pub struct Cancellable {
    raw: ffi::GCancellable,
    _marker: marker::ObjectMarker
}

unsafe impl Send for Cancellable { }
unsafe impl Sync for Cancellable { }
unsafe impl wrap::Wrapper for Cancellable {
    type Raw = ffi::GCancellable;
}

#[repr(C)]
pub struct InputStream {
    raw: ffi::GInputStream,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for InputStream {
    type Raw = ffi::GInputStream;
}

#[repr(C)]
pub struct FileInputStream {
    raw: ffi::GFileInputStream,
    _marker: marker::ObjectMarker
}

unsafe impl wrap::Wrapper for FileInputStream {
    type Raw = ffi::GFileInputStream;
}

#[derive(Copy, PartialEq, Eq, FromPrimitive, Debug)]
#[repr(C)]
pub enum IOErrorEnum {
    Failed = 0,
    NotFound = 1,
    Exists = 2,
    // ...
}

impl enumeration::IntrospectedEnum for IOErrorEnum {

    fn from_int(v: gint) -> Result<Self, enumeration::UnknownValue> {
        num::from_i32(v as i32)
            .ok_or_else(|| enumeration::UnknownValue(v))
    }

    fn to_int(&self) -> gint {
        *self as gint
    }

    fn name(&self) -> &'static str {
        match *self {
            IOErrorEnum::Failed => "failed",
            IOErrorEnum::NotFound => "not-found",
            IOErrorEnum::Exists   => "exists",
            // ...
        }
    }
}

impl enumeration::EnumType for IOErrorEnum {
    fn get_type() -> GType {
        unsafe { GType::from_raw(ffi::g_io_error_enum_get_type()) }
    }
}

impl error::Domain for IOErrorEnum {
    fn domain() -> quark::Quark {
        g_static_quark!(b"g-io-error-quark\0")
    }
}

impl fmt::Display for IOErrorEnum {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.name())
    }
}

pub mod flags {

    pub mod file_attribute_info {
        use grust::flags::prelude::*;
        use ffi;
        use std::fmt;

        bitflags! {
            flags Flags: guint {
                const NONE            = 0,
                const COPY_WITH_FILE  = 1,
                const COPY_WHEN_MOVED = 2,
            }
        }

        impl IntrospectedFlags for Flags {

            fn from_uint(v: guint) -> Result<Flags, UnknownFlags> {
                Flags::from_bits(v)
                    .ok_or_else(|| UnknownFlags::new(v, Flags::all().bits()))
            }

            #[inline]
            fn to_uint(&self) -> guint {
                self.bits()
            }
        }

        impl FlagsType for Flags {
            fn get_type() -> GType {
                unsafe {
                    let raw = ffi::g_file_attribute_info_flags_get_type();
                    GType::from_raw(raw)
                }
            }
        }

        impl fmt::Debug for Flags {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                const FLAG_INFO: &'static [(Flags, &'static str)] = &[
                    (COPY_WITH_FILE,  "COPY_WITH_FILE"),
                    (COPY_WHEN_MOVED, "COPY_WHEN_MOVED")
                ];
                let mut contents = String::new();
                for &(flag, name) in FLAG_INFO.iter() {
                    if self.contains(flag) {
                        if contents.is_empty() {
                            contents.push_str(name);
                        } else {
                            contents.push('|');
                            contents.push_str(name);
                        }
                    }
                }
                write!(f, "FileAttributeInfoFlags({})", contents)
            }
        }
    }
}

pub use flags::file_attribute_info::Flags as FileAttributeInfoFlags;

mod async {
    use ffi;
    use gobject_ffi;
    use gobject;

    use grust::types::gpointer;
    use grust::wrap;
    use std::mem;

    pub extern "C" fn async_ready_callback<F>(source_object: *mut gobject_ffi::GObject,
                                              res: *mut ffi::GAsyncResult,
                                              user_data: gpointer)
        where F: FnOnce(&gobject::Object, &super::AsyncResult)
    {
        let cb: Box<F> = unsafe { mem::transmute(user_data) };
        let arg1 = unsafe { wrap::from_raw::<gobject::Object>(source_object) };
        let arg2 = unsafe { wrap::from_raw::<super::AsyncResult>(res) };
        cb(arg1, arg2);
    }
}

pub mod cast {
    use grust::object;

    use gobject;

    pub trait AsAsyncResult {
        fn as_async_result(&self) -> &super::AsyncResult;
    }

    impl<T> AsAsyncResult for T where T: object::Upcast<super::AsyncResult> {

        #[inline]
        fn as_async_result(&self) -> &super::AsyncResult {
            self.upcast()
        }
    }

    pub trait AsCancellable : gobject::cast::AsObject {
        fn as_cancellable(&self) -> &super::Cancellable;
    }

    impl<T> AsCancellable for T
        where T: object::Upcast<super::Cancellable>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_cancellable(&self) -> &super::Cancellable {
            self.upcast()
        }
    }

    pub trait AsInputStream : gobject::cast::AsObject {
        fn as_input_stream(&self) -> &super::InputStream;
    }

    impl<T> AsInputStream for T
        where T: object::Upcast<super::InputStream>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_input_stream(&self) -> &super::InputStream {
            self.upcast()
        }
    }

    pub trait AsFileInputStream : AsInputStream {
        fn as_file_input_stream(&self) -> &super::FileInputStream;
    }

    impl<T> AsFileInputStream for T
        where T: object::Upcast<super::FileInputStream>,
              T: object::Upcast<super::InputStream>,
              T: object::Upcast<gobject::Object>
    {
        #[inline]
        fn as_file_input_stream(&self) -> &super::FileInputStream {
            self.upcast()
        }
    }

    pub trait AsFile {
        fn as_file(&self) -> &super::File;
    }

    impl<T> AsFile for T where T: object::Upcast<super::File> {

        #[inline]
        fn as_file(&self) -> &super::File {
            self.upcast()
        }
    }
}

impl File {

    pub fn new_for_path(path: &gstr::Utf8) -> refcount::Ref<File> {
        unsafe {
            let ret = ffi::g_file_new_for_path(path.as_ptr());
            refcount::Ref::from_raw(ret)
        }
    }

    pub fn get_path(&self) -> gstr::OwnedGStr {
        unsafe {
            use grust::wrap::Wrapper;
            let ret = ffi::g_file_get_path(self.as_mut_ptr());
            gstr::OwnedGStr::from_ptr(ret)
        }
    }

    pub fn read_async<F>(&self,
                         io_priority: gint,
                         cancellable: Option<&Cancellable>,
                         callback: F)
        where F: FnOnce(&gobject::Object, &AsyncResult),
              F: 'static
    {
        unsafe {
            use grust::wrap::Wrapper;
            let self_raw = self.as_mut_ptr();
            let cancellable = {
                match cancellable {
                    Some(c) => c.as_mut_ptr(),
                    None    => std::ptr::null_mut()
                }
            };
            let callback: gpointer = mem::transmute(Box::new(callback));

            ffi::g_file_read_async(self_raw,
                                   io_priority,
                                   cancellable,
                                   async::async_ready_callback::<F>,
                                   callback);
        }
    }

    pub fn read_finish(&self, res: &AsyncResult)
                      -> result::Result<refcount::Ref<FileInputStream>,
                                        error::Error> {
        let mut err: *mut glib_ffi::GError = ptr::null_mut();
        let ret = unsafe {
            use grust::wrap::Wrapper;
            ffi::g_file_read_finish(self.as_mut_ptr(),
                                    res.as_mut_ptr(),
                                    &mut err)
        };
        if err.is_null() {
            Ok(unsafe { refcount::Ref::from_raw(ret) })
        } else {
            Err(unsafe { error::Error::from_raw(err) })
        }
    }
}

unsafe impl object::ObjectType for AsyncResult {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_async_result_get_type())
        }
    }
}

unsafe impl object::ObjectType for File {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_file_get_type())
        }
    }
}

unsafe impl object::ObjectType for InputStream {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_input_stream_get_type())
        }
    }
}

unsafe impl object::ObjectType for FileInputStream {
    fn get_type() -> GType {
        unsafe {
            GType::from_raw(ffi::g_file_input_stream_get_type())
        }
    }
}

impl object::Upcast<gobject::Object> for Cancellable {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<gobject::Object> for InputStream {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<InputStream> for FileInputStream {

    #[inline]
    fn upcast(&self) -> &InputStream {
        unsafe {
            wrap::from_raw(&self.raw.parent_instance)
        }
    }
}

impl object::Upcast<gobject::Object> for FileInputStream {

    #[inline]
    fn upcast(&self) -> &gobject::Object {
        use cast::AsInputStream;
        self.as_input_stream().upcast()
    }
}
<|endoftext|>


<commit_before>// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

use crate::legacy::EventFdTrigger;
use crate::BusDevice;
use logger::SerialDeviceMetrics;
use std::io;
use std::io::Write;
use std::os::unix::io::AsRawFd;
use std::result;
use std::sync::Arc;
use vm_superio::serial::Error as SerialError;
use vm_superio::serial::SerialEvents;
use vm_superio::Serial;
use vm_superio::Trigger;

use event_manager::{EventOps, Events, MutEventSubscriber};
use logger::{error, warn, IncMetric};
use std::os::unix::io::RawFd;
use utils::epoll::EventSet;

// Cannot use multiple types as bounds for a trait object, so we define our own trait
// which is a composition of the desired bounds. In this case, io::Read and AsRawFd.
// Run `rustc --explain E0225` for more details.
/// Trait that composes the `std::io::Read` and `std::os::unix::io::AsRawFd` traits.
pub trait ReadableFd: io::Read + AsRawFd {}

#[derive(Debug)]
pub enum RawIOError {
    Serial(SerialError<io::Error>),
}

pub trait RawIOHandler {
    /// Send raw input to this emulated device.
    fn raw_input(&mut self, _data: &[u8]) -> result::Result<(), RawIOError>;
}

impl<EV: SerialEvents, W: Write> RawIOHandler for Serial<EventFdTrigger, EV, W> {
    // This is not used for anything and is basically just a dummy implementation for `raw_input`.
    fn raw_input(&mut self, data: &[u8]) -> result::Result<(), RawIOError> {
        // Fail fast if the serial is serviced with more data than it can buffer.
        if data.len() > self.fifo_capacity() {
            return Err(RawIOError::Serial(SerialError::FullFifo));
        }

        // Before enqueuing bytes we first check if there is enough free space
        // in the FIFO.
        if self.fifo_capacity() >= data.len() {
            self.enqueue_raw_bytes(data).map_err(RawIOError::Serial)?;
        }
        Ok(())
    }
}

pub struct SerialEventsWrapper {
    pub metrics: Arc<SerialDeviceMetrics>,
    pub buffer_ready_event_fd: Option<EventFdTrigger>,
}

impl SerialEvents for SerialEventsWrapper {
    fn buffer_read(&self) {
        self.metrics.read_count.inc();
    }

    fn out_byte(&self) {
        self.metrics.write_count.inc();
    }

    fn tx_lost_byte(&self) {
        self.metrics.missed_write_count.inc();
    }

    fn in_buffer_empty(&self) {
        match self
            .buffer_ready_event_fd
            .as_ref()
            .map_or(Ok(()), |buf_ready| buf_ready.write(1))
        {
            Ok(_) => (),
            Err(err) => error!(
                "Could not signal that serial device buffer is ready: {:?}",
                err
            ),
        }
    }
}

pub struct SerialWrapper<T: Trigger, EV: SerialEvents, W: Write> {
    pub serial: Serial<T, EV, W>,
    pub input: Option<Box<dyn ReadableFd + Send>>,
}

impl<W: Write> SerialWrapper<EventFdTrigger, SerialEventsWrapper, W> {
    fn handle_ewouldblock(&self, ops: &mut EventOps) {
        let buffer_ready_fd = self.buffer_ready_evt_fd();
        let input_fd = self.serial_input_fd();
        if input_fd < 0 || buffer_ready_fd < 0 {
            error!("Serial does not have a configured input source.");
            return;
        }
        match ops.add(Events::new(&input_fd, EventSet::IN)) {
            Err(event_manager::Error::FdAlreadyRegistered) => (),
            Err(e) => {
                error!(
                    "Could not register the serial input to the event manager: {:?}",
                    e
                );
            }
            Ok(()) => {
                // Bytes might had come on the unregistered stdin. Try to consume any.
                self.serial.events().in_buffer_empty()
            }
        };
    }

    fn recv_bytes(&mut self) -> io::Result<usize> {
        let avail_cap = self.serial.fifo_capacity();
        if avail_cap == 0 {
            return Err(io::Error::from_raw_os_error(libc::ENOBUFS));
        }

        if let Some(input) = self.input.as_mut() {
            let mut out = vec![0u8; avail_cap];
            let count = input.read(&mut out)?;
            if count > 0 {
                self.serial
                    .raw_input(&out[..count])
                    .map_err(|_| io::Error::from_raw_os_error(libc::ENOBUFS))?;
            }

            return Ok(count);
        }

        Err(io::Error::from_raw_os_error(libc::ENOTTY))
    }

    #[inline]
    fn buffer_ready_evt_fd(&self) -> RawFd {
        self.serial
            .events()
            .buffer_ready_event_fd
            .as_ref()
            .map_or(-1, |buf_ready| buf_ready.as_raw_fd())
    }

    #[inline]
    fn serial_input_fd(&self) -> RawFd {
        self.input.as_ref().map_or(-1, |input| input.as_raw_fd())
    }

    pub fn consume_buffer_ready_event(&self) -> io::Result<u64> {
        self.serial
            .events()
            .buffer_ready_event_fd
            .as_ref()
            .map_or(Ok(0), |buf_ready| buf_ready.read())
    }
}

pub type SerialDevice =
    SerialWrapper<EventFdTrigger, SerialEventsWrapper, Box<dyn io::Write + Send>>;

impl<W: Write + Send + 'static> BusDevice
    for SerialWrapper<EventFdTrigger, SerialEventsWrapper, W>
{
    fn read(&mut self, offset: u64, data: &mut [u8]) {
        if data.len() != 1 {
            self.serial.events().metrics.missed_read_count.inc();
            return;
        }
        data[0] = self.serial.read(offset as u8);
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        if data.len() != 1 {
            self.serial.events().metrics.missed_write_count.inc();
            return;
        }
        if let Err(e) = self.serial.write(offset as u8, data[0]) {
            // Counter incremented for any handle_write() error.
            error!("Failed the write to serial: {:?}", e);
            self.serial.events().metrics.error_count.inc();
        }
    }
}
<commit_msg>[serial]: Implement event manager for serial<commit_after>// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

use crate::legacy::EventFdTrigger;
use crate::BusDevice;
use logger::SerialDeviceMetrics;
use std::io;
use std::io::Write;
use std::os::unix::io::AsRawFd;
use std::result;
use std::sync::Arc;
use vm_superio::serial::Error as SerialError;
use vm_superio::serial::SerialEvents;
use vm_superio::Serial;
use vm_superio::Trigger;

use event_manager::{EventOps, Events, MutEventSubscriber};
use logger::{error, warn, IncMetric};
use std::os::unix::io::RawFd;
use utils::epoll::EventSet;

// Cannot use multiple types as bounds for a trait object, so we define our own trait
// which is a composition of the desired bounds. In this case, io::Read and AsRawFd.
// Run `rustc --explain E0225` for more details.
/// Trait that composes the `std::io::Read` and `std::os::unix::io::AsRawFd` traits.
pub trait ReadableFd: io::Read + AsRawFd {}

#[derive(Debug)]
pub enum RawIOError {
    Serial(SerialError<io::Error>),
}

pub trait RawIOHandler {
    /// Send raw input to this emulated device.
    fn raw_input(&mut self, _data: &[u8]) -> result::Result<(), RawIOError>;
}

impl<EV: SerialEvents, W: Write> RawIOHandler for Serial<EventFdTrigger, EV, W> {
    // This is not used for anything and is basically just a dummy implementation for `raw_input`.
    fn raw_input(&mut self, data: &[u8]) -> result::Result<(), RawIOError> {
        // Fail fast if the serial is serviced with more data than it can buffer.
        if data.len() > self.fifo_capacity() {
            return Err(RawIOError::Serial(SerialError::FullFifo));
        }

        // Before enqueuing bytes we first check if there is enough free space
        // in the FIFO.
        if self.fifo_capacity() >= data.len() {
            self.enqueue_raw_bytes(data).map_err(RawIOError::Serial)?;
        }
        Ok(())
    }
}

pub struct SerialEventsWrapper {
    pub metrics: Arc<SerialDeviceMetrics>,
    pub buffer_ready_event_fd: Option<EventFdTrigger>,
}

impl SerialEvents for SerialEventsWrapper {
    fn buffer_read(&self) {
        self.metrics.read_count.inc();
    }

    fn out_byte(&self) {
        self.metrics.write_count.inc();
    }

    fn tx_lost_byte(&self) {
        self.metrics.missed_write_count.inc();
    }

    fn in_buffer_empty(&self) {
        match self
            .buffer_ready_event_fd
            .as_ref()
            .map_or(Ok(()), |buf_ready| buf_ready.write(1))
        {
            Ok(_) => (),
            Err(err) => error!(
                "Could not signal that serial device buffer is ready: {:?}",
                err
            ),
        }
    }
}

pub struct SerialWrapper<T: Trigger, EV: SerialEvents, W: Write> {
    pub serial: Serial<T, EV, W>,
    pub input: Option<Box<dyn ReadableFd + Send>>,
}

impl<W: Write> SerialWrapper<EventFdTrigger, SerialEventsWrapper, W> {
    fn handle_ewouldblock(&self, ops: &mut EventOps) {
        let buffer_ready_fd = self.buffer_ready_evt_fd();
        let input_fd = self.serial_input_fd();
        if input_fd < 0 || buffer_ready_fd < 0 {
            error!("Serial does not have a configured input source.");
            return;
        }
        match ops.add(Events::new(&input_fd, EventSet::IN)) {
            Err(event_manager::Error::FdAlreadyRegistered) => (),
            Err(e) => {
                error!(
                    "Could not register the serial input to the event manager: {:?}",
                    e
                );
            }
            Ok(()) => {
                // Bytes might had come on the unregistered stdin. Try to consume any.
                self.serial.events().in_buffer_empty()
            }
        };
    }

    fn recv_bytes(&mut self) -> io::Result<usize> {
        let avail_cap = self.serial.fifo_capacity();
        if avail_cap == 0 {
            return Err(io::Error::from_raw_os_error(libc::ENOBUFS));
        }

        if let Some(input) = self.input.as_mut() {
            let mut out = vec![0u8; avail_cap];
            let count = input.read(&mut out)?;
            if count > 0 {
                self.serial
                    .raw_input(&out[..count])
                    .map_err(|_| io::Error::from_raw_os_error(libc::ENOBUFS))?;
            }

            return Ok(count);
        }

        Err(io::Error::from_raw_os_error(libc::ENOTTY))
    }

    #[inline]
    fn buffer_ready_evt_fd(&self) -> RawFd {
        self.serial
            .events()
            .buffer_ready_event_fd
            .as_ref()
            .map_or(-1, |buf_ready| buf_ready.as_raw_fd())
    }

    #[inline]
    fn serial_input_fd(&self) -> RawFd {
        self.input.as_ref().map_or(-1, |input| input.as_raw_fd())
    }

    pub fn consume_buffer_ready_event(&self) -> io::Result<u64> {
        self.serial
            .events()
            .buffer_ready_event_fd
            .as_ref()
            .map_or(Ok(0), |buf_ready| buf_ready.read())
    }
}

pub type SerialDevice =
    SerialWrapper<EventFdTrigger, SerialEventsWrapper, Box<dyn io::Write + Send>>;

impl<W: std::io::Write> MutEventSubscriber
    for SerialWrapper<EventFdTrigger, SerialEventsWrapper, W>
{
    /// Handle events on the serial input fd.
    fn process(&mut self, event: Events, ops: &mut EventOps) {
        #[inline]
        fn unregister_source<T: AsRawFd>(ops: &mut EventOps, source: &T) {
            match ops.remove(Events::new(source, EventSet::IN)) {
                Ok(_) => (),
                Err(_) => error!("Could not unregister source fd: {}", source.as_raw_fd()),
            }
        }

        let input_fd = self.serial_input_fd();
        let buffer_ready_fd = self.buffer_ready_evt_fd();
        if input_fd < 0 || buffer_ready_fd < 0 {
            error!("Serial does not have a configured input source.");
            return;
        }

        if buffer_ready_fd == event.fd() {
            match self.consume_buffer_ready_event() {
                Ok(_) => (),
                Err(err) => {
                    error!("Detach serial device input source due to error in consuming the buffer ready event: {:?}", err);
                    unregister_source(ops, &input_fd);
                    unregister_source(ops, &buffer_ready_fd);
                    return;
                }
            }
        }

        // We expect to receive: `EventSet::IN`, `EventSet::HANG_UP` or
        // `EventSet::ERROR`. To process all these events we just have to
        // read from the serial input.
        match self.recv_bytes() {
            Ok(count) => {
                // Handle EOF if the event came from the input source.
                if input_fd == event.fd() && count == 0 {
                    unregister_source(ops, &input_fd);
                    unregister_source(ops, &buffer_ready_fd);
                    warn!("Detached the serial input due to peer close/error.");
                }
            }
            Err(e) => {
                match e.raw_os_error() {
                    Some(errno) if errno == libc::ENOBUFS => {
                        unregister_source(ops, &input_fd);
                    }
                    Some(errno) if errno == libc::EWOULDBLOCK => {
                        self.handle_ewouldblock(ops);
                    }
                    Some(errno) if errno == libc::ENOTTY => {
                        error!("The serial device does not have the input source attached.");
                        unregister_source(ops, &input_fd);
                        unregister_source(ops, &buffer_ready_fd);
                    }
                    Some(_) | None => {
                        // Unknown error, detach the serial input source.
                        unregister_source(ops, &input_fd);
                        unregister_source(ops, &buffer_ready_fd);
                        warn!("Detached the serial input due to peer close/error.");
                    }
                }
            }
        }
    }

    /// Initial registration of pollable objects.
    /// If serial input is present, register the serial input FD as readable.
    fn init(&mut self, ops: &mut EventOps) {
        if self.input.is_some() && self.serial.events().buffer_ready_event_fd.is_some() {
            let serial_fd = self.serial_input_fd();
            let buf_ready_evt = self.buffer_ready_evt_fd();
            if serial_fd != -1 {
                if let Err(e) = ops.add(Events::new(&serial_fd, EventSet::IN)) {
                    warn!("Failed to register serial input fd: {}", e);
                }
            }
            if let Err(e) = ops.add(Events::new(&buf_ready_evt, EventSet::IN)) {
                warn!("Failed to register serial buffer ready event: {}", e);
            }
        }
    }
}

impl<W: Write + Send + 'static> BusDevice
    for SerialWrapper<EventFdTrigger, SerialEventsWrapper, W>
{
    fn read(&mut self, offset: u64, data: &mut [u8]) {
        if data.len() != 1 {
            self.serial.events().metrics.missed_read_count.inc();
            return;
        }
        data[0] = self.serial.read(offset as u8);
    }

    fn write(&mut self, offset: u64, data: &[u8]) {
        if data.len() != 1 {
            self.serial.events().metrics.missed_write_count.inc();
            return;
        }
        if let Err(e) = self.serial.write(offset as u8, data[0]) {
            // Counter incremented for any handle_write() error.
            error!("Failed the write to serial: {:?}", e);
            self.serial.events().metrics.error_count.inc();
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Takeru Ohta <phjgt308@gmail.com>
//
// This software is released under the MIT License,
// see the LICENSE file at the top-level directory.

use bit_vec::BitVec;

pub struct Allocator {
    head: usize,
    bits: BitVec,
    nexts: Vec<Option<u32>>,
    prevs: Vec<Option<u32>>,
}

impl Allocator {
    pub fn new() -> Self {
        Allocator {
            head: 0x100,
            bits: BitVec::from_elem(1, false),
            nexts: vec![Some(1)],
            prevs: vec![None],
        }
    }

    pub fn allocate(&mut self, arcs: &[u8]) -> u32 {
        assert!(arcs.len() > 0);

        // let mut count = 0;
        let front = arcs[0];
        let head = self.head;
        let mut curr = self.get_next(head);
        loop {
            let base = curr - front as u32;
            if self.can_allocate(base as usize, &arcs[1..]) {
                self.allocate_impl(base as usize, &arcs);
                // TODO: optimize
                // if count > 10 {
                //     let head = self.head;
                //     let next_head = self.get_next(head) as usize;
                //     self.head = next_head;
                // }
                return base;
            }
            // count += 1;
            curr = self.get_next(curr as usize);
        }
    }

    fn allocate_impl(&mut self, index: usize, arcs: &[u8]) {
        self.bits.set(index, true);

        let base = index;
        for arc in arcs.iter() {
            let index = base + *arc as usize;
            self.extend_if_needed(index);

            let prev = self.prevs[index].unwrap() as usize;
            let next = self.nexts[index].unwrap() as usize;

            self.prevs[index] = None;
            self.nexts[index] = None;

            if self.head == index {
                self.head = next;
            }
            self.nexts[prev] = Some(next as u32);

            self.extend_if_needed(next);
            self.prevs[next] = Some(prev as u32);
        }
    }

    fn get_next(&mut self, index: usize) -> u32 {
        self.extend_if_needed(index);
        self.nexts[index].unwrap()
    }

    fn can_allocate(&mut self, index: usize, arcs: &[u8]) -> bool {
        if self.is_allocated(index) {
            return false; // already used
        }
        arcs.iter().all(|a| self.nexts.get(index + *a as usize).map_or(true, |x| x.is_some()))
    }

    fn is_allocated(&mut self, index: usize) -> bool {
        self.extend_if_needed(index);
        self.bits.get(index).unwrap()
    }

    fn extend_if_needed(&mut self, index: usize) {
        if index < self.prevs.len() {
            return;
        }
        let size = self.prevs.len();
        for i in size..index + 1 {
            self.nexts.push(Some(i as u32 + 1));
            self.prevs.push(Some(i as u32 - 1));
        }
        self.bits.grow(index + 1 - size, false);
    }
}
<commit_msg>Use undirectional list to manage free nodes<commit_after>// Copyright (c) 2015 Takeru Ohta <phjgt308@gmail.com>
//
// This software is released under the MIT License,
// see the LICENSE file at the top-level directory.

use bit_vec::BitVec;

pub struct Allocator {
    head: usize,
    pub bits: BitVec,
    nexts: Vec<Option<u32>>,
}

impl Allocator {
    pub fn new() -> Self {
        Allocator {
            head: 0x100,
            bits: BitVec::from_elem(1, false),
            nexts: vec![Some(1)],
        }
    }

    pub fn allocate(&mut self, arcs: &[u8]) -> u32 {
        assert!(arcs.len() > 0);

        let front = arcs[0];
        let head = self.head;
        let mut prev = head;
        let mut curr = self.get_next(head);
        loop {
            let base = curr - front as u32;
            if self.can_allocate(base as usize, &arcs[1..]) {
                self.allocate_impl(base as usize, &arcs, prev);
                return base;
            }
            prev = curr as usize;
            curr = self.get_next(curr as usize);
        }
    }

    fn allocate_impl(&mut self, index: usize, arcs: &[u8], mut prev: usize) {
        self.bits.set(index, true);

        let base = index;
        for arc in arcs.iter() {
            let index = base + *arc as usize;
            self.extend_if_needed(index);

            while self.nexts[prev] != Some(index as u32) {
                prev = self.nexts[prev].unwrap() as usize;
                assert!(prev < index);
            }

            let next = self.nexts[index].unwrap() as usize;

            self.nexts[index] = None;

            if self.head == index {
                self.head = next;
            }
            self.nexts[prev] = Some(next as u32);
        }
    }

    fn get_next(&mut self, index: usize) -> u32 {
        self.extend_if_needed(index);
        self.nexts[index].unwrap()
    }

    fn can_allocate(&mut self, index: usize, arcs: &[u8]) -> bool {
        if self.is_allocated(index) {
            return false; // already used
        }
        arcs.iter().all(|a| self.nexts.get(index + *a as usize).map_or(true, |x| x.is_some()))
    }

    fn is_allocated(&mut self, index: usize) -> bool {
        self.extend_if_needed(index);
        self.bits.get(index).unwrap()
    }

    fn extend_if_needed(&mut self, index: usize) {
        if index < self.nexts.len() {
            return;
        }
        let size = self.nexts.len();
        for i in size..index + 1 {
            self.nexts.push(Some(i as u32 + 1));
        }
        self.bits.grow(index + 1 - size, false);
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate bufstream;
extern crate cargo;
extern crate filetime;
extern crate flate2;
extern crate git2;
extern crate hamcrest;
extern crate libc;
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate url;
#[cfg(windows)] extern crate kernel32;
#[cfg(windows)] extern crate winapi;

use cargo::util::Rustc;
use std::ffi::OsStr;
use std::time::Duration;
use std::path::PathBuf;
use std::env;

pub mod support;
pub mod install;

thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc")).unwrap());

pub fn rustc_host() -> String {
    RUSTC.with(|r| r.host.clone())
}

pub fn is_nightly() -> bool {
    RUSTC.with(|r| {
        r.verbose_version.contains("-nightly") ||
            r.verbose_version.contains("-dev")
    })
}

pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
    _process(t.as_ref())
}

fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
    let mut p = cargo::util::process(t);
    p.cwd(&support::paths::root())
     .env_remove("CARGO_HOME")
     .env("HOME", support::paths::home())
     .env("CARGO_HOME", support::paths::home().join(".cargo"))
     .env_remove("RUSTC")
     .env_remove("RUSTFLAGS")
     .env_remove("CARGO_INCREMENTAL")
     .env_remove("XDG_CONFIG_HOME")      // see #2345
     .env("GIT_CONFIG_NOSYSTEM", "1")    // keep trying to sandbox ourselves
     .env_remove("CARGO_TARGET_DIR")     // we assume 'target'
     .env_remove("MSYSTEM");             // assume cmd.exe everywhere on windows

    // We'll need dynamic libraries at some point in this test suite, so ensure
    // that the rustc libdir is somewhere in LD_LIBRARY_PATH as appropriate.
    // Note that this isn't needed on Windows as we assume the bindir (with
    // dlls) is in PATH.
    if cfg!(unix) {
        let var = if cfg!(target_os = "macos") {
            "DYLD_LIBRARY_PATH"
        } else {
            "LD_LIBRARY_PATH"
        };
        let rustc = RUSTC.with(|r| r.path.clone());
        let path = env::var_os("PATH").unwrap_or(Default::default());
        let rustc = env::split_paths(&path)
                        .map(|p| p.join(&rustc))
                        .find(|p| p.exists())
                        .unwrap();
        let mut libdir = rustc.clone();
        libdir.pop();
        libdir.pop();
        libdir.push("lib");
        let prev = env::var_os(&var).unwrap_or(Default::default());
        let mut paths = env::split_paths(&prev).collect::<Vec<_>>();
        println!("libdir: {:?}", libdir);
        if !paths.contains(&libdir) {
            paths.push(libdir);
            p.env(var, env::join_paths(&paths).unwrap());
        }
    }
    return p
}

pub fn cargo_process() -> cargo::util::ProcessBuilder {
    process(&support::cargo_dir().join("cargo"))
}

pub fn sleep_ms(ms: u64) {
    std::thread::sleep(Duration::from_millis(ms));
}
<commit_msg>Auto merge of #3785 - joshtriplett:insulate-tests-from-user-env, r=alexcrichton<commit_after>#![deny(warnings)]

extern crate bufstream;
extern crate cargo;
extern crate filetime;
extern crate flate2;
extern crate git2;
extern crate hamcrest;
extern crate libc;
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate tar;
extern crate tempdir;
extern crate term;
extern crate url;
#[cfg(windows)] extern crate kernel32;
#[cfg(windows)] extern crate winapi;

use cargo::util::Rustc;
use std::ffi::OsStr;
use std::time::Duration;
use std::path::PathBuf;
use std::env;

pub mod support;
pub mod install;

thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc")).unwrap());

pub fn rustc_host() -> String {
    RUSTC.with(|r| r.host.clone())
}

pub fn is_nightly() -> bool {
    RUSTC.with(|r| {
        r.verbose_version.contains("-nightly") ||
            r.verbose_version.contains("-dev")
    })
}

pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
    _process(t.as_ref())
}

fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
    let mut p = cargo::util::process(t);
    p.cwd(&support::paths::root())
     .env_remove("CARGO_HOME")
     .env("HOME", support::paths::home())
     .env("CARGO_HOME", support::paths::home().join(".cargo"))
     .env_remove("RUSTC")
     .env_remove("RUSTFLAGS")
     .env_remove("CARGO_INCREMENTAL")
     .env_remove("XDG_CONFIG_HOME")      // see #2345
     .env("GIT_CONFIG_NOSYSTEM", "1")    // keep trying to sandbox ourselves
     .env_remove("EMAIL")
     .env_remove("GIT_AUTHOR_NAME")
     .env_remove("GIT_AUTHOR_EMAIL")
     .env_remove("GIT_COMMITTER_NAME")
     .env_remove("GIT_COMMITTER_EMAIL")
     .env_remove("CARGO_TARGET_DIR")     // we assume 'target'
     .env_remove("MSYSTEM");             // assume cmd.exe everywhere on windows

    // We'll need dynamic libraries at some point in this test suite, so ensure
    // that the rustc libdir is somewhere in LD_LIBRARY_PATH as appropriate.
    // Note that this isn't needed on Windows as we assume the bindir (with
    // dlls) is in PATH.
    if cfg!(unix) {
        let var = if cfg!(target_os = "macos") {
            "DYLD_LIBRARY_PATH"
        } else {
            "LD_LIBRARY_PATH"
        };
        let rustc = RUSTC.with(|r| r.path.clone());
        let path = env::var_os("PATH").unwrap_or(Default::default());
        let rustc = env::split_paths(&path)
                        .map(|p| p.join(&rustc))
                        .find(|p| p.exists())
                        .unwrap();
        let mut libdir = rustc.clone();
        libdir.pop();
        libdir.pop();
        libdir.push("lib");
        let prev = env::var_os(&var).unwrap_or(Default::default());
        let mut paths = env::split_paths(&prev).collect::<Vec<_>>();
        println!("libdir: {:?}", libdir);
        if !paths.contains(&libdir) {
            paths.push(libdir);
            p.env(var, env::join_paths(&paths).unwrap());
        }
    }
    return p
}

pub fn cargo_process() -> cargo::util::ProcessBuilder {
    process(&support::cargo_dir().join("cargo"))
}

pub fn sleep_ms(ms: u64) {
    std::thread::sleep(Duration::from_millis(ms));
}
<|endoftext|>


<commit_before>use assert_cmd::Command;
use std::ffi::OsStr;

pub(crate) trait Expectable {
    #[track_caller]
    fn assert_eq(self, other: &[u8]);
}

impl Expectable for &str {
    #[track_caller]
    fn assert_eq(self, other: &[u8]) {
        if let Ok(other_str) = std::str::from_utf8(other) {
            assert_eq!(other_str, self)
        } else {
            // should always fail as other is not valid utf-8 but self is
            // just for consistent assert error message
            assert_eq!(other, self.as_bytes())
        }
    }
}

impl Expectable for &[u8] {
    #[track_caller]
    fn assert_eq(self, other: &[u8]) {
        assert_eq!(other, self)
    }
}

/// Tests whether the file can be successfully loaded
/// and produces the expected output during it
pub(crate) fn load_module_test<T: Expectable>(file: &str, expected: T) {
    use scryer_prolog::*;

    let input = machine::Stream::from("");
    let output = machine::Stream::from(String::new());
    let error = machine::Stream::from(String::new());

    let mut wam = machine::Machine::new(input, output.clone(), error);

    wam.load_file(
        file.into(),
        machine::Stream::from(
            std::fs::read_to_string(AsRef::<std::path::Path>::as_ref(file)).unwrap(),
        ),
    );

    let output = output.bytes().unwrap();
    expected.assert_eq(output.as_slice());
}

pub const SCRYER_PROLOG: &str = "scryer-prolog";

pub fn run_top_level_test_no_args<
    S: Into<Vec<u8>>,
    O: assert_cmd::assert::IntoOutputPredicate<P>,
    P: predicates_core::Predicate<[u8]>,
>(
    stdin: S,
    expected_stdout: O,
) {
    run_top_level_test_with_args::<&[&str], _, _, _, _>(&[], stdin, expected_stdout)
}

/// Test whether scryer-prolog
/// produces the expected output when called with the supplied
/// arguments and fed the supplied input
pub fn run_top_level_test_with_args<
    A: IntoIterator<Item = AS>,
    S: Into<Vec<u8>>,
    O: assert_cmd::assert::IntoOutputPredicate<P>,
    AS: AsRef<OsStr>,
    P: predicates_core::Predicate<[u8]>,
>(
    args: A,
    stdin: S,
    expected_stdout: O,
) {
    Command::cargo_bin(SCRYER_PROLOG)
        .unwrap()
        .args(args)
        .write_stdin(stdin)
        .assert()
        .stdout(expected_stdout.into_output())
        .success();
}
<commit_msg>pass -f to scryer-prolog in cargo test so that we ignore .scryerrc<commit_after>use assert_cmd::Command;
use std::ffi::OsStr;

pub(crate) trait Expectable {
    #[track_caller]
    fn assert_eq(self, other: &[u8]);
}

impl Expectable for &str {
    #[track_caller]
    fn assert_eq(self, other: &[u8]) {
        if let Ok(other_str) = std::str::from_utf8(other) {
            assert_eq!(other_str, self)
        } else {
            // should always fail as other is not valid utf-8 but self is
            // just for consistent assert error message
            assert_eq!(other, self.as_bytes())
        }
    }
}

impl Expectable for &[u8] {
    #[track_caller]
    fn assert_eq(self, other: &[u8]) {
        assert_eq!(other, self)
    }
}

/// Tests whether the file can be successfully loaded
/// and produces the expected output during it
pub(crate) fn load_module_test<T: Expectable>(file: &str, expected: T) {
    use scryer_prolog::*;

    let input = machine::Stream::from("");
    let output = machine::Stream::from(String::new());
    let error = machine::Stream::from(String::new());

    let mut wam = machine::Machine::new(input, output.clone(), error);

    wam.load_file(
        file.into(),
        machine::Stream::from(
            std::fs::read_to_string(AsRef::<std::path::Path>::as_ref(file)).unwrap(),
        ),
    );

    let output = output.bytes().unwrap();
    expected.assert_eq(output.as_slice());
}

pub const SCRYER_PROLOG: &str = "scryer-prolog";

pub fn run_top_level_test_no_args<
    S: Into<Vec<u8>>,
    O: assert_cmd::assert::IntoOutputPredicate<P>,
    P: predicates_core::Predicate<[u8]>,
>(
    stdin: S,
    expected_stdout: O,
) {
    run_top_level_test_with_args::<&[&str], _, _, _, _>(&[], stdin, expected_stdout)
}

/// Test whether scryer-prolog
/// produces the expected output when called with the supplied
/// arguments and fed the supplied input
pub fn run_top_level_test_with_args<
    A: IntoIterator<Item = AS>,
    S: Into<Vec<u8>>,
    O: assert_cmd::assert::IntoOutputPredicate<P>,
    AS: AsRef<OsStr>,
    P: predicates_core::Predicate<[u8]>,
>(
    args: A,
    stdin: S,
    expected_stdout: O,
) {
    Command::cargo_bin(SCRYER_PROLOG)
        .unwrap()
        .arg("-f")
        .args(args)
        .write_stdin(stdin)
        .assert()
        .stdout(expected_stdout.into_output())
        .success();
}
<|endoftext|>


<commit_before>use serde_json::Value;

use std::collections::HashMap;
use std::fmt;

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum AMQPType {
    Boolean,
    ShortShortInt,
    ShortShortUInt,
    ShortInt,
    ShortUInt,
    LongInt,
    LongUInt,
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    ShortString,
    LongString,
    FieldArray,
    Timestamp,
    FieldTable,
    Void,
}

impl AMQPType {
    pub fn from_id(id: char) -> Option<AMQPType> {
        match id {
            't' => Some(AMQPType::Boolean),
            'b' => Some(AMQPType::ShortShortInt),
            'B' => Some(AMQPType::ShortShortUInt),
            'U' => Some(AMQPType::ShortInt),
            'u' => Some(AMQPType::ShortUInt),
            'I' => Some(AMQPType::LongInt),
            'i' => Some(AMQPType::LongUInt),
            'L' => Some(AMQPType::LongLongInt),
            'l' => Some(AMQPType::LongLongUInt),
            'f' => Some(AMQPType::Float),
            'd' => Some(AMQPType::Double),
            'D' => Some(AMQPType::DecimalValue),
            's' => Some(AMQPType::ShortString),
            'S' => Some(AMQPType::LongString),
            'A' => Some(AMQPType::FieldArray),
            'T' => Some(AMQPType::Timestamp),
            'F' => Some(AMQPType::FieldTable),
            'V' => Some(AMQPType::Void),
            _   => None,
        }
    }

    pub fn get_id(&self) -> char {
        match *self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            AMQPType::ShortInt => 'U',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            AMQPType::LongLongInt => 'L',
            AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            AMQPType::ShortString => 's',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::Timestamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::Void => 'V',
        }
    }

    pub fn to_string(&self) -> String {
        format!("{}", self)
    }
}

impl fmt::Display for AMQPType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type Timestamp      = u64;
pub type FieldTable     = HashMap<String, AMQPValue>;
pub type Void           = ();

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct DecimalValue {
    pub scale: u8,
    pub value: LongUInt,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    Timestamp(Timestamp),
    FieldTable(FieldTable),
    Void,
}

impl From<Value> for AMQPValue {
    fn from(v: Value) -> AMQPValue {
        From::from(&v)
    }
}

impl<'a> From<&'a Value> for AMQPValue {
    fn from(v: &Value) -> AMQPValue {
        match *v {
            Value::Bool(ref b)   => AMQPValue::Boolean(*b),
            Value::Number(ref n) => {
                if n.is_u64() {
                    AMQPValue::LongLongUInt(n.as_u64().unwrap())
                } else if n.is_i64() {
                    AMQPValue::LongLongInt(n.as_i64().unwrap())
                } else {
                    AMQPValue::Double(n.as_f64().unwrap())
                }
            },
            Value::String(ref s) => AMQPValue::LongString(s.clone()),
            Value::Array(ref v)  => AMQPValue::FieldArray(v.iter().map(From::from).collect()),
            Value::Object(ref o) => AMQPValue::FieldTable(o.iter().fold(FieldTable::new(), |mut table, (k, v)| {
                table.insert(k.clone(), From::from(v));
                table
            })),
            Value::Null          => AMQPValue::Void,
        }
    }
}
<commit_msg>types: slightly change types definition<commit_after>use serde_json::Value;

use std::collections::HashMap;
use std::fmt;

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum AMQPType {
    Boolean,
    ShortShortInt,
    ShortShortUInt,
    ShortInt,
    ShortUInt,
    LongInt,
    LongUInt,
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    ShortString,
    LongString,
    FieldArray,
    Timestamp,
    FieldTable,
    Void,
}

impl AMQPType {
    pub fn from_id(id: char) -> Option<AMQPType> {
        match id {
            't' => Some(AMQPType::Boolean),
            'b' => Some(AMQPType::ShortShortInt),
            'B' => Some(AMQPType::ShortShortUInt),
            'U' => Some(AMQPType::ShortInt),
            'u' => Some(AMQPType::ShortUInt),
            'I' => Some(AMQPType::LongInt),
            'i' => Some(AMQPType::LongUInt),
            'L' => Some(AMQPType::LongLongInt),
            'l' => Some(AMQPType::LongLongUInt),
            'f' => Some(AMQPType::Float),
            'd' => Some(AMQPType::Double),
            'D' => Some(AMQPType::DecimalValue),
            's' => Some(AMQPType::ShortString),
            'S' => Some(AMQPType::LongString),
            'A' => Some(AMQPType::FieldArray),
            'T' => Some(AMQPType::Timestamp),
            'F' => Some(AMQPType::FieldTable),
            'V' => Some(AMQPType::Void),
            _   => None,
        }
    }

    pub fn get_id(&self) -> char {
        match *self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            AMQPType::ShortInt => 'U',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            AMQPType::LongLongInt => 'L',
            AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            AMQPType::ShortString => 's',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::Timestamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::Void => 'V',
        }
    }

    pub fn to_string(&self) -> String {
        format!("{}", self)
    }
}

impl fmt::Display for AMQPType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type Timestamp      = LongLongUInt;
pub type FieldTable     = HashMap<ShortString, AMQPValue>;
pub type Void           = ();

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct DecimalValue {
    pub scale: ShortShortUInt,
    pub value: LongUInt,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    Timestamp(Timestamp),
    FieldTable(FieldTable),
    Void,
}

impl From<Value> for AMQPValue {
    fn from(v: Value) -> AMQPValue {
        From::from(&v)
    }
}

impl<'a> From<&'a Value> for AMQPValue {
    fn from(v: &Value) -> AMQPValue {
        match *v {
            Value::Bool(ref b)   => AMQPValue::Boolean(*b),
            Value::Number(ref n) => {
                if n.is_u64() {
                    AMQPValue::LongLongUInt(n.as_u64().unwrap())
                } else if n.is_i64() {
                    AMQPValue::LongLongInt(n.as_i64().unwrap())
                } else {
                    AMQPValue::Double(n.as_f64().unwrap())
                }
            },
            Value::String(ref s) => AMQPValue::LongString(s.clone()),
            Value::Array(ref v)  => AMQPValue::FieldArray(v.iter().map(From::from).collect()),
            Value::Object(ref o) => AMQPValue::FieldTable(o.iter().fold(FieldTable::new(), |mut table, (k, v)| {
                table.insert(k.clone(), From::from(v));
                table
            })),
            Value::Null          => AMQPValue::Void,
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::marker::PhantomFn;
use libc::{c_char, c_void};

use block::Block;
use runtime::{Class, Object, Sel};

enum Code {
    Slice(&'static str),
}

/// An Objective-C type encoding.
///
/// For more information, see Apple's documentation:
/// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
pub struct Encoding {
    code: Code,
}

impl Encoding {
    /// Returns self as a `str`.
    pub fn as_str(&self) -> &str {
        match self.code {
            Code::Slice(code) => code,
        }
    }
}

impl Clone for Encoding {
    fn clone(&self) -> Encoding {
        let code = match self.code {
            Code::Slice(code) => Code::Slice(code),
        };
        Encoding { code: code }
    }
}

impl PartialEq for Encoding {
    fn eq(&self, other: &Encoding) -> bool {
        self.as_str() == other.as_str()
    }
}

impl fmt::Debug for Encoding {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

pub fn from_static_str(code: &'static str) -> Encoding {
    Encoding { code: Code::Slice(code) }
}

/// Types that have an Objective-C type encoding.
///
/// Unsafe because Objective-C will make assumptions about the type (like its
/// size and alignment) from its encoding, so the implementer must verify that
/// the encoding is accurate.
pub unsafe trait Encode : PhantomFn<Self> {
    /// Returns the Objective-C type encoding for Self.
    fn encode() -> Encoding;
}

macro_rules! encode_impls {
    ($($t:ty : $s:expr,)*) => ($(
        unsafe impl Encode for $t {
            fn encode() -> Encoding { from_static_str($s) }
        }
    )*);
}

encode_impls!(
    i8: "c",
    i16: "s",
    i32: "i",
    i64: "q",
    u8: "C",
    u16: "S",
    u32: "I",
    u64: "Q",
    f32: "f",
    f64: "d",
    bool: "B",
    (): "v",
    *mut c_char: "*",
    *const c_char: "r*",
    *mut c_void: "^v",
    *const c_void: "r^v",
    Sel: ":",
);

unsafe impl Encode for isize {
    #[cfg(target_pointer_width = "32")]
    fn encode() -> Encoding { i32::encode() }

    #[cfg(target_pointer_width = "64")]
    fn encode() -> Encoding { i64::encode() }
}

unsafe impl Encode for usize {
    #[cfg(target_pointer_width = "32")]
    fn encode() -> Encoding { u32::encode() }

    #[cfg(target_pointer_width = "64")]
    fn encode() -> Encoding { u64::encode() }
}

macro_rules! encode_message_impl {
    ($code:expr, $name:ident) => (
        encode_message_impl!($code, $name,);
    );
    ($code:expr, $name:ident, $($t:ident),*) => (
        unsafe impl<'a $(, $t)*> $crate::Encode for &'a $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for &'a mut $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for Option<&'a $name<$($t),*>> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for Option<&'a mut $name<$($t),*>> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<$($t),*> $crate::Encode for *const $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<$($t),*> $crate::Encode for *mut $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }
    );
}

encode_message_impl!("@", Object);

encode_message_impl!("#", Class);

encode_message_impl!("@?", Block, A, R);

#[cfg(test)]
mod tests {
    use runtime::{Class, Object, Sel};
    use super::Encode;

    #[test]
    fn test_encode() {
        assert!(u32::encode().as_str() == "I");
        assert!(<()>::encode().as_str() == "v");
        assert!(<&Object>::encode().as_str() == "@");
        assert!(<*mut Object>::encode().as_str() == "@");
        assert!(<&Class>::encode().as_str() == "#");
        assert!(Sel::encode().as_str() == ":");
    }
}
<commit_msg>Added an Owned variant for Encoding's Code.<commit_after>use std::fmt;
use std::marker::PhantomFn;
use libc::{c_char, c_void};

use block::Block;
use runtime::{Class, Object, Sel};

enum Code {
    Slice(&'static str),
    Owned(String),
}

/// An Objective-C type encoding.
///
/// For more information, see Apple's documentation:
/// https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
pub struct Encoding {
    code: Code,
}

impl Encoding {
    /// Returns self as a `str`.
    pub fn as_str(&self) -> &str {
        match self.code {
            Code::Slice(code) => code,
            Code::Owned(ref code) => code,
        }
    }
}

impl Clone for Encoding {
    fn clone(&self) -> Encoding {
        let code = match self.code {
            Code::Slice(code) => Code::Slice(code),
            Code::Owned(ref code) => Code::Owned(code.clone()),
        };
        Encoding { code: code }
    }
}

impl PartialEq for Encoding {
    fn eq(&self, other: &Encoding) -> bool {
        self.as_str() == other.as_str()
    }
}

impl fmt::Debug for Encoding {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

pub fn from_static_str(code: &'static str) -> Encoding {
    Encoding { code: Code::Slice(code) }
}

/// Types that have an Objective-C type encoding.
///
/// Unsafe because Objective-C will make assumptions about the type (like its
/// size and alignment) from its encoding, so the implementer must verify that
/// the encoding is accurate.
pub unsafe trait Encode : PhantomFn<Self> {
    /// Returns the Objective-C type encoding for Self.
    fn encode() -> Encoding;
}

macro_rules! encode_impls {
    ($($t:ty : $s:expr,)*) => ($(
        unsafe impl Encode for $t {
            fn encode() -> Encoding { from_static_str($s) }
        }
    )*);
}

encode_impls!(
    i8: "c",
    i16: "s",
    i32: "i",
    i64: "q",
    u8: "C",
    u16: "S",
    u32: "I",
    u64: "Q",
    f32: "f",
    f64: "d",
    bool: "B",
    (): "v",
    *mut c_char: "*",
    *const c_char: "r*",
    *mut c_void: "^v",
    *const c_void: "r^v",
    Sel: ":",
);

unsafe impl Encode for isize {
    #[cfg(target_pointer_width = "32")]
    fn encode() -> Encoding { i32::encode() }

    #[cfg(target_pointer_width = "64")]
    fn encode() -> Encoding { i64::encode() }
}

unsafe impl Encode for usize {
    #[cfg(target_pointer_width = "32")]
    fn encode() -> Encoding { u32::encode() }

    #[cfg(target_pointer_width = "64")]
    fn encode() -> Encoding { u64::encode() }
}

macro_rules! encode_message_impl {
    ($code:expr, $name:ident) => (
        encode_message_impl!($code, $name,);
    );
    ($code:expr, $name:ident, $($t:ident),*) => (
        unsafe impl<'a $(, $t)*> $crate::Encode for &'a $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for &'a mut $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for Option<&'a $name<$($t),*>> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<'a $(, $t)*> $crate::Encode for Option<&'a mut $name<$($t),*>> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<$($t),*> $crate::Encode for *const $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }

        unsafe impl<$($t),*> $crate::Encode for *mut $name<$($t),*> {
            fn encode() -> Encoding { from_static_str($code) }
        }
    );
}

encode_message_impl!("@", Object);

encode_message_impl!("#", Class);

encode_message_impl!("@?", Block, A, R);

#[cfg(test)]
mod tests {
    use runtime::{Class, Object, Sel};
    use super::Encode;

    #[test]
    fn test_encode() {
        assert!(u32::encode().as_str() == "I");
        assert!(<()>::encode().as_str() == "v");
        assert!(<&Object>::encode().as_str() == "@");
        assert!(<*mut Object>::encode().as_str() == "@");
        assert!(<&Class>::encode().as_str() == "#");
        assert!(Sel::encode().as_str() == ":");
    }
}
<|endoftext|>


<commit_before>use truetype::{Result, Tape, Value};

use layout::{Coverage, Device};

table! {
    #[doc = "A glyph attachment."]
    pub Attachment { // AttachPoint
        index_count (u16), // PointCount

        indices (Vec<u16>) |this, tape| { // PointIndex
            tape.take_given(this.index_count as usize)
        },
    }
}

table! {
    @position
    #[doc = "A set of glyph attachments."]
    pub Attachments { // AttachList
        coverage_offset (u16), // Coverage
        count           (u16), // GlyphCount

        offsets (Vec<u16>) |this, tape, _| { // AttachPoint
            tape.take_given(this.count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        records (Vec<Attachment>) |this, tape, position| {
            jump_take!(tape, position, this.count, this.offsets)
        },
    }
}

/// A ligature caret.
#[derive(Clone, Debug)]
pub enum Caret {
    /// Format 1.
    Format1(Caret1),
    /// Format 2.
    Format2(Caret2),
    /// Format 3.
    Format3(Caret3),
}

table! {
    /// A ligature caret in format 1.
    #[derive(Copy)]
    pub Caret1 {
        format     (u16), // CaretValueFormat
        coordinate (i16), // Coordinate
    }
}

table! {
    /// A ligature caret in format 2.
    #[derive(Copy)]
    pub Caret2 {
        format (u16), // CaretValueFormat
        index  (u16), // CaretValuePoint
    }
}

table! {
    @position
    /// A ligature caret in format 3.
    pub Caret3 {
        format        (u16), // CaretValueFormat
        coordinate    (i16), // Coordinate
        device_offset (u16), // DeviceTable

        device (Device) |this, tape, position| {
            jump_take!(tape, position, this.device_offset)
        },
    }
}

table! {
    @position
    #[doc = "A ligature."]
    pub Ligature { // LigGlyph
        caret_count (u16), // CaretCount

        caret_offsets (Vec<u16>) |this, tape, _| { // CaretValue
            tape.take_given(this.caret_count as usize)
        },

        carets (Vec<Caret>) |this, tape, position| {
            jump_take!(tape, position, this.caret_count, this.caret_offsets)
        },
    }
}

table! {
    @position
    #[doc = "A set of ligatures."]
    pub Ligatures { // LigatureCaretList
        coverage_offset (u16), // Coverage
        count           (u16), // LigGlyphCount

        offsets (Vec<u16>) |this, tape, _| { // LigGlyph
            tape.take_given(this.count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        records (Vec<Ligature>) |this, tape, position| {
            jump_take!(tape, position, this.count, this.offsets)
        },
    }
}

table! {
    @position
    #[doc = "A set of marks."]
    pub Marks { // MarkGlyphSetsTable
        format (u16) = { 1 }, // MarkSetTableFormat
        count  (u16), // MarkSetCount

        coverage_offsets (Vec<u32>) |this, tape, _| { // Coverage
            tape.take_given(this.count as usize)
        },

        coverages (Vec<Coverage>) |this, tape, position| {
            jump_take!(tape, position, this.count, this.coverage_offsets)
        },
    }
}

impl Value for Caret {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u32>()) {
            1 => Caret::Format1(try!(tape.take())),
            2 => Caret::Format2(try!(tape.take())),
            3 => Caret::Format3(try!(tape.take())),
            _ => raise!("found an unknown format of the caret-value table"),
        })
    }
}
<commit_msg>Fix a typo<commit_after>use truetype::{Result, Tape, Value};

use layout::{Coverage, Device};

table! {
    #[doc = "A glyph attachment."]
    pub Attachment { // AttachPoint
        index_count (u16), // PointCount

        indices (Vec<u16>) |this, tape| { // PointIndex
            tape.take_given(this.index_count as usize)
        },
    }
}

table! {
    @position
    #[doc = "A set of glyph attachments."]
    pub Attachments { // AttachList
        coverage_offset (u16), // Coverage
        count           (u16), // GlyphCount

        offsets (Vec<u16>) |this, tape, _| { // AttachPoint
            tape.take_given(this.count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        records (Vec<Attachment>) |this, tape, position| {
            jump_take!(tape, position, this.count, this.offsets)
        },
    }
}

/// A ligature caret.
#[derive(Clone, Debug)]
pub enum Caret {
    /// Format 1.
    Format1(Caret1),
    /// Format 2.
    Format2(Caret2),
    /// Format 3.
    Format3(Caret3),
}

table! {
    /// A ligature caret in format 1.
    #[derive(Copy)]
    pub Caret1 {
        format     (u16), // CaretValueFormat
        coordinate (i16), // Coordinate
    }
}

table! {
    /// A ligature caret in format 2.
    #[derive(Copy)]
    pub Caret2 {
        format (u16), // CaretValueFormat
        index  (u16), // CaretValuePoint
    }
}

table! {
    @position
    /// A ligature caret in format 3.
    pub Caret3 {
        format        (u16), // CaretValueFormat
        coordinate    (i16), // Coordinate
        device_offset (u16), // DeviceTable

        device (Device) |this, tape, position| {
            jump_take!(tape, position, this.device_offset)
        },
    }
}

table! {
    @position
    #[doc = "A ligature."]
    pub Ligature { // LigGlyph
        caret_count (u16), // CaretCount

        caret_offsets (Vec<u16>) |this, tape, _| { // CaretValue
            tape.take_given(this.caret_count as usize)
        },

        carets (Vec<Caret>) |this, tape, position| {
            jump_take!(tape, position, this.caret_count, this.caret_offsets)
        },
    }
}

table! {
    @position
    #[doc = "A set of ligatures."]
    pub Ligatures { // LigCaretList
        coverage_offset (u16), // Coverage
        count           (u16), // LigGlyphCount

        offsets (Vec<u16>) |this, tape, _| { // LigGlyph
            tape.take_given(this.count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            jump_take!(tape, position, this.coverage_offset)
        },

        records (Vec<Ligature>) |this, tape, position| {
            jump_take!(tape, position, this.count, this.offsets)
        },
    }
}

table! {
    @position
    #[doc = "A set of marks."]
    pub Marks { // MarkGlyphSetsTable
        format (u16) = { 1 }, // MarkSetTableFormat
        count  (u16), // MarkSetCount

        coverage_offsets (Vec<u32>) |this, tape, _| { // Coverage
            tape.take_given(this.count as usize)
        },

        coverages (Vec<Coverage>) |this, tape, position| {
            jump_take!(tape, position, this.count, this.coverage_offsets)
        },
    }
}

impl Value for Caret {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u32>()) {
            1 => Caret::Format1(try!(tape.take())),
            2 => Caret::Format2(try!(tape.take())),
            3 => Caret::Format3(try!(tape.take())),
            _ => raise!("found an unknown format of the caret-value table"),
        })
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait A {
    extern "fastcall" fn test1(i: i32);
    extern fn test2(i: i32);
}

struct S;
impl S {
    extern "stdcall" fn test3(i: i32) {
        assert_eq!(i, 3);
    }
}

impl A for S {
    extern "fastcall" fn test1(i: i32) {
        assert_eq!(i, 1);
    }
    extern fn test2(i: i32) {
        assert_eq!(i, 2);
    }
}

fn main() {
    <S as A>::test1(1);
    <S as A>::test2(2);
    S::test3(3);
}
<commit_msg>Add marker trait to test (fixup #22538)<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::marker::MarkerTrait;

trait A : MarkerTrait {
    extern "fastcall" fn test1(i: i32);
    extern fn test2(i: i32);
}

struct S;
impl S {
    extern "stdcall" fn test3(i: i32) {
        assert_eq!(i, 3);
    }
}

impl A for S {
    extern "fastcall" fn test1(i: i32) {
        assert_eq!(i, 1);
    }
    extern fn test2(i: i32) {
        assert_eq!(i, 2);
    }
}

fn main() {
    <S as A>::test1(1);
    <S as A>::test2(2);
    S::test3(3);
}
<|endoftext|>