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

#![stable(feature = "metadata_ext", since = "1.1.0")]

use libc;

use fs::Metadata;
use sys_common::AsInner;

#[allow(deprecated)]
use os::linux::raw;

/// OS-specific extension methods for `fs::Metadata`
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
    /// Gain a reference to the underlying `stat` structure which contains
    /// the raw information returned by the OS.
    ///
    /// The contents of the returned [`stat`] are **not** consistent across
    /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
    /// cross-Unix abstractions contained within the raw stat.
    ///
    /// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// let stat = meta.as_raw_stat();
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    #[rustc_deprecated(since = "1.8.0",
                       reason = "deprecated in favor of the accessor \
                                 methods of this trait")]
    #[allow(deprecated)]
    fn as_raw_stat(&self) -> &raw::stat;

    /// Returns the device ID on which this file resides.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_dev());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_dev(&self) -> u64;
    /// Returns the inode number.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_ino());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_ino(&self) -> u64;
    /// Returns the file type and mode.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_mode());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_mode(&self) -> u32;
    /// Returns the number of hard links to file.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_nlink());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_nlink(&self) -> u64;
    /// Returns the user ID of the file owner.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_uid());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_uid(&self) -> u32;
    /// Returns the group ID of the file owner.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_gid());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_gid(&self) -> u32;
    /// Returns the device ID that this file represents. Only relevant for special file.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_rdev());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_rdev(&self) -> u64;
    /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
    ///
    /// The size of a symbolic link is the length of the pathname it contains,
    /// without a terminating null byte.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_size());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_size(&self) -> u64;
    /// Returns the last access time.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_atime());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_atime(&self) -> i64;
    /// Returns the last access time, nano seconds part.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_atime_nsec());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_atime_nsec(&self) -> i64;
    /// Returns the last modification time.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_mtime());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_mtime(&self) -> i64;
    /// Returns the last modification time, nano seconds part.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_mtime_nsec());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_mtime_nsec(&self) -> i64;
    /// Returns the last status change time.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_ctime());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_ctime(&self) -> i64;
    /// Returns the last status change time, nano seconds part.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_ctime_nsec());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_ctime_nsec(&self) -> i64;
    /// Returns the "preferred" blocksize for efficient filesystem I/O.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_blksize());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_blksize(&self) -> u64;
    /// Returns the number of blocks allocated to the file, 512-byte units.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::unix::prelude::*;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_blocks());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_blocks(&self) -> u64;
}

#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
    #[allow(deprecated)]
    fn as_raw_stat(&self) -> &raw::stat {
        unsafe {
            &*(self.as_inner().as_inner() as *const libc::stat64
                                          as *const raw::stat)
        }
    }
    fn st_dev(&self) -> u64 {
        self.as_inner().as_inner().st_dev as u64
    }
    fn st_ino(&self) -> u64 {
        self.as_inner().as_inner().st_ino as u64
    }
    fn st_mode(&self) -> u32 {
        self.as_inner().as_inner().st_mode as u32
    }
    fn st_nlink(&self) -> u64 {
        self.as_inner().as_inner().st_nlink as u64
    }
    fn st_uid(&self) -> u32 {
        self.as_inner().as_inner().st_uid as u32
    }
    fn st_gid(&self) -> u32 {
        self.as_inner().as_inner().st_gid as u32
    }
    fn st_rdev(&self) -> u64 {
        self.as_inner().as_inner().st_rdev as u64
    }
    fn st_size(&self) -> u64 {
        self.as_inner().as_inner().st_size as u64
    }
    fn st_atime(&self) -> i64 {
        self.as_inner().as_inner().st_atime as i64
    }
    fn st_atime_nsec(&self) -> i64 {
        self.as_inner().as_inner().st_atime_nsec as i64
    }
    fn st_mtime(&self) -> i64 {
        self.as_inner().as_inner().st_mtime as i64
    }
    fn st_mtime_nsec(&self) -> i64 {
        self.as_inner().as_inner().st_mtime_nsec as i64
    }
    fn st_ctime(&self) -> i64 {
        self.as_inner().as_inner().st_ctime as i64
    }
    fn st_ctime_nsec(&self) -> i64 {
        self.as_inner().as_inner().st_ctime_nsec as i64
    }
    fn st_blksize(&self) -> u64 {
        self.as_inner().as_inner().st_blksize as u64
    }
    fn st_blocks(&self) -> u64 {
        self.as_inner().as_inner().st_blocks as u64
    }
}
<commit_msg>Fix doc build on other architectures than linux<commit_after>// Copyright 2016 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.

#![stable(feature = "metadata_ext", since = "1.1.0")]

use libc;

use fs::Metadata;
use sys_common::AsInner;

#[allow(deprecated)]
use os::linux::raw;

/// OS-specific extension methods for `fs::Metadata`
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
    /// Gain a reference to the underlying `stat` structure which contains
    /// the raw information returned by the OS.
    ///
    /// The contents of the returned [`stat`] are **not** consistent across
    /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
    /// cross-Unix abstractions contained within the raw stat.
    ///
    /// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// let stat = meta.as_raw_stat();
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext", since = "1.1.0")]
    #[rustc_deprecated(since = "1.8.0",
                       reason = "deprecated in favor of the accessor \
                                 methods of this trait")]
    #[allow(deprecated)]
    fn as_raw_stat(&self) -> &raw::stat;

    /// Returns the device ID on which this file resides.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_dev());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_dev(&self) -> u64;
    /// Returns the inode number.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_ino());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_ino(&self) -> u64;
    /// Returns the file type and mode.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_mode());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_mode(&self) -> u32;
    /// Returns the number of hard links to file.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_nlink());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_nlink(&self) -> u64;
    /// Returns the user ID of the file owner.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_uid());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_uid(&self) -> u32;
    /// Returns the group ID of the file owner.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_gid());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_gid(&self) -> u32;
    /// Returns the device ID that this file represents. Only relevant for special file.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_rdev());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_rdev(&self) -> u64;
    /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
    ///
    /// The size of a symbolic link is the length of the pathname it contains,
    /// without a terminating null byte.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_size());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_size(&self) -> u64;
    /// Returns the last access time.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_atime());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_atime(&self) -> i64;
    /// Returns the last access time, nano seconds part.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_atime_nsec());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_atime_nsec(&self) -> i64;
    /// Returns the last modification time.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_mtime());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_mtime(&self) -> i64;
    /// Returns the last modification time, nano seconds part.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_mtime_nsec());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_mtime_nsec(&self) -> i64;
    /// Returns the last status change time.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_ctime());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_ctime(&self) -> i64;
    /// Returns the last status change time, nano seconds part.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_ctime_nsec());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_ctime_nsec(&self) -> i64;
    /// Returns the "preferred" blocksize for efficient filesystem I/O.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_blksize());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_blksize(&self) -> u64;
    /// Returns the number of blocks allocated to the file, 512-byte units.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::fs;
    /// use std::os::linux::fs::MetadataExt;
    ///
    /// # use std::io;
    /// # fn f() -> io::Result<()> {
    /// let meta = fs::metadata("some_file")?;
    /// println!("{}", meta.st_blocks());
    /// # Ok(())
    /// # }
    /// ```
    #[stable(feature = "metadata_ext2", since = "1.8.0")]
    fn st_blocks(&self) -> u64;
}

#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
    #[allow(deprecated)]
    fn as_raw_stat(&self) -> &raw::stat {
        unsafe {
            &*(self.as_inner().as_inner() as *const libc::stat64
                                          as *const raw::stat)
        }
    }
    fn st_dev(&self) -> u64 {
        self.as_inner().as_inner().st_dev as u64
    }
    fn st_ino(&self) -> u64 {
        self.as_inner().as_inner().st_ino as u64
    }
    fn st_mode(&self) -> u32 {
        self.as_inner().as_inner().st_mode as u32
    }
    fn st_nlink(&self) -> u64 {
        self.as_inner().as_inner().st_nlink as u64
    }
    fn st_uid(&self) -> u32 {
        self.as_inner().as_inner().st_uid as u32
    }
    fn st_gid(&self) -> u32 {
        self.as_inner().as_inner().st_gid as u32
    }
    fn st_rdev(&self) -> u64 {
        self.as_inner().as_inner().st_rdev as u64
    }
    fn st_size(&self) -> u64 {
        self.as_inner().as_inner().st_size as u64
    }
    fn st_atime(&self) -> i64 {
        self.as_inner().as_inner().st_atime as i64
    }
    fn st_atime_nsec(&self) -> i64 {
        self.as_inner().as_inner().st_atime_nsec as i64
    }
    fn st_mtime(&self) -> i64 {
        self.as_inner().as_inner().st_mtime as i64
    }
    fn st_mtime_nsec(&self) -> i64 {
        self.as_inner().as_inner().st_mtime_nsec as i64
    }
    fn st_ctime(&self) -> i64 {
        self.as_inner().as_inner().st_ctime as i64
    }
    fn st_ctime_nsec(&self) -> i64 {
        self.as_inner().as_inner().st_ctime_nsec as i64
    }
    fn st_blksize(&self) -> u64 {
        self.as_inner().as_inner().st_blksize as u64
    }
    fn st_blocks(&self) -> u64 {
        self.as_inner().as_inner().st_blocks as u64
    }
}
<|endoftext|>


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

/*!
 * A simple map based on a vector for small integer keys. Space requirements
 * are O(highest integer key).
 */
#[forbid(deprecated_mode)];

use map;
use map::Map;

use core::dvec::DVec;
use core::ops;
use core::option::{Some, None};
use core::option;
use core::prelude::*;

// FIXME (#2347): Should not be @; there's a bug somewhere in rustc that
// requires this to be.
struct SmallIntMap_<T: Copy> {
    v: DVec<Option<T>>,
}

pub enum SmallIntMap<T:Copy> {
    SmallIntMap_(@SmallIntMap_<T>)
}

/// Create a smallintmap
pub fn mk<T: Copy>() -> SmallIntMap<T> {
    let v = DVec();
    SmallIntMap_(@SmallIntMap_ { v: v } )
}

/**
 * Add a value to the map. If the map already contains a value for
 * the specified key then the original value is replaced.
 */
#[inline(always)]
pub fn insert<T: Copy>(self: SmallIntMap<T>, key: uint, val: T) {
    //io::println(fmt!("%?", key));
    self.v.grow_set_elt(key, &None, Some(val));
}

/**
 * Get the value for the specified key. If the key does not exist
 * in the map then returns none
 */
pub pure fn find<T: Copy>(self: SmallIntMap<T>, key: uint) -> Option<T> {
    if key < self.v.len() { return self.v.get_elt(key); }
    return None::<T>;
}

/**
 * Get the value for the specified key
 *
 * # Failure
 *
 * If the key does not exist in the map
 */
pub pure fn get<T: Copy>(self: SmallIntMap<T>, key: uint) -> T {
    match find(self, key) {
      None => {
        error!("smallintmap::get(): key not present");
        fail;
      }
      Some(move v) => return v
    }
}

/// Returns true if the map contains a value for the specified key
pub pure fn contains_key<T: Copy>(self: SmallIntMap<T>, key: uint) -> bool {
    return !find(self, key).is_none();
}

/// Implements the map::map interface for smallintmap
impl<V: Copy> SmallIntMap<V>: map::Map<uint, V> {
    pure fn size() -> uint {
        let mut sz = 0u;
        for self.v.each |item| {
            match *item {
              Some(_) => sz += 1u,
              _ => ()
            }
        }
        sz
    }
    #[inline(always)]
    fn insert(key: uint, value: V) -> bool {
        let exists = contains_key(self, key);
        insert(self, key, value);
        return !exists;
    }
    fn remove(key: uint) -> bool {
        if key >= self.v.len() {
            return false;
        }
        let old = self.v.get_elt(key);
        self.v.set_elt(key, None);
        old.is_some()
    }
    fn clear() {
        self.v.set(~[]);
    }
    pure fn contains_key(key: uint) -> bool {
        contains_key(self, key)
    }
    pure fn contains_key_ref(key: &uint) -> bool {
        contains_key(self, *key)
    }
    pure fn get(key: uint) -> V { get(self, key) }
    pure fn find(key: uint) -> Option<V> { find(self, key) }

    fn update_with_key(key: uint, val: V, ff: fn(uint, V, V) -> V) -> bool {
        match self.find(key) {
            None            => return self.insert(key, val),
            Some(copy orig) => return self.insert(key, ff(key, orig, val)),
        }
    }

    fn update(key: uint, newval: V, ff: fn(V, V) -> V) -> bool {
        return self.update_with_key(key, newval, |_k, v, v1| ff(v,v1));
    }

    pure fn each(it: fn(key: uint, value: V) -> bool) {
        self.each_ref(|k, v| it(*k, *v))
    }
    pure fn each_key(it: fn(key: uint) -> bool) {
        self.each_ref(|k, _v| it(*k))
    }
    pure fn each_value(it: fn(value: V) -> bool) {
        self.each_ref(|_k, v| it(*v))
    }
    pure fn each_ref(it: fn(key: &uint, value: &V) -> bool) {
        let mut idx = 0u, l = self.v.len();
        while idx < l {
            match self.v.get_elt(idx) {
              Some(ref elt) => if !it(&idx, elt) { break },
              None => ()
            }
            idx += 1u;
        }
    }
    pure fn each_key_ref(blk: fn(key: &uint) -> bool) {
        self.each_ref(|k, _v| blk(k))
    }
    pure fn each_value_ref(blk: fn(value: &V) -> bool) {
        self.each_ref(|_k, v| blk(v))
    }
}

impl<V: Copy> SmallIntMap<V>: ops::Index<uint, V> {
    pure fn index(&self, key: uint) -> V {
        unsafe {
            get(*self, key)
        }
    }
}

/// Cast the given smallintmap to a map::map
pub fn as_map<V: Copy>(s: SmallIntMap<V>) -> map::Map<uint, V> {
    s as map::Map::<uint, V>
}

#[cfg(test)]
mod tests {
    use smallintmap::{mk, SmallIntMap};

    use core::option::None;
    use core::option;

    #[test]
    fn test_insert_with_key() {
        let map: SmallIntMap<uint> = mk();

        // given a new key, initialize it with this new count, given
        // given an existing key, add more to its count
        fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        fn addMoreToCount_simple(v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        // count integers
        map.update(3, 1, addMoreToCount_simple);
        map.update_with_key(9, 1, addMoreToCount);
        map.update(3, 7, addMoreToCount_simple);
        map.update_with_key(5, 3, addMoreToCount);
        map.update_with_key(3, 2, addMoreToCount);

        // check the total counts
        assert 10 == option::get(map.find(3));
        assert  3 == option::get(map.find(5));
        assert  1 == option::get(map.find(9));

        // sadly, no sevens were counted
        assert None == map.find(7);
    }
}
<commit_msg>Remove bounds from type decl of smallintmap<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * A simple map based on a vector for small integer keys. Space requirements
 * are O(highest integer key).
 */
#[forbid(deprecated_mode)];

use map;
use map::Map;

use core::dvec::DVec;
use core::ops;
use core::option::{Some, None};
use core::option;
use core::prelude::*;

// FIXME (#2347): Should not be @; there's a bug somewhere in rustc that
// requires this to be.
struct SmallIntMap_<T> {
    v: DVec<Option<T>>,
}

pub enum SmallIntMap<T> {
    SmallIntMap_(@SmallIntMap_<T>)
}

/// Create a smallintmap
pub fn mk<T: Copy>() -> SmallIntMap<T> {
    let v = DVec();
    SmallIntMap_(@SmallIntMap_ { v: v } )
}

/**
 * Add a value to the map. If the map already contains a value for
 * the specified key then the original value is replaced.
 */
#[inline(always)]
pub fn insert<T: Copy>(self: SmallIntMap<T>, key: uint, val: T) {
    //io::println(fmt!("%?", key));
    self.v.grow_set_elt(key, &None, Some(val));
}

/**
 * Get the value for the specified key. If the key does not exist
 * in the map then returns none
 */
pub pure fn find<T: Copy>(self: SmallIntMap<T>, key: uint) -> Option<T> {
    if key < self.v.len() { return self.v.get_elt(key); }
    return None::<T>;
}

/**
 * Get the value for the specified key
 *
 * # Failure
 *
 * If the key does not exist in the map
 */
pub pure fn get<T: Copy>(self: SmallIntMap<T>, key: uint) -> T {
    match find(self, key) {
      None => {
        error!("smallintmap::get(): key not present");
        fail;
      }
      Some(move v) => return v
    }
}

/// Returns true if the map contains a value for the specified key
pub pure fn contains_key<T: Copy>(self: SmallIntMap<T>, key: uint) -> bool {
    return !find(self, key).is_none();
}

/// Implements the map::map interface for smallintmap
impl<V: Copy> SmallIntMap<V>: map::Map<uint, V> {
    pure fn size() -> uint {
        let mut sz = 0u;
        for self.v.each |item| {
            match *item {
              Some(_) => sz += 1u,
              _ => ()
            }
        }
        sz
    }
    #[inline(always)]
    fn insert(key: uint, value: V) -> bool {
        let exists = contains_key(self, key);
        insert(self, key, value);
        return !exists;
    }
    fn remove(key: uint) -> bool {
        if key >= self.v.len() {
            return false;
        }
        let old = self.v.get_elt(key);
        self.v.set_elt(key, None);
        old.is_some()
    }
    fn clear() {
        self.v.set(~[]);
    }
    pure fn contains_key(key: uint) -> bool {
        contains_key(self, key)
    }
    pure fn contains_key_ref(key: &uint) -> bool {
        contains_key(self, *key)
    }
    pure fn get(key: uint) -> V { get(self, key) }
    pure fn find(key: uint) -> Option<V> { find(self, key) }

    fn update_with_key(key: uint, val: V, ff: fn(uint, V, V) -> V) -> bool {
        match self.find(key) {
            None            => return self.insert(key, val),
            Some(copy orig) => return self.insert(key, ff(key, orig, val)),
        }
    }

    fn update(key: uint, newval: V, ff: fn(V, V) -> V) -> bool {
        return self.update_with_key(key, newval, |_k, v, v1| ff(v,v1));
    }

    pure fn each(it: fn(key: uint, value: V) -> bool) {
        self.each_ref(|k, v| it(*k, *v))
    }
    pure fn each_key(it: fn(key: uint) -> bool) {
        self.each_ref(|k, _v| it(*k))
    }
    pure fn each_value(it: fn(value: V) -> bool) {
        self.each_ref(|_k, v| it(*v))
    }
    pure fn each_ref(it: fn(key: &uint, value: &V) -> bool) {
        let mut idx = 0u, l = self.v.len();
        while idx < l {
            match self.v.get_elt(idx) {
              Some(ref elt) => if !it(&idx, elt) { break },
              None => ()
            }
            idx += 1u;
        }
    }
    pure fn each_key_ref(blk: fn(key: &uint) -> bool) {
        self.each_ref(|k, _v| blk(k))
    }
    pure fn each_value_ref(blk: fn(value: &V) -> bool) {
        self.each_ref(|_k, v| blk(v))
    }
}

impl<V: Copy> SmallIntMap<V>: ops::Index<uint, V> {
    pure fn index(&self, key: uint) -> V {
        unsafe {
            get(*self, key)
        }
    }
}

/// Cast the given smallintmap to a map::map
pub fn as_map<V: Copy>(s: SmallIntMap<V>) -> map::Map<uint, V> {
    s as map::Map::<uint, V>
}

#[cfg(test)]
mod tests {
    use smallintmap::{mk, SmallIntMap};

    use core::option::None;
    use core::option;

    #[test]
    fn test_insert_with_key() {
        let map: SmallIntMap<uint> = mk();

        // given a new key, initialize it with this new count, given
        // given an existing key, add more to its count
        fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        fn addMoreToCount_simple(v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        // count integers
        map.update(3, 1, addMoreToCount_simple);
        map.update_with_key(9, 1, addMoreToCount);
        map.update(3, 7, addMoreToCount_simple);
        map.update_with_key(5, 3, addMoreToCount);
        map.update_with_key(3, 2, addMoreToCount);

        // check the total counts
        assert 10 == option::get(map.find(3));
        assert  3 == option::get(map.find(5));
        assert  1 == option::get(map.find(9));

        // sadly, no sevens were counted
        assert None == map.find(7);
    }
}
<|endoftext|>


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

//! An implementation of the [Cap'n Proto remote procedure call](https://capnproto.org/rpc.html)
//! protocol. Includes all [Level 1](https://capnproto.org/rpc.html#protocol-features) features.
//!
//! # Example
//!
//! ```capnp
//! # Cap'n Proto schema
//! interface Foo {
//!     identity @0 (x: UInt32) -> (y: UInt32);
//! }
//! ```
//!
//! ```ignore
//! // Rust server defining an implementation of Foo.
//! struct FooImpl;
//! impl foo::Server for FooImpl {
//!     fn identity(&mut self,
//!                 params: foo::IdentityParams,
//!                 mut results: foo::IdentityResults)
//!                 -> Promise<(), ::capnp::Error>
//!     {
//!         let x = pry!(params.get()).get_x();
//!         results.get().set_y(x);
//!         Promise::ok(())
//!     }
//! }
//! ```
//!
//! ```ignore
//! // Rust client calling a remote implementation of Foo.
//! let mut request = foo_client.identity_request();
//! request.get().set_x(123);
//! let promise = request.send().promise.and_then(|response| {
//!     println!("results = {}", response.get()?.get_y());
//!     Ok(())
//! });
//! ```
//!
//! For a more complete example, see https://github.com/capnproto/capnproto-rust/tree/master/capnp-rpc/examples/calculator

use std::pin::Pin;
use std::task::{Context, Poll};
use futures::{Future, FutureExt, TryFutureExt};
use futures::channel::oneshot;
use capnp::Error;
use capnp::capability::Promise;
use capnp::private::capability::{ClientHook};
use std::cell::{RefCell};
use std::rc::{Rc};

use crate::task_set::TaskSet;
pub use crate::rpc::Disconnector;

/// Code generated from [rpc.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/rpc.capnp).
pub mod rpc_capnp;

/// Code generated from [rpc-twoparty.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/rpc-twoparty.capnp).
pub mod rpc_twoparty_capnp;

/// Like `try!()`, but for functions that return a `Promise<T, E>` rather than a `Result<T, E>`.
///
/// Unwraps a `Result<T, E>`. In the case of an error `Err(e)`, immediately returns from the
/// enclosing function with `Promise::err(e)`.
#[macro_export]
macro_rules! pry {
    ($expr:expr) => (
        match $expr {
            ::std::result::Result::Ok(val) => val,
            ::std::result::Result::Err(err) => {
                return ::capnp::capability::Promise::err(::std::convert::From::from(err))
            }
        })
}

mod broken;
mod local;
mod queued;
mod rpc;
mod attach;
mod sender_queue;
mod split;
mod task_set;
pub mod twoparty;

pub trait OutgoingMessage {
    fn get_body<'a>(&'a mut self) -> ::capnp::Result<::capnp::any_pointer::Builder<'a>>;
    fn get_body_as_reader<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>>;

    /// Sends the message. Returns a promise for the message that resolves once the send has completed.
    /// Dropping the returned promise does *not* cancel the send.
    fn send(self: Box<Self>)
            -> (Promise<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>, ::capnp::Error>,
                Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>);

    fn take(self: Box<Self>) -> ::capnp::message::Builder<::capnp::message::HeapAllocator>;
}

pub trait IncomingMessage {
    fn get_body<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>>;
}

pub trait Connection<VatId> {
    fn get_peer_vat_id(&self) -> VatId;
    fn new_outgoing_message(&mut self, first_segment_word_size: u32) -> Box<dyn OutgoingMessage>;

    /// Waits for a message to be received and returns it.  If the read stream cleanly terminates,
    /// returns None. If any other problem occurs, returns an Error.
    fn receive_incoming_message(&mut self) -> Promise<Option<Box<dyn IncomingMessage>>, Error>;

    // Waits until all outgoing messages have been sent, then shuts down the outgoing stream. The
    // returned promise resolves after shutdown is complete.
    fn shutdown(&mut self, result: ::capnp::Result<()>) -> Promise<(), Error>;
}

pub trait VatNetwork<VatId> {
    /// Returns None if `hostId` refers to the local vat.
    fn connect(&mut self, host_id: VatId) -> Option<Box<dyn Connection<VatId>>>;

    /// Waits for the next incoming connection and return it.
    fn accept(&mut self) -> Promise<Box<dyn Connection<VatId>>, ::capnp::Error>;

    fn drive_until_shutdown(&mut self) -> Promise<(), Error>;
}

/// A portal to objects available on the network.
///
/// The RPC implemententation sits on top of an implementation of `VatNetwork`, which
/// determines how to form connections between vats. The RPC implementation determines
/// how to use such connections to manage object references and make method calls.
///
/// At the moment, this is all rather more general than it needs to be, because the only
/// implementation of `VatNetwork` is `twoparty::VatNetwork`. However, eventually we
/// will need to have more sophisticated `VatNetwork` implementations, in order to support
/// [level 3](https://capnproto.org/rpc.html#protocol-features) features.
///
/// An `RpcSystem` is a `Future` and needs to be driven by a task executor. A common way
/// accomplish that is to pass the `RpcSystem` to `tokio_core::reactor::Handle::spawn()`.
#[must_use = "futures do nothing unless polled"]
pub struct RpcSystem<VatId> where VatId: 'static {
    network: Box<dyn crate::VatNetwork<VatId>>,

    bootstrap_cap: Box<dyn ClientHook>,

    // XXX To handle three or more party networks, this should be a map from connection pointers
    // to connection states.
    connection_state: Rc<RefCell<Option<Rc<rpc::ConnectionState<VatId>>>>>,

    tasks: TaskSet<Error>,
    handle: crate::task_set::TaskSetHandle<Error>
}

impl <VatId> RpcSystem <VatId> {
    /// Constructs a new `RpcSystem` with the given network and bootstrap capability.
    pub fn new(
        mut network: Box<dyn crate::VatNetwork<VatId>>,
        bootstrap: Option<::capnp::capability::Client>) -> RpcSystem<VatId>
    {
        let bootstrap_cap = match bootstrap {
            Some(cap) => cap.hook,
            None => broken::new_cap(Error::failed("no bootstrap capabiity".to_string())),
        };
        let (mut handle, tasks) = TaskSet::new(Box::new(SystemTaskReaper));

        let mut handle1 = handle.clone();
        handle.add(network.drive_until_shutdown().then(move |r| {
            let r = match r {
                Ok(()) => Ok(()),
                Err(e) => {
                    if e.kind != ::capnp::ErrorKind::Disconnected {
                        // Don't report disconnects as an error.
                        Err(e)
                    } else {
                        Ok(())
                    }
                }
            };

            handle1.terminate(r);
            Promise::ok(())
        }));

        let mut result = RpcSystem {
            network: network,
            bootstrap_cap: bootstrap_cap,
            connection_state: Rc::new(RefCell::new(None)),

            tasks: tasks,
            handle: handle.clone(),
        };

        let accept_loop = result.accept_loop();
        handle.add(accept_loop);
        result
    }

    /// Connects to the given vat and returns its bootstrap interface.
    pub fn bootstrap<T>(&mut self, vat_id: VatId) -> T
        where T: ::capnp::capability::FromClientHook
    {
        let connection = match self.network.connect(vat_id) {
            Some(connection) => connection,
            None => {
                return T::new(self.bootstrap_cap.clone());
            }
        };
        let connection_state =
            RpcSystem::get_connection_state(self.connection_state.clone(),
                                            self.bootstrap_cap.clone(),
                                            connection, self.handle.clone());

        let hook = rpc::ConnectionState::bootstrap(connection_state.clone());
        T::new(hook)
    }

    // not really a loop, because it doesn't need to be for the two party case
    fn accept_loop(&mut self) -> Promise<(), Error> {
        let connection_state_ref = self.connection_state.clone();
        let bootstrap_cap = self.bootstrap_cap.clone();
        let handle = self.handle.clone();
        Promise::from_future(self.network.accept().map_ok(move |connection| {
            RpcSystem::get_connection_state(connection_state_ref,
                                            bootstrap_cap,
                                            connection,
                                            handle);
        }))
    }

    fn get_connection_state(connection_state_ref: Rc<RefCell<Option<Rc<rpc::ConnectionState<VatId>>>>>,
                            bootstrap_cap: Box<dyn ClientHook>,
                            connection: Box<dyn crate::Connection<VatId>>,
                            mut handle: crate::task_set::TaskSetHandle<Error>)
                            -> Rc<rpc::ConnectionState<VatId>>
    {
        // TODO this needs to be updated once we allow more general VatNetworks.
        let (tasks, result) = match *connection_state_ref.borrow() {
            Some(ref connection_state) => {
                // return early.
                return connection_state.clone()
            }
            None => {
                let (on_disconnect_fulfiller, on_disconnect_promise) =
                    oneshot::channel::<Promise<(), Error>>();
                let connection_state_ref1 = connection_state_ref.clone();
                handle.add(on_disconnect_promise.then(move |shutdown_promise| {
                    *connection_state_ref1.borrow_mut() = None;
                    match shutdown_promise {
                        Ok(s) => s,
                        Err(e) => Promise::err(Error::failed(format!("{}", e))),
                    }
                }));
                rpc::ConnectionState::new(bootstrap_cap, connection, on_disconnect_fulfiller)
            }
        };
        *connection_state_ref.borrow_mut() = Some(result.clone());
        handle.add(tasks);
        result
    }

    /// Returns a `Disconnector` future that can be run to cleanly close the connection to this `RpcSystem`'s network.
    /// You should get the `Disconnector` before you spawn the `RpcSystem`.
    pub fn get_disconnector(&self) -> rpc::Disconnector<VatId> {
        rpc::Disconnector::new(self.connection_state.clone())
    }
}

impl <VatId> Future for RpcSystem<VatId> where VatId: 'static {
    type Output = Result<(),Error>;
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        Pin::new(&mut self.tasks).poll(cx)
    }
}

/// Creates a new local RPC client of type `C` out of an object that implements a server trait `S`.
pub fn new_client<C, S>(s: S) -> C where C: capnp::capability::FromServer<S> {
    capnp::capability::FromClientHook::new(Box::new(
        local::Client::new(Box::new(<C as capnp::capability::FromServer::<S>>::from_server(s)))))
}

/// Converts a promise for a client into a client that queues up any calls that arrive
/// before the promise resolves.
// TODO: figure out a better way to allow construction of promise clients.
pub fn new_promise_client<T, F>(client_promise: F) -> T
    where T: ::capnp::capability::FromClientHook,
          F: ::futures::Future<Output=Result<capnp::capability::Client,Error>>,
          F: 'static + Unpin
{
    let mut queued_client = crate::queued::Client::new(None);
    let weak_client = Rc::downgrade(&queued_client.inner);

    queued_client.drive(client_promise.then(move |r| {
        if let Some(queued_inner) = weak_client.upgrade() {
            crate::queued::ClientInner::resolve(&queued_inner, r.map(|c| c.hook));
        }
        Promise::ok(())
    }));

    T::new(Box::new(queued_client))
}

struct SystemTaskReaper;
impl crate::task_set::TaskReaper<Error> for SystemTaskReaper {
    fn task_failed(&mut self, error: Error) {
        println!("ERROR: {}", error);
    }
}

pub struct ImbuedMessageBuilder<A> where A: ::capnp::message::Allocator {
    builder: ::capnp::message::Builder<A>,
    cap_table: Vec<Option<Box<dyn (::capnp::private::capability::ClientHook)>>>,
}

impl <A> ImbuedMessageBuilder<A> where A: ::capnp::message::Allocator {
    pub fn new(allocator: A) -> Self {
        ImbuedMessageBuilder {
            builder: ::capnp::message::Builder::new(allocator),
            cap_table: Vec::new(),
        }
    }

    pub fn get_root<'a, T>(&'a mut self) -> ::capnp::Result<T>
        where T: ::capnp::traits::FromPointerBuilder<'a>
    {
        use capnp::traits::ImbueMut;
        let mut root: ::capnp::any_pointer::Builder = self.builder.get_root()?;
        root.imbue_mut(&mut self.cap_table);
        root.get_as()
    }

    pub fn set_root<To, From>(&mut self, value: From) -> ::capnp::Result<()>
        where From: ::capnp::traits::SetPointerBuilder<To>
    {
        use capnp::traits::ImbueMut;
        let mut root: ::capnp::any_pointer::Builder = self.builder.get_root()?;
        root.imbue_mut(&mut self.cap_table);
        root.set_as(value)
    }
}

fn canceled_to_error(_e: futures::channel::oneshot::Canceled) -> Error {
        Error::failed(format!("oneshot was canceled"))
}
<commit_msg>fix typo: capabiity -> capability<commit_after>// Copyright (c) 2013-2017 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! An implementation of the [Cap'n Proto remote procedure call](https://capnproto.org/rpc.html)
//! protocol. Includes all [Level 1](https://capnproto.org/rpc.html#protocol-features) features.
//!
//! # Example
//!
//! ```capnp
//! # Cap'n Proto schema
//! interface Foo {
//!     identity @0 (x: UInt32) -> (y: UInt32);
//! }
//! ```
//!
//! ```ignore
//! // Rust server defining an implementation of Foo.
//! struct FooImpl;
//! impl foo::Server for FooImpl {
//!     fn identity(&mut self,
//!                 params: foo::IdentityParams,
//!                 mut results: foo::IdentityResults)
//!                 -> Promise<(), ::capnp::Error>
//!     {
//!         let x = pry!(params.get()).get_x();
//!         results.get().set_y(x);
//!         Promise::ok(())
//!     }
//! }
//! ```
//!
//! ```ignore
//! // Rust client calling a remote implementation of Foo.
//! let mut request = foo_client.identity_request();
//! request.get().set_x(123);
//! let promise = request.send().promise.and_then(|response| {
//!     println!("results = {}", response.get()?.get_y());
//!     Ok(())
//! });
//! ```
//!
//! For a more complete example, see https://github.com/capnproto/capnproto-rust/tree/master/capnp-rpc/examples/calculator

use std::pin::Pin;
use std::task::{Context, Poll};
use futures::{Future, FutureExt, TryFutureExt};
use futures::channel::oneshot;
use capnp::Error;
use capnp::capability::Promise;
use capnp::private::capability::{ClientHook};
use std::cell::{RefCell};
use std::rc::{Rc};

use crate::task_set::TaskSet;
pub use crate::rpc::Disconnector;

/// Code generated from [rpc.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/rpc.capnp).
pub mod rpc_capnp;

/// Code generated from [rpc-twoparty.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/rpc-twoparty.capnp).
pub mod rpc_twoparty_capnp;

/// Like `try!()`, but for functions that return a `Promise<T, E>` rather than a `Result<T, E>`.
///
/// Unwraps a `Result<T, E>`. In the case of an error `Err(e)`, immediately returns from the
/// enclosing function with `Promise::err(e)`.
#[macro_export]
macro_rules! pry {
    ($expr:expr) => (
        match $expr {
            ::std::result::Result::Ok(val) => val,
            ::std::result::Result::Err(err) => {
                return ::capnp::capability::Promise::err(::std::convert::From::from(err))
            }
        })
}

mod broken;
mod local;
mod queued;
mod rpc;
mod attach;
mod sender_queue;
mod split;
mod task_set;
pub mod twoparty;

pub trait OutgoingMessage {
    fn get_body<'a>(&'a mut self) -> ::capnp::Result<::capnp::any_pointer::Builder<'a>>;
    fn get_body_as_reader<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>>;

    /// Sends the message. Returns a promise for the message that resolves once the send has completed.
    /// Dropping the returned promise does *not* cancel the send.
    fn send(self: Box<Self>)
            -> (Promise<Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>, ::capnp::Error>,
                Rc<::capnp::message::Builder<::capnp::message::HeapAllocator>>);

    fn take(self: Box<Self>) -> ::capnp::message::Builder<::capnp::message::HeapAllocator>;
}

pub trait IncomingMessage {
    fn get_body<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>>;
}

pub trait Connection<VatId> {
    fn get_peer_vat_id(&self) -> VatId;
    fn new_outgoing_message(&mut self, first_segment_word_size: u32) -> Box<dyn OutgoingMessage>;

    /// Waits for a message to be received and returns it.  If the read stream cleanly terminates,
    /// returns None. If any other problem occurs, returns an Error.
    fn receive_incoming_message(&mut self) -> Promise<Option<Box<dyn IncomingMessage>>, Error>;

    // Waits until all outgoing messages have been sent, then shuts down the outgoing stream. The
    // returned promise resolves after shutdown is complete.
    fn shutdown(&mut self, result: ::capnp::Result<()>) -> Promise<(), Error>;
}

pub trait VatNetwork<VatId> {
    /// Returns None if `hostId` refers to the local vat.
    fn connect(&mut self, host_id: VatId) -> Option<Box<dyn Connection<VatId>>>;

    /// Waits for the next incoming connection and return it.
    fn accept(&mut self) -> Promise<Box<dyn Connection<VatId>>, ::capnp::Error>;

    fn drive_until_shutdown(&mut self) -> Promise<(), Error>;
}

/// A portal to objects available on the network.
///
/// The RPC implemententation sits on top of an implementation of `VatNetwork`, which
/// determines how to form connections between vats. The RPC implementation determines
/// how to use such connections to manage object references and make method calls.
///
/// At the moment, this is all rather more general than it needs to be, because the only
/// implementation of `VatNetwork` is `twoparty::VatNetwork`. However, eventually we
/// will need to have more sophisticated `VatNetwork` implementations, in order to support
/// [level 3](https://capnproto.org/rpc.html#protocol-features) features.
///
/// An `RpcSystem` is a `Future` and needs to be driven by a task executor. A common way
/// accomplish that is to pass the `RpcSystem` to `tokio_core::reactor::Handle::spawn()`.
#[must_use = "futures do nothing unless polled"]
pub struct RpcSystem<VatId> where VatId: 'static {
    network: Box<dyn crate::VatNetwork<VatId>>,

    bootstrap_cap: Box<dyn ClientHook>,

    // XXX To handle three or more party networks, this should be a map from connection pointers
    // to connection states.
    connection_state: Rc<RefCell<Option<Rc<rpc::ConnectionState<VatId>>>>>,

    tasks: TaskSet<Error>,
    handle: crate::task_set::TaskSetHandle<Error>
}

impl <VatId> RpcSystem <VatId> {
    /// Constructs a new `RpcSystem` with the given network and bootstrap capability.
    pub fn new(
        mut network: Box<dyn crate::VatNetwork<VatId>>,
        bootstrap: Option<::capnp::capability::Client>) -> RpcSystem<VatId>
    {
        let bootstrap_cap = match bootstrap {
            Some(cap) => cap.hook,
            None => broken::new_cap(Error::failed("no bootstrap capability".to_string())),
        };
        let (mut handle, tasks) = TaskSet::new(Box::new(SystemTaskReaper));

        let mut handle1 = handle.clone();
        handle.add(network.drive_until_shutdown().then(move |r| {
            let r = match r {
                Ok(()) => Ok(()),
                Err(e) => {
                    if e.kind != ::capnp::ErrorKind::Disconnected {
                        // Don't report disconnects as an error.
                        Err(e)
                    } else {
                        Ok(())
                    }
                }
            };

            handle1.terminate(r);
            Promise::ok(())
        }));

        let mut result = RpcSystem {
            network: network,
            bootstrap_cap: bootstrap_cap,
            connection_state: Rc::new(RefCell::new(None)),

            tasks: tasks,
            handle: handle.clone(),
        };

        let accept_loop = result.accept_loop();
        handle.add(accept_loop);
        result
    }

    /// Connects to the given vat and returns its bootstrap interface.
    pub fn bootstrap<T>(&mut self, vat_id: VatId) -> T
        where T: ::capnp::capability::FromClientHook
    {
        let connection = match self.network.connect(vat_id) {
            Some(connection) => connection,
            None => {
                return T::new(self.bootstrap_cap.clone());
            }
        };
        let connection_state =
            RpcSystem::get_connection_state(self.connection_state.clone(),
                                            self.bootstrap_cap.clone(),
                                            connection, self.handle.clone());

        let hook = rpc::ConnectionState::bootstrap(connection_state.clone());
        T::new(hook)
    }

    // not really a loop, because it doesn't need to be for the two party case
    fn accept_loop(&mut self) -> Promise<(), Error> {
        let connection_state_ref = self.connection_state.clone();
        let bootstrap_cap = self.bootstrap_cap.clone();
        let handle = self.handle.clone();
        Promise::from_future(self.network.accept().map_ok(move |connection| {
            RpcSystem::get_connection_state(connection_state_ref,
                                            bootstrap_cap,
                                            connection,
                                            handle);
        }))
    }

    fn get_connection_state(connection_state_ref: Rc<RefCell<Option<Rc<rpc::ConnectionState<VatId>>>>>,
                            bootstrap_cap: Box<dyn ClientHook>,
                            connection: Box<dyn crate::Connection<VatId>>,
                            mut handle: crate::task_set::TaskSetHandle<Error>)
                            -> Rc<rpc::ConnectionState<VatId>>
    {
        // TODO this needs to be updated once we allow more general VatNetworks.
        let (tasks, result) = match *connection_state_ref.borrow() {
            Some(ref connection_state) => {
                // return early.
                return connection_state.clone()
            }
            None => {
                let (on_disconnect_fulfiller, on_disconnect_promise) =
                    oneshot::channel::<Promise<(), Error>>();
                let connection_state_ref1 = connection_state_ref.clone();
                handle.add(on_disconnect_promise.then(move |shutdown_promise| {
                    *connection_state_ref1.borrow_mut() = None;
                    match shutdown_promise {
                        Ok(s) => s,
                        Err(e) => Promise::err(Error::failed(format!("{}", e))),
                    }
                }));
                rpc::ConnectionState::new(bootstrap_cap, connection, on_disconnect_fulfiller)
            }
        };
        *connection_state_ref.borrow_mut() = Some(result.clone());
        handle.add(tasks);
        result
    }

    /// Returns a `Disconnector` future that can be run to cleanly close the connection to this `RpcSystem`'s network.
    /// You should get the `Disconnector` before you spawn the `RpcSystem`.
    pub fn get_disconnector(&self) -> rpc::Disconnector<VatId> {
        rpc::Disconnector::new(self.connection_state.clone())
    }
}

impl <VatId> Future for RpcSystem<VatId> where VatId: 'static {
    type Output = Result<(),Error>;
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        Pin::new(&mut self.tasks).poll(cx)
    }
}

/// Creates a new local RPC client of type `C` out of an object that implements a server trait `S`.
pub fn new_client<C, S>(s: S) -> C where C: capnp::capability::FromServer<S> {
    capnp::capability::FromClientHook::new(Box::new(
        local::Client::new(Box::new(<C as capnp::capability::FromServer::<S>>::from_server(s)))))
}

/// Converts a promise for a client into a client that queues up any calls that arrive
/// before the promise resolves.
// TODO: figure out a better way to allow construction of promise clients.
pub fn new_promise_client<T, F>(client_promise: F) -> T
    where T: ::capnp::capability::FromClientHook,
          F: ::futures::Future<Output=Result<capnp::capability::Client,Error>>,
          F: 'static + Unpin
{
    let mut queued_client = crate::queued::Client::new(None);
    let weak_client = Rc::downgrade(&queued_client.inner);

    queued_client.drive(client_promise.then(move |r| {
        if let Some(queued_inner) = weak_client.upgrade() {
            crate::queued::ClientInner::resolve(&queued_inner, r.map(|c| c.hook));
        }
        Promise::ok(())
    }));

    T::new(Box::new(queued_client))
}

struct SystemTaskReaper;
impl crate::task_set::TaskReaper<Error> for SystemTaskReaper {
    fn task_failed(&mut self, error: Error) {
        println!("ERROR: {}", error);
    }
}

pub struct ImbuedMessageBuilder<A> where A: ::capnp::message::Allocator {
    builder: ::capnp::message::Builder<A>,
    cap_table: Vec<Option<Box<dyn (::capnp::private::capability::ClientHook)>>>,
}

impl <A> ImbuedMessageBuilder<A> where A: ::capnp::message::Allocator {
    pub fn new(allocator: A) -> Self {
        ImbuedMessageBuilder {
            builder: ::capnp::message::Builder::new(allocator),
            cap_table: Vec::new(),
        }
    }

    pub fn get_root<'a, T>(&'a mut self) -> ::capnp::Result<T>
        where T: ::capnp::traits::FromPointerBuilder<'a>
    {
        use capnp::traits::ImbueMut;
        let mut root: ::capnp::any_pointer::Builder = self.builder.get_root()?;
        root.imbue_mut(&mut self.cap_table);
        root.get_as()
    }

    pub fn set_root<To, From>(&mut self, value: From) -> ::capnp::Result<()>
        where From: ::capnp::traits::SetPointerBuilder<To>
    {
        use capnp::traits::ImbueMut;
        let mut root: ::capnp::any_pointer::Builder = self.builder.get_root()?;
        root.imbue_mut(&mut self.cap_table);
        root.set_as(value)
    }
}

fn canceled_to_error(_e: futures::channel::oneshot::Canceled) -> Error {
        Error::failed(format!("oneshot was canceled"))
}
<|endoftext|>


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

// extern crate core;

use kl25z_map::Sim;
use kl25z_map::Port;
use kl25z_map::Osc0;
use kl25z_map::Mcg;

use core::option::*;

extern {
    fn __StackTop();

    static     __etext : u32;
    static mut __data_start__  : u32;
    static mut __data_end__ : u32;
    static mut __bss_start__   : u32;
    static mut __bss_end__  : u32;
}

#[link_section=".vector_table"]
pub static ISR_VECTOR: [Option<unsafe extern fn()>, .. 16] = [
  Option::Some(__StackTop),
  Option::Some(reset_handler),
  Option::Some(nmi_handler),
  Option::Some(hardfault_handler),
  Option::None,
  Option::None,
  Option::None,
  Option::None,
  Option::None,
  Option::None,
  Option::None,
  Option::Some(svc_handler),
  Option::None,
  Option::None,
  Option::Some(pendsv_handler),
  Option::Some(systick_handler),
];

#[link_section=".flash_configuration"]
pub static FLASH_CONFIG_FIELD: [u32, ..4] = [
    0xFFFFFFFF,
    0xFFFFFFFF,
    0xFFFFFFFF,
    0xFFFFFFFE,
];

#[no_mangle]
pub unsafe extern "C" fn reset_handler() {
    let sim = Sim::get();
    sim.copc.set(0x0);

    let mut bss  = &mut __bss_start__  as *mut u32;
    let ebss = &mut __bss_end__ as *mut u32;

    while bss < ebss {
        *bss = 0;
        bss = ((bss as u32) + 4) as *mut u32;
    }

    let mut data  = &mut __data_start__  as *mut u32;
    let     edata = &mut __data_end__ as *mut u32;
    let mut etext = &    __etext as *const u32;

    while data < edata {
        *data = *etext;
        data  = ((data as u32)  + 4) as *mut u32;
        etext = ((etext as u32) + 4) as *const u32;
    }

    system_init();
    ::main();
}

#[no_mangle]
pub unsafe extern "C" fn nmi_handler() {
    abort();
}

#[no_mangle]
pub unsafe extern "C" fn hardfault_handler() {
    abort();
}

#[no_mangle]
pub unsafe extern "C" fn svc_handler() {
    abort();
}

#[no_mangle]
pub unsafe extern "C" fn pendsv_handler() {
    abort();
}

#[no_mangle]
pub unsafe extern "C" fn systick_handler() {
    abort();
}

pub fn system_init()
{
    let sim = Sim::get();
    sim.scgc5.bitwise_inc_or(0x0200);
    sim.clkdiv1.set(0x10010000);
    let porta = Port::get(0);
    porta.pcr[18].bitwise_and(-0x01000700);
    porta.pcr[19].bitwise_and(-0x01000700);
    let osc0 = Osc0::get();
    osc0.cr.set(0x89);
    let mcg = Mcg::get();
    mcg.c2.set(0x24);
    mcg.c1.set(0x9A);
    mcg.c4.bitwise_and_u8(-0xE0);
    mcg.c5.set(0x1);
    mcg.c6.set(0x0);
    while (mcg.s.get() & 0x10) != 0x0 {};
    while (mcg.s.get() & 0x0C) != 0x08 {};
    mcg.c6.set(0x40);
    while (mcg.s.get() & 0x0C) != 0x08 {};
    while (mcg.s.get() & 0x40) == 0x00 {};
    mcg.c1.set(0x1A);
    while (mcg.s.get() & 0x0C) != 0x0C {};
}

#[doc(hidden)]
#[no_mangle]
pub extern fn __aeabi_unwind_cpp_pr0() {
    abort();
}

#[doc(hidden)]
#[no_mangle]
pub extern fn __aeabi_unwind_cpp_pr1() {
    abort();
}

#[no_mangle]
pub extern fn abort() -> ! {
    loop {}
}
<commit_msg>fn is an unique type (as in used in Option<>)<commit_after>// Copyright 2014 Martin Kojtal (0xc0170)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// extern crate core;

use kl25z_map::Sim;
use kl25z_map::Port;
use kl25z_map::Osc0;
use kl25z_map::Mcg;

use core::option::*;

extern {
    fn __StackTop();

    static     __etext : u32;
    static mut __data_start__  : u32;
    static mut __data_end__ : u32;
    static mut __bss_start__   : u32;
    static mut __bss_end__  : u32;
}

#[link_section=".vector_table"]
pub static ISR_VECTOR: [Option<unsafe extern fn()>, .. 16] = [
  Option::Some(__StackTop),
  Option::Some(reset_handler as unsafe extern fn()),
  Option::Some(nmi_handler as unsafe extern fn()),
  Option::Some(hardfault_handler as unsafe extern fn()),
  Option::None,
  Option::None,
  Option::None,
  Option::None,
  Option::None,
  Option::None,
  Option::None,
  Option::Some(svc_handler as unsafe extern fn()),
  Option::None,
  Option::None,
  Option::Some(pendsv_handler as unsafe extern fn()),
  Option::Some(systick_handler as unsafe extern fn()),
];

#[link_section=".flash_configuration"]
pub static FLASH_CONFIG_FIELD: [u32, ..4] = [
    0xFFFFFFFF,
    0xFFFFFFFF,
    0xFFFFFFFF,
    0xFFFFFFFE,
];

#[no_mangle]
pub unsafe extern "C" fn reset_handler() {
    let sim = Sim::get();
    sim.copc.set(0x0);

    let mut bss  = &mut __bss_start__  as *mut u32;
    let ebss = &mut __bss_end__ as *mut u32;

    while bss < ebss {
        *bss = 0;
        bss = ((bss as u32) + 4) as *mut u32;
    }

    let mut data  = &mut __data_start__  as *mut u32;
    let     edata = &mut __data_end__ as *mut u32;
    let mut etext = &    __etext as *const u32;

    while data < edata {
        *data = *etext;
        data  = ((data as u32)  + 4) as *mut u32;
        etext = ((etext as u32) + 4) as *const u32;
    }

    system_init();
    ::main();
}

#[no_mangle]
pub unsafe extern "C" fn nmi_handler() {
    abort();
}

#[no_mangle]
pub unsafe extern "C" fn hardfault_handler() {
    abort();
}

#[no_mangle]
pub unsafe extern "C" fn svc_handler() {
    abort();
}

#[no_mangle]
pub unsafe extern "C" fn pendsv_handler() {
    abort();
}

#[no_mangle]
pub unsafe extern "C" fn systick_handler() {
    abort();
}

pub fn system_init()
{
    let sim = Sim::get();
    sim.scgc5.bitwise_inc_or(0x0200);
    sim.clkdiv1.set(0x10010000);
    let porta = Port::get(0);
    porta.pcr[18].bitwise_and(-0x01000700);
    porta.pcr[19].bitwise_and(-0x01000700);
    let osc0 = Osc0::get();
    osc0.cr.set(0x89);
    let mcg = Mcg::get();
    mcg.c2.set(0x24);
    mcg.c1.set(0x9A);
    mcg.c4.bitwise_and_u8(-0xE0);
    mcg.c5.set(0x1);
    mcg.c6.set(0x0);
    while (mcg.s.get() & 0x10) != 0x0 {};
    while (mcg.s.get() & 0x0C) != 0x08 {};
    mcg.c6.set(0x40);
    while (mcg.s.get() & 0x0C) != 0x08 {};
    while (mcg.s.get() & 0x40) == 0x00 {};
    mcg.c1.set(0x1A);
    while (mcg.s.get() & 0x0C) != 0x0C {};
}

#[doc(hidden)]
#[no_mangle]
pub extern fn __aeabi_unwind_cpp_pr0() {
    abort();
}

#[doc(hidden)]
#[no_mangle]
pub extern fn __aeabi_unwind_cpp_pr1() {
    abort();
}

#[no_mangle]
pub extern fn abort() -> ! {
    loop {}
}
<|endoftext|>


<commit_before>use dsp::Node;
use dsp::sample::frame::Mono;
use dsp::sample::signal;
use dsp::sample::signal::{Sine, ConstHz};
use dsp::sample::{Frame, slice};
use envelope::{Envelope, Point};
use envelope_lib::Envelope as Trait;
use time_calc::{SampleHz, Ms, Samples};
use std::f64;

pub type PadIdx = usize;
pub type Velocity = f64;
pub type Volume = f64;
pub type AudioOut = Mono<f64>;

struct PadState {
    /// Is the pad active.
    active: bool,
    /// The time that the pad has been active.
    active_time: Ms,
    /// The velocity this pad was triggered with.
    vel: Velocity,
    /// The duration of the active state.
    duration: Ms,
    /// The amplitude envelope of this pad.
    amp_env: Envelope,
}

impl PadState {
    fn new() -> Self {
        let amp_env = Envelope::from(vec!(
            //         Time ,  Amp ,  Curve
            Point::new(0.0  ,  0.1 ,  0.0),
            Point::new(0.01 ,  1.0 ,  0.0),
            Point::new(0.25 ,  0.8 ,  0.0),
            Point::new(0.75 ,  0.2 ,  0.0),
            Point::new(1.0  ,  0.0 ,  0.0),
        ));

        PadState {
            active: false,
            active_time: Ms(0.0),
            vel: 0.0,
            duration: Ms(1_000.0),
            amp_env: amp_env,
        }
    }

    /// Trigger a sound.
    fn trigger(&mut self, vel: Velocity) {
        self.active = true;
        self.vel = vel;
    }

    /// Deactivate.
    fn silence(&mut self) {
        self.active = false;
        self.active_time = Ms(0.0);
        self.vel = 0.0;
    }

    /// Get the next amplitude multiplier
    fn next_amp(&mut self, sample_hz: SampleHz) -> f64 {
        // Step forward by the sample rate
        self.active_time = self.active_time + Samples(1).to_ms(sample_hz);
        let perc = self.active_time.ms() / self.duration.ms();

        if perc > 1.0 {
            self.silence();
            0.0
        } else {
            self.amp_env.y(perc).unwrap()
        }
    }

    /// Get the next audio frame.
    fn next_frame(&mut self, sample_hz: SampleHz) -> AudioOut {
        if !self.active {
            AudioOut::equilibrium()
        } else {
            // TODO: sound generator
            [1.0 * self.next_amp(sample_hz)]
        }
    }
}

pub struct Machine {
    /// Amplitude multiplier (volume).
    pub volume: Volume,
    /// Render playback or not.
    pub is_paused: bool,
    /// The states of the pads that generate sound for the machine.
    pads: Vec<PadState>,
}

impl Machine {
    /// Constructor for a new drum machine.
    pub fn new() -> Self {;
        Machine {
            volume: 1.0,
            is_paused: false,
            pads: vec![PadState::new()],
        }
    }

    /// Trigger a pad.
    pub fn trigger(&mut self, pad: PadIdx, vel: Velocity) {
        if pad <= self.pads.len() {
            self.pads[pad - 1].trigger(vel);
        }
    }

    /// Deactivate a pad.
    pub fn silence(&mut self, pad: PadIdx) {
        if pad <= self.pads.len() {
            self.pads[pad - 1].silence();
        }
    }

    /// Pause playback.
    pub fn pause(&mut self) {
        self.is_paused = true;
    }

    /// Unpause playback.
    pub fn unpause(&mut self) {
        self.is_paused = false;
    }

    /// Stop playback and clear the current pads.
    pub fn stop(&mut self) {
        for pad in &mut self.pads {
            pad.silence();
        }
    }

    /// Get the next audio frame.
    pub fn next_frame(&mut self, sample_hz: SampleHz) -> AudioOut {
        if self.is_paused {
            AudioOut::equilibrium()
        } else {
            self.pads.iter_mut().fold(AudioOut::equilibrium(),
                                      |f, pad| f.add_amp(pad.next_frame(sample_hz)))
        }
    }
}

impl Node<AudioOut> for Machine {
    fn audio_requested(&mut self, buffer: &mut [AudioOut], sample_hz: SampleHz) {
        slice::map_in_place(buffer, |_| self.next_frame(sample_hz));
    }
}
<commit_msg>Scale with velocity and volume<commit_after>use dsp::Node;
use dsp::sample::frame::Mono;
use dsp::sample::{Frame, slice};
use envelope::{Envelope, Point};
use envelope_lib::Envelope as Trait;
use time_calc::{SampleHz, Ms, Samples};
use std::f64;

pub type PadIdx = usize;
pub type Velocity = f64;
pub type Volume = f64;
pub type AudioOut = Mono<f64>;

struct PadState {
    /// Is the pad active.
    active: bool,
    /// The time that the pad has been active.
    active_time: Ms,
    /// The velocity this pad was triggered with.
    vel: Velocity,
    /// The duration of the active state.
    duration: Ms,
    /// The amplitude envelope of this pad.
    amp_env: Envelope,
}

impl PadState {
    fn new() -> Self {
        let amp_env = Envelope::from(vec!(
            //         Time ,  Amp ,  Curve
            Point::new(0.0  ,  0.1 ,  0.0),
            Point::new(0.01 ,  1.0 ,  0.0),
            Point::new(0.25 ,  0.8 ,  0.0),
            Point::new(0.75 ,  0.2 ,  0.0),
            Point::new(1.0  ,  0.0 ,  0.0),
        ));

        PadState {
            active: false,
            active_time: Ms(0.0),
            vel: 0.0,
            duration: Ms(1_000.0),
            amp_env: amp_env,
        }
    }

    /// Trigger a sound.
    fn trigger(&mut self, vel: Velocity) {
        self.active = true;
        self.vel = vel;
    }

    /// Deactivate.
    fn silence(&mut self) {
        self.active = false;
        self.active_time = Ms(0.0);
        self.vel = 0.0;
    }

    /// Get the next amplitude multiplier
    fn next_amp(&mut self, sample_hz: SampleHz) -> f64 {
        // Step forward by the sample rate
        self.active_time = self.active_time + Samples(1).to_ms(sample_hz);
        let perc = self.active_time.ms() / self.duration.ms();

        if perc > 1.0 {
            self.silence();
            0.0
        } else {
            self.amp_env.y(perc).unwrap()
        }
    }

    /// Get the next audio frame.
    fn next_frame(&mut self, sample_hz: SampleHz) -> AudioOut {
        if !self.active {
            AudioOut::equilibrium()
        } else {
            // TODO: sound generator
            [1.0 * self.vel * self.next_amp(sample_hz)]
        }
    }
}

pub struct Machine {
    /// Amplitude multiplier (volume).
    pub volume: Volume,
    /// Render playback or not.
    pub is_paused: bool,
    /// The states of the pads that generate sound for the machine.
    pads: Vec<PadState>,
}

impl Machine {
    /// Constructor for a new drum machine.
    pub fn new() -> Self {;
        Machine {
            volume: 1.0,
            is_paused: false,
            pads: vec![PadState::new()],
        }
    }

    /// Trigger a pad.
    pub fn trigger(&mut self, pad: PadIdx, vel: Velocity) {
        if pad <= self.pads.len() {
            self.pads[pad - 1].trigger(vel);
        }
    }

    /// Deactivate a pad.
    pub fn silence(&mut self, pad: PadIdx) {
        if pad <= self.pads.len() {
            self.pads[pad - 1].silence();
        }
    }

    /// Pause playback.
    pub fn pause(&mut self) {
        self.is_paused = true;
    }

    /// Unpause playback.
    pub fn unpause(&mut self) {
        self.is_paused = false;
    }

    /// Stop playback and clear the current pads.
    pub fn stop(&mut self) {
        for pad in &mut self.pads {
            pad.silence();
        }
    }

    /// Get the next audio frame.
    pub fn next_frame(&mut self, sample_hz: SampleHz) -> AudioOut {
        if self.is_paused {
            AudioOut::equilibrium()
        } else {
            self.pads
                .iter_mut()
                .fold(AudioOut::equilibrium(),
                      |f, pad| f.add_amp(pad.next_frame(sample_hz)))
                .scale_amp(self.volume)
        }
    }
}

impl Node<AudioOut> for Machine {
    fn audio_requested(&mut self, buffer: &mut [AudioOut], sample_hz: SampleHz) {
        slice::map_in_place(buffer, |_| self.next_frame(sample_hz));
    }
}
<|endoftext|>


<commit_before>//! Elements of the WebAssembly binary format.

use std::error;
use std::fmt;
use std::io;

macro_rules! buffered_read {
	($buffer_size: expr, $length: expr, $reader: expr) => {
		{
			let mut vec_buf = Vec::new();
			let mut total_read = 0;
			let mut buf = [0u8; $buffer_size];
			while total_read < $length {
				let next_to_read = if $length - total_read > $buffer_size { $buffer_size } else { $length - total_read };
				$reader.read_exact(&mut buf[0..next_to_read])?;
				vec_buf.extend_from_slice(&buf[0..next_to_read]);
				total_read += next_to_read;
			}
			vec_buf
		}
	}
}

mod primitives;
mod module;
mod section;
mod types;
mod import_entry;
mod export_entry;
mod global_entry;
mod ops;
mod func;
mod segment;
mod index_map;
mod name_section;

pub use self::module::{Module, peek_size, ImportCountType};
pub use self::section::{
	Section, FunctionSection, CodeSection, MemorySection, DataSection,
	ImportSection, ExportSection, GlobalSection, TypeSection, ElementSection,
	TableSection, CustomSection,
};
pub use self::import_entry::{ImportEntry, ResizableLimits, MemoryType, TableType, GlobalType, External};
pub use self::export_entry::{ExportEntry, Internal};
pub use self::global_entry::GlobalEntry;
pub use self::primitives::{
	VarUint32, VarUint7, Uint8, VarUint1, VarInt7, Uint32, VarInt32, VarInt64,
	Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
};
pub use self::types::{Type, ValueType, BlockType, FunctionType, TableElementType};
pub use self::ops::{Opcode, Opcodes, InitExpr};
pub use self::func::{Func, FuncBody, Local};
pub use self::segment::{ElementSegment, DataSegment};
pub use self::index_map::IndexMap;
pub use self::name_section::{
	NameMap, NameSection, ModuleNameSection, FunctionNameSection,
	LocalNameSection,
};

/// Deserialization from serial i/o
pub trait Deserialize : Sized {
	/// Serialization error produced by deserialization routine.
	type Error: From<io::Error>;
	/// Deserialize type from serial i/o
	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
}

/// Serialization to serial i/o
pub trait Serialize {
	/// Serialization error produced by serialization routine.
	type Error: From<io::Error>;
	/// Serialize type to serial i/o
	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
}

/// Deserialization/serialization error
#[derive(Debug, Clone)]
pub enum Error {
	/// Unexpected end of input
	UnexpectedEof,
	/// Invalid magic
	InvalidMagic,
	/// Unsupported version
	UnsupportedVersion(u32),
	/// Inconsistence between declared and actual length
	InconsistentLength {
		/// Expected length of the definition
		expected: usize,
		/// Actual length of the definition
		actual: usize
	},
	/// Other static error
	Other(&'static str),
	/// Other allocated error
	HeapOther(String),
	/// Invalid/unknown value type declaration
	UnknownValueType(i8),
	/// Invalid/unknown table element type declaration
	UnknownTableElementType(i8),
	/// Non-utf8 string
	NonUtf8String,
	/// Unknown external kind code
	UnknownExternalKind(u8),
	/// Unknown internal kind code
	UnknownInternalKind(u8),
	/// Unknown opcode encountered
	UnknownOpcode(u8),
	/// Invalid VarUint1 value
	InvalidVarUint1(u8),
	/// Invalid VarInt32 value
	InvalidVarInt32,
	/// Invalid VarInt64 value
	InvalidVarInt64,
	/// Invalid VarUint32 value
	InvalidVarUint32,
	/// Invalid VarUint64 value
	InvalidVarUint64,
	/// Inconsistent metadata
	InconsistentMetadata,
	/// Invalid section id
	InvalidSectionId(u8),
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			Error::UnexpectedEof => write!(f, "Unexpected end of input"),
			Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
			Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
			Error::InconsistentLength { expected, actual } => {
				write!(f, "Expected length {}, found {}", expected, actual)
			}
			Error::Other(msg) => write!(f, "{}", msg),
			Error::HeapOther(ref msg) => write!(f, "{}", msg),
			Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
			Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
			Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
			Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
			Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
			Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
			Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
			Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
			Error::InvalidVarUint32 => write!(f, "Not an unsigned 32-bit integer"),
			Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
			Error::InvalidVarUint64 => write!(f, "Not an unsigned 64-bit integer"),
			Error::InconsistentMetadata =>  write!(f, "Inconsistent metadata"),
			Error::InvalidSectionId(ref id) =>  write!(f, "Invalid section id: {}", id),
		}
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			Error::UnexpectedEof => "Unexpected end of input",
			Error::InvalidMagic => "Invalid magic number at start of file",
			Error::UnsupportedVersion(_) => "Unsupported wasm version",
			Error::InconsistentLength { .. } => "Inconsistent length",
			Error::Other(msg) => msg,
			Error::HeapOther(ref msg) => &msg[..],
			Error::UnknownValueType(_) => "Invalid or unknown value type",
			Error::UnknownTableElementType(_) => "Unknown table element type",
			Error::NonUtf8String => "Non-UTF-8 string",
			Error::UnknownExternalKind(_) => "Unknown external kind",
			Error::UnknownInternalKind(_) => "Unknown internal kind",
			Error::UnknownOpcode(_) => "Unknown opcode",
			Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
			Error::InvalidVarInt32 => "Not a signed 32-bit integer",
			Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
			Error::InvalidVarInt64 => "Not a signed 64-bit integer",
			Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
			Error::InconsistentMetadata => "Inconsistent metadata",
			Error::InvalidSectionId(_) =>  "Invalid section id",
		}
	}
}

impl From<io::Error> for Error {
	fn from(err: io::Error) -> Self {
		Error::HeapOther(format!("I/O Error: {}", err))
	}
}

/// Unparsed part of the module/section
pub struct Unparsed(pub Vec<u8>);

impl Deserialize for Unparsed {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let len = VarUint32::deserialize(reader)?.into();
		let mut vec = vec![0u8; len];
		reader.read_exact(&mut vec[..])?;
		Ok(Unparsed(vec))
	}
}

impl From<Unparsed> for Vec<u8> {
	fn from(u: Unparsed) -> Vec<u8> {
		u.0
	}
}

/// Deserialize module from file.
pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
	use std::io::Read;

	let mut contents = Vec::new();
	::std::fs::File::open(p)?.read_to_end(&mut contents)?;

	deserialize_buffer(&contents)
}

/// Deserialize deserializable type from buffer.
pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
	let mut reader = io::Cursor::new(contents);
	let result = T::deserialize(&mut reader)?;
	println!("position: {}, content.len: {}", reader.position(), contents.len());
	if reader.position() != contents.len() as u64 {
		return Err(io::Error::from(io::ErrorKind::InvalidData).into())
	}
	Ok(result)
}

/// Create buffer with serialized value.
pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
	let mut buf = Vec::new();
	val.serialize(&mut buf)?;
	Ok(buf)
}

/// Serialize module to the file
pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error>
{
	let mut io = ::std::fs::File::create(p)?;
	module.serialize(&mut io)
}
<commit_msg>remove stray println<commit_after>//! Elements of the WebAssembly binary format.

use std::error;
use std::fmt;
use std::io;

macro_rules! buffered_read {
	($buffer_size: expr, $length: expr, $reader: expr) => {
		{
			let mut vec_buf = Vec::new();
			let mut total_read = 0;
			let mut buf = [0u8; $buffer_size];
			while total_read < $length {
				let next_to_read = if $length - total_read > $buffer_size { $buffer_size } else { $length - total_read };
				$reader.read_exact(&mut buf[0..next_to_read])?;
				vec_buf.extend_from_slice(&buf[0..next_to_read]);
				total_read += next_to_read;
			}
			vec_buf
		}
	}
}

mod primitives;
mod module;
mod section;
mod types;
mod import_entry;
mod export_entry;
mod global_entry;
mod ops;
mod func;
mod segment;
mod index_map;
mod name_section;

pub use self::module::{Module, peek_size, ImportCountType};
pub use self::section::{
	Section, FunctionSection, CodeSection, MemorySection, DataSection,
	ImportSection, ExportSection, GlobalSection, TypeSection, ElementSection,
	TableSection, CustomSection,
};
pub use self::import_entry::{ImportEntry, ResizableLimits, MemoryType, TableType, GlobalType, External};
pub use self::export_entry::{ExportEntry, Internal};
pub use self::global_entry::GlobalEntry;
pub use self::primitives::{
	VarUint32, VarUint7, Uint8, VarUint1, VarInt7, Uint32, VarInt32, VarInt64,
	Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
};
pub use self::types::{Type, ValueType, BlockType, FunctionType, TableElementType};
pub use self::ops::{Opcode, Opcodes, InitExpr};
pub use self::func::{Func, FuncBody, Local};
pub use self::segment::{ElementSegment, DataSegment};
pub use self::index_map::IndexMap;
pub use self::name_section::{
	NameMap, NameSection, ModuleNameSection, FunctionNameSection,
	LocalNameSection,
};

/// Deserialization from serial i/o
pub trait Deserialize : Sized {
	/// Serialization error produced by deserialization routine.
	type Error: From<io::Error>;
	/// Deserialize type from serial i/o
	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
}

/// Serialization to serial i/o
pub trait Serialize {
	/// Serialization error produced by serialization routine.
	type Error: From<io::Error>;
	/// Serialize type to serial i/o
	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
}

/// Deserialization/serialization error
#[derive(Debug, Clone)]
pub enum Error {
	/// Unexpected end of input
	UnexpectedEof,
	/// Invalid magic
	InvalidMagic,
	/// Unsupported version
	UnsupportedVersion(u32),
	/// Inconsistence between declared and actual length
	InconsistentLength {
		/// Expected length of the definition
		expected: usize,
		/// Actual length of the definition
		actual: usize
	},
	/// Other static error
	Other(&'static str),
	/// Other allocated error
	HeapOther(String),
	/// Invalid/unknown value type declaration
	UnknownValueType(i8),
	/// Invalid/unknown table element type declaration
	UnknownTableElementType(i8),
	/// Non-utf8 string
	NonUtf8String,
	/// Unknown external kind code
	UnknownExternalKind(u8),
	/// Unknown internal kind code
	UnknownInternalKind(u8),
	/// Unknown opcode encountered
	UnknownOpcode(u8),
	/// Invalid VarUint1 value
	InvalidVarUint1(u8),
	/// Invalid VarInt32 value
	InvalidVarInt32,
	/// Invalid VarInt64 value
	InvalidVarInt64,
	/// Invalid VarUint32 value
	InvalidVarUint32,
	/// Invalid VarUint64 value
	InvalidVarUint64,
	/// Inconsistent metadata
	InconsistentMetadata,
	/// Invalid section id
	InvalidSectionId(u8),
}

impl fmt::Display for Error {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			Error::UnexpectedEof => write!(f, "Unexpected end of input"),
			Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
			Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
			Error::InconsistentLength { expected, actual } => {
				write!(f, "Expected length {}, found {}", expected, actual)
			}
			Error::Other(msg) => write!(f, "{}", msg),
			Error::HeapOther(ref msg) => write!(f, "{}", msg),
			Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
			Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
			Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
			Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
			Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
			Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
			Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
			Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
			Error::InvalidVarUint32 => write!(f, "Not an unsigned 32-bit integer"),
			Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
			Error::InvalidVarUint64 => write!(f, "Not an unsigned 64-bit integer"),
			Error::InconsistentMetadata =>  write!(f, "Inconsistent metadata"),
			Error::InvalidSectionId(ref id) =>  write!(f, "Invalid section id: {}", id),
		}
	}
}

impl error::Error for Error {
	fn description(&self) -> &str {
		match *self {
			Error::UnexpectedEof => "Unexpected end of input",
			Error::InvalidMagic => "Invalid magic number at start of file",
			Error::UnsupportedVersion(_) => "Unsupported wasm version",
			Error::InconsistentLength { .. } => "Inconsistent length",
			Error::Other(msg) => msg,
			Error::HeapOther(ref msg) => &msg[..],
			Error::UnknownValueType(_) => "Invalid or unknown value type",
			Error::UnknownTableElementType(_) => "Unknown table element type",
			Error::NonUtf8String => "Non-UTF-8 string",
			Error::UnknownExternalKind(_) => "Unknown external kind",
			Error::UnknownInternalKind(_) => "Unknown internal kind",
			Error::UnknownOpcode(_) => "Unknown opcode",
			Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
			Error::InvalidVarInt32 => "Not a signed 32-bit integer",
			Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
			Error::InvalidVarInt64 => "Not a signed 64-bit integer",
			Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
			Error::InconsistentMetadata => "Inconsistent metadata",
			Error::InvalidSectionId(_) =>  "Invalid section id",
		}
	}
}

impl From<io::Error> for Error {
	fn from(err: io::Error) -> Self {
		Error::HeapOther(format!("I/O Error: {}", err))
	}
}

/// Unparsed part of the module/section
pub struct Unparsed(pub Vec<u8>);

impl Deserialize for Unparsed {
	type Error = Error;

	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
		let len = VarUint32::deserialize(reader)?.into();
		let mut vec = vec![0u8; len];
		reader.read_exact(&mut vec[..])?;
		Ok(Unparsed(vec))
	}
}

impl From<Unparsed> for Vec<u8> {
	fn from(u: Unparsed) -> Vec<u8> {
		u.0
	}
}

/// Deserialize module from file.
pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
	use std::io::Read;

	let mut contents = Vec::new();
	::std::fs::File::open(p)?.read_to_end(&mut contents)?;

	deserialize_buffer(&contents)
}

/// Deserialize deserializable type from buffer.
pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
	let mut reader = io::Cursor::new(contents);
	let result = T::deserialize(&mut reader)?;
	if reader.position() != contents.len() as u64 {
		return Err(io::Error::from(io::ErrorKind::InvalidData).into())
	}
	Ok(result)
}

/// Create buffer with serialized value.
pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
	let mut buf = Vec::new();
	val.serialize(&mut buf)?;
	Ok(buf)
}

/// Serialize module to the file
pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error>
{
	let mut io = ::std::fs::File::create(p)?;
	module.serialize(&mut io)
}
<|endoftext|>