<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Cerberus manifest manipulation.
//!
//! Cerberus uses a number of signed "manifests" to describe both the physical
//! configuration of a system it protects, and to describe policies on what
//! firmware can run on those systems.

use core::fmt;

use crate::crypto::rsa;
use crate::io;
use crate::io::Read;
use crate::protocol::WireEnum;

pub mod fpm;
pub use fpm::Fpm;

wire_enum! {
    /// A Cerberus [`Manifest`] type.
    ///
    /// This enum represents the "magic number" `u16` value in a maniest header.
    ///
    /// [`Manifest`]: struct.Manifest.html
    pub enum ManifestType: u16 {
        /// A ["Firmware Policy Manifest"], a `manticore`-specific variant of the
        /// PFM.
        ///
        /// ["Firmware Policy Manifest"]: fpm/index.html
        Fpm = 0xda0e,
    }
}

/// A parsed, verified Cerberus manifest.
///
/// This type represents a generic, authenticated manifest. A value of this
/// type is a witness that authentication via signature was successful; it is
/// not possible to parse a `Manifest` without also verifying it.
///
///
/// On the wire, a `Manifest` looks like the following:
/// ```text
/// struct Manifest {
///     /// Total length, including the header.
///     len: u16,
///     /// The "magic number", which determines the manifest type.
///     magic: u16,
///     /// The monotonic id.
///     id: u32,
///     /// The length of the signature.
///     sig_len: u16,
///     /// Alignment padding.
///     _: u16,
///     /// The manifest-specific body.
///     body: [u8; self.len - HEADER_LEN - self.sig_len],
///     /// The cryptographic signature, an RSA signature in PKCS 1.5
///     /// format.
///     signature: [u8; self.sig_len],
/// }
/// ```
///
/// This manifest format is intended to be fully wire-compatible with Cerberus,
/// although the magic number and the manifest body may contain payloads that
/// are `manticore`-specific.
pub struct Manifest<'m> {
    /// The type of this `Manifest`.
    manifest_type: ManifestType,
    /// A monotonically-increasing ID for a `Manifest`.
    ///
    /// When a `Manifest` is updated, the incoming, updated `Manifest` is
    /// required to have a higher ID. This ensures that older manifests cannot
    /// be used in a replay attack.
    id: u32,
    /// The body of the `Manifest`. The structure of this buffer is
    /// specific to each `ManifestType`.
    ///
    /// [`ManifestType`]: enum.ManifestType.html
    body: &'m [u8],
}

/// An error returned by a [`Manifest`] parsing operation.
///
/// [`Manifest`]: struct.Manifest.html
#[derive(Clone, Copy, Debug)]
pub enum ParseError {
    /// Indicates an error in a low-level [`io`] type.
    ///
    /// [`io`]: ../io/index.html
    Io(io::Error),
    /// Indicates that a parsed value was out of its expected range, like a
    /// magic number.
    OutOfRange,
    /// Indicates that some assumption about a manifest's alignment (internal
    /// or overall) was violated.
    Unaligned,
}

impl From<io::Error> for ParseError {
    fn from(e: io::Error) -> Self {
        Self::Io(e)
    }
}

/// An error returned by a manifest parsing and verification operation.
///
/// This error is separate from `ParseError`, since most manifest parsing does
/// not need to perform cryptographic operations, making the `Rsa` parameter
/// unecessary.
#[derive(Clone, Copy)]
pub enum ParseOrVerifyError<Rsa: rsa::Engine> {
    /// Indicates an error in an [`rsa::Engine`].
    ///
    /// This encompases, among other errors, signature verification errors.
    ///
    /// [`rsa::Engine`]: ../crypto/rsa/trait.Engine.html
    Crypto(Rsa::Error),
    /// Indicates a non-cryptographic error.
    Parse(ParseError),
}

impl<Rsa: rsa::Engine> From<io::Error> for ParseOrVerifyError<Rsa> {
    fn from(e: io::Error) -> Self {
        Self::Parse(ParseError::Io(e))
    }
}

impl<Rsa: rsa::Engine> From<ParseError> for ParseOrVerifyError<Rsa> {
    fn from(e: ParseError) -> Self {
        Self::Parse(e)
    }
}

// Note: this can't be derived, because of the non-trivial bound
// `Rsa::Error: fmt::Debug`.
impl<Rsa: rsa::Engine> fmt::Debug for ParseOrVerifyError<Rsa>
where
    Rsa::Error: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Self::Crypto(e) => f.debug_tuple("Crypto").field(e).finish(),
            Self::Parse(e) => f.debug_tuple("Parse").field(e).finish(),
        }
    }
}

impl<'m> Manifest<'m> {
    /// Parses and verifies a `Manifest` using the provided [`rsa::Engine`].
    ///
    /// This function first parses the `Manifest`'s header, which it uses for
    /// finding the signature at the end of the buffer.
    ///
    /// `buf` must be aligned to a four-byte boundary.
    ///
    /// [`rsa::Engine`]: ../crypto/rsa/trait.Engine.html
    pub fn parse_and_verify<Rsa: rsa::Engine>(
        buf: &'m [u8],
        rsa: &mut Rsa,
    ) -> Result<Self, ParseOrVerifyError<Rsa>> {
        if buf.as_ptr().align_offset(4) != 0 {
            return Err(ParseError::Unaligned.into());
        }

        let mut r = buf;
        let buf_len = r.remaining_data();
        let len = r.read_le::<u16>()? as usize;
        let magic = r.read_le::<u16>()?;
        let id = r.read_le::<u32>()?;
        let sig_len = r.read_le::<u16>()? as usize;
        let _ = r.read_le::<u16>()?;
        let header_len = buf_len - r.remaining_data();

        let rest = r.read_bytes(len - header_len)?;
        let sig_offset = len - sig_len;
        let (body, signature) = rest.split_at(sig_offset - header_len);

        // We need to include the header in the "signed portion". This code
        // cannot panic, because we have already completely consumed the buffer
        // up until to `sig_offset`.
        let signed_portion = &buf[..sig_offset];
        rsa.verify_signature(signature, signed_portion)
            .map_err(ParseOrVerifyError::Crypto)?;

        Ok(Manifest {
            manifest_type: ManifestType::from_wire(magic)
                .ok_or(ParseError::OutOfRange)?,
            id,
            body,
        })
    }

    /// Returns the [`ManifestType`] for this `Manifest`.
    ///
    /// [`ManifestType`]: enum.ManifestType.html
    pub fn manifest_type(&self) -> ManifestType {
        self.manifest_type
    }

    /// Checks whether this `Manifest` can replace `other`.
    ///
    /// In other words, `self` must:
    /// - Be of the same type as `other`.
    /// - Have a greater or equal `id` number than `other`.
    pub fn can_replace(&self, other: &Self) -> bool {
        self.manifest_type == other.manifest_type && self.id >= other.id
    }

    /// Returns the authenticated body of the `Manifest`.
    pub fn body(&self) -> &'m [u8] {
        self.body
    }
}

/// Reads exactly `n * size_of::<T>` bytes from `r`, and converts them
/// into a slice of `T`s.
///
/// Moreover, this function requires that the next pointer that would be
/// returned by `read_bytes()` is well-aligned for `T`; otherwise,
/// `ParseError::Unaligned` is returned.
fn read_zerocopy<'m, T: zerocopy::FromBytes>(
    r: &mut &'m [u8],
    count: usize,
) -> Result<&'m [T], ParseError> {
    let expected_len = core::mem::size_of::<T>()
        .checked_mul(count)
        .ok_or(io::Error::BufferExhausted)?;
    let bytes = r.read_bytes(expected_len)?;
    let layout = zerocopy::LayoutVerified::new_slice(bytes)
        .ok_or(ParseError::Unaligned)?;
    Ok(layout.into_slice())
}

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

    use crate::crypto::ring;
    use crate::crypto::rsa::Builder as _;
    use crate::crypto::testdata;

    const MANIFEST_HEADER: &[u8] = &[
        0x1e, 0x01, // Total length. This is the header length (12) +
        //          // body length (18) + signature length (256).
        0x0e, 0xda, // FPM magic.
        0xaa, 0x55, 0x01, 0x00, // Manifest id (0x55aa).
        0x00, 0x01, // Signature length (0x800 = 256).
        0xff, 0xff, // Padding to 4 bytes.
    ];

    const MANIFEST_CONTENTS: &[u8] = b"Manifest contents!";

    #[test]
    fn parse_manifest() {
        let mut manifest = MANIFEST_HEADER.to_vec();
        manifest.extend_from_slice(MANIFEST_CONTENTS);
        let sig = ring::Rsa::sign_with_pkcs8(
            testdata::RSA_2048_PRIV_PKCS8,
            &manifest,
        );
        manifest.extend_from_slice(&sig);
        assert_eq!(manifest.len(), 0x11e);

        let pub_key =
            ring::RsaPubKey::from_pkcs8(testdata::RSA_2048_PRIV_PKCS8);
        let mut rsa = ring::Rsa.new_engine(pub_key).unwrap();

        let manifest = Manifest::parse_and_verify(&manifest, &mut rsa).unwrap();
        assert_eq!(manifest.manifest_type(), ManifestType::Fpm);
        assert_eq!(manifest.body(), MANIFEST_CONTENTS);
    }

    #[test]
    fn parse_manifest_too_short() {
        let mut manifest = MANIFEST_HEADER.to_vec();
        manifest.extend_from_slice(&MANIFEST_CONTENTS[1..]);
        let sig = ring::Rsa::sign_with_pkcs8(
            testdata::RSA_2048_PRIV_PKCS8,
            &manifest,
        );
        manifest.extend_from_slice(&sig);
        assert_eq!(manifest.len(), 0x11d);

        let pub_key =
            ring::RsaPubKey::from_pkcs8(testdata::RSA_2048_PRIV_PKCS8);
        let mut rsa = ring::Rsa.new_engine(pub_key).unwrap();

        assert!(Manifest::parse_and_verify(&manifest, &mut rsa).is_err());
    }

    #[test]
    fn parse_manifest_bad_sig() {
        let mut manifest = MANIFEST_HEADER.to_vec();
        manifest.extend_from_slice(MANIFEST_CONTENTS);
        let mut sig = ring::Rsa::sign_with_pkcs8(
            testdata::RSA_2048_PRIV_PKCS8,
            &manifest,
        );

        // Flip a byte in the signature.
        sig[0] = !sig[0];
        manifest.extend_from_slice(&sig);
        assert_eq!(manifest.len(), 0x11e);

        let pub_key =
            ring::RsaPubKey::from_pkcs8(testdata::RSA_2048_PRIV_PKCS8);
        let mut rsa = ring::Rsa.new_engine(pub_key).unwrap();

        assert!(matches!(
            Manifest::parse_and_verify(&manifest, &mut rsa),
            Err(ParseOrVerifyError::Crypto(..))
        ));
    }
}
<commit_msg>[manifest] Fix crash bug in Manifest::parse_and_verify<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! Cerberus manifest manipulation.
//!
//! Cerberus uses a number of signed "manifests" to describe both the physical
//! configuration of a system it protects, and to describe policies on what
//! firmware can run on those systems.

use core::fmt;

use crate::crypto::rsa;
use crate::io;
use crate::io::Read;
use crate::protocol::WireEnum;

pub mod fpm;
pub use fpm::Fpm;

wire_enum! {
    /// A Cerberus [`Manifest`] type.
    ///
    /// This enum represents the "magic number" `u16` value in a maniest header.
    ///
    /// [`Manifest`]: struct.Manifest.html
    pub enum ManifestType: u16 {
        /// A ["Firmware Policy Manifest"], a `manticore`-specific variant of the
        /// PFM.
        ///
        /// ["Firmware Policy Manifest"]: fpm/index.html
        Fpm = 0xda0e,
    }
}

/// A parsed, verified Cerberus manifest.
///
/// This type represents a generic, authenticated manifest. A value of this
/// type is a witness that authentication via signature was successful; it is
/// not possible to parse a `Manifest` without also verifying it.
///
///
/// On the wire, a `Manifest` looks like the following:
/// ```text
/// struct Manifest {
///     /// Total length, including the header.
///     len: u16,
///     /// The "magic number", which determines the manifest type.
///     magic: u16,
///     /// The monotonic id.
///     id: u32,
///     /// The length of the signature.
///     sig_len: u16,
///     /// Alignment padding.
///     _: u16,
///     /// The manifest-specific body.
///     body: [u8; self.len - HEADER_LEN - self.sig_len],
///     /// The cryptographic signature, an RSA signature in PKCS 1.5
///     /// format.
///     signature: [u8; self.sig_len],
/// }
/// ```
///
/// This manifest format is intended to be fully wire-compatible with Cerberus,
/// although the magic number and the manifest body may contain payloads that
/// are `manticore`-specific.
pub struct Manifest<'m> {
    /// The type of this `Manifest`.
    manifest_type: ManifestType,
    /// A monotonically-increasing ID for a `Manifest`.
    ///
    /// When a `Manifest` is updated, the incoming, updated `Manifest` is
    /// required to have a higher ID. This ensures that older manifests cannot
    /// be used in a replay attack.
    id: u32,
    /// The body of the `Manifest`. The structure of this buffer is
    /// specific to each `ManifestType`.
    ///
    /// [`ManifestType`]: enum.ManifestType.html
    body: &'m [u8],
}

/// An error returned by a [`Manifest`] parsing operation.
///
/// [`Manifest`]: struct.Manifest.html
#[derive(Clone, Copy, Debug)]
pub enum ParseError {
    /// Indicates an error in a low-level [`io`] type.
    ///
    /// [`io`]: ../io/index.html
    Io(io::Error),
    /// Indicates that a parsed value was out of its expected range, like a
    /// magic number.
    OutOfRange,
    /// Indicates that some assumption about a manifest's alignment (internal
    /// or overall) was violated.
    Unaligned,
}

impl From<io::Error> for ParseError {
    fn from(e: io::Error) -> Self {
        Self::Io(e)
    }
}

/// An error returned by a manifest parsing and verification operation.
///
/// This error is separate from `ParseError`, since most manifest parsing does
/// not need to perform cryptographic operations, making the `Rsa` parameter
/// unecessary.
#[derive(Clone, Copy)]
pub enum ParseOrVerifyError<Rsa: rsa::Engine> {
    /// Indicates an error in an [`rsa::Engine`].
    ///
    /// This encompases, among other errors, signature verification errors.
    ///
    /// [`rsa::Engine`]: ../crypto/rsa/trait.Engine.html
    Crypto(Rsa::Error),
    /// Indicates a non-cryptographic error.
    Parse(ParseError),
}

impl<Rsa: rsa::Engine> From<io::Error> for ParseOrVerifyError<Rsa> {
    fn from(e: io::Error) -> Self {
        Self::Parse(ParseError::Io(e))
    }
}

impl<Rsa: rsa::Engine> From<ParseError> for ParseOrVerifyError<Rsa> {
    fn from(e: ParseError) -> Self {
        Self::Parse(e)
    }
}

// Note: this can't be derived, because of the non-trivial bound
// `Rsa::Error: fmt::Debug`.
impl<Rsa: rsa::Engine> fmt::Debug for ParseOrVerifyError<Rsa>
where
    Rsa::Error: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Self::Crypto(e) => f.debug_tuple("Crypto").field(e).finish(),
            Self::Parse(e) => f.debug_tuple("Parse").field(e).finish(),
        }
    }
}

impl<'m> Manifest<'m> {
    /// Parses and verifies a `Manifest` using the provided [`rsa::Engine`].
    ///
    /// This function first parses the `Manifest`'s header, which it uses for
    /// finding the signature at the end of the buffer.
    ///
    /// `buf` must be aligned to a four-byte boundary.
    ///
    /// [`rsa::Engine`]: ../crypto/rsa/trait.Engine.html
    pub fn parse_and_verify<Rsa: rsa::Engine>(
        buf: &'m [u8],
        rsa: &mut Rsa,
    ) -> Result<Self, ParseOrVerifyError<Rsa>> {
        if buf.as_ptr().align_offset(4) != 0 {
            return Err(ParseError::Unaligned.into());
        }

        let mut r = buf;
        let buf_len = r.remaining_data();
        let len = r.read_le::<u16>()? as usize;
        let magic = r.read_le::<u16>()?;
        let id = r.read_le::<u32>()?;
        let sig_len = r.read_le::<u16>()? as usize;
        let _ = r.read_le::<u16>()?;
        let header_len = buf_len - r.remaining_data();

        let rest_len =
            len.checked_sub(header_len).ok_or(ParseError::OutOfRange)?;
        let rest = r.read_bytes(rest_len)?;
        let sig_offset =
            len.checked_sub(sig_len).ok_or(ParseError::OutOfRange)?;
        let sig_offset_past_header = sig_offset
            .checked_sub(header_len)
            .ok_or(ParseError::OutOfRange)?;
        let (body, signature) = rest.split_at(sig_offset_past_header);

        // We need to include the header in the "signed portion". This code
        // cannot panic, because we have already completely consumed the buffer
        // up until to `sig_offset`.
        let signed_portion = &buf[..sig_offset];
        rsa.verify_signature(signature, signed_portion)
            .map_err(ParseOrVerifyError::Crypto)?;

        Ok(Manifest {
            manifest_type: ManifestType::from_wire(magic)
                .ok_or(ParseError::OutOfRange)?,
            id,
            body,
        })
    }

    /// Returns the [`ManifestType`] for this `Manifest`.
    ///
    /// [`ManifestType`]: enum.ManifestType.html
    pub fn manifest_type(&self) -> ManifestType {
        self.manifest_type
    }

    /// Checks whether this `Manifest` can replace `other`.
    ///
    /// In other words, `self` must:
    /// - Be of the same type as `other`.
    /// - Have a greater or equal `id` number than `other`.
    pub fn can_replace(&self, other: &Self) -> bool {
        self.manifest_type == other.manifest_type && self.id >= other.id
    }

    /// Returns the authenticated body of the `Manifest`.
    pub fn body(&self) -> &'m [u8] {
        self.body
    }
}

/// Reads exactly `n * size_of::<T>` bytes from `r`, and converts them
/// into a slice of `T`s.
///
/// Moreover, this function requires that the next pointer that would be
/// returned by `read_bytes()` is well-aligned for `T`; otherwise,
/// `ParseError::Unaligned` is returned.
fn read_zerocopy<'m, T: zerocopy::FromBytes>(
    r: &mut &'m [u8],
    count: usize,
) -> Result<&'m [T], ParseError> {
    let expected_len = core::mem::size_of::<T>()
        .checked_mul(count)
        .ok_or(io::Error::BufferExhausted)?;
    let bytes = r.read_bytes(expected_len)?;
    let layout = zerocopy::LayoutVerified::new_slice(bytes)
        .ok_or(ParseError::Unaligned)?;
    Ok(layout.into_slice())
}

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

    use crate::crypto::ring;
    use crate::crypto::rsa::Builder as _;
    use crate::crypto::testdata;

    const MANIFEST_HEADER: &[u8] = &[
        0x1e, 0x01, // Total length. This is the header length (12) +
        //          // body length (18) + signature length (256).
        0x0e, 0xda, // FPM magic.
        0xaa, 0x55, 0x01, 0x00, // Manifest id (0x55aa).
        0x00, 0x01, // Signature length (0x800 = 256).
        0xff, 0xff, // Padding to 4 bytes.
    ];

    const MANIFEST_CONTENTS: &[u8] = b"Manifest contents!";

    #[test]
    fn parse_manifest() {
        let mut manifest = MANIFEST_HEADER.to_vec();
        manifest.extend_from_slice(MANIFEST_CONTENTS);
        let sig = ring::Rsa::sign_with_pkcs8(
            testdata::RSA_2048_PRIV_PKCS8,
            &manifest,
        );
        manifest.extend_from_slice(&sig);
        assert_eq!(manifest.len(), 0x11e);

        let pub_key =
            ring::RsaPubKey::from_pkcs8(testdata::RSA_2048_PRIV_PKCS8);
        let mut rsa = ring::Rsa.new_engine(pub_key).unwrap();

        let manifest = Manifest::parse_and_verify(&manifest, &mut rsa).unwrap();
        assert_eq!(manifest.manifest_type(), ManifestType::Fpm);
        assert_eq!(manifest.body(), MANIFEST_CONTENTS);
    }

    #[test]
    fn parse_manifest_too_short() {
        let mut manifest = MANIFEST_HEADER.to_vec();
        manifest.extend_from_slice(&MANIFEST_CONTENTS[1..]);
        let sig = ring::Rsa::sign_with_pkcs8(
            testdata::RSA_2048_PRIV_PKCS8,
            &manifest,
        );
        manifest.extend_from_slice(&sig);
        assert_eq!(manifest.len(), 0x11d);

        let pub_key =
            ring::RsaPubKey::from_pkcs8(testdata::RSA_2048_PRIV_PKCS8);
        let mut rsa = ring::Rsa.new_engine(pub_key).unwrap();

        assert!(Manifest::parse_and_verify(&manifest, &mut rsa).is_err());
    }

    #[test]
    fn parse_manifest_bad_sig() {
        let mut manifest = MANIFEST_HEADER.to_vec();
        manifest.extend_from_slice(MANIFEST_CONTENTS);
        let mut sig = ring::Rsa::sign_with_pkcs8(
            testdata::RSA_2048_PRIV_PKCS8,
            &manifest,
        );

        // Flip a byte in the signature.
        sig[0] = !sig[0];
        manifest.extend_from_slice(&sig);
        assert_eq!(manifest.len(), 0x11e);

        let pub_key =
            ring::RsaPubKey::from_pkcs8(testdata::RSA_2048_PRIV_PKCS8);
        let mut rsa = ring::Rsa.new_engine(pub_key).unwrap();

        assert!(matches!(
            Manifest::parse_and_verify(&manifest, &mut rsa),
            Err(ParseOrVerifyError::Crypto(..))
        ));
    }
}
<|endoftext|>


<commit_before>//use std::collections::HashMap;
use std::ffi::{CString};
use libc::{c_int};

use super::ffi;

use {SqliteResult, SqliteError, SqliteConnection, SqliteStatement, SqliteRows, SqliteRow};
use types::{ToSql};

impl SqliteConnection {
    /// Convenience method to prepare and execute a single SQL statement with named parameter(s).
    pub fn execute_named(&self, sql: &str, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> {
        self.prepare(sql).and_then(|mut stmt| stmt.execute_named(params))
    }

    /// Convenience method to execute a query with named parameter(s) that is expected to return a single row.
    ///
    /// If the query returns more than one row, all rows except the first are ignored.
    pub fn query_named_row<T, F>(&self, sql: &str, params: &[(&str, &ToSql)], f: F) -> SqliteResult<T>
                           where F: FnOnce(SqliteRow) -> T {
        let mut stmt = try!(self.prepare(sql));
        let mut rows = try!(stmt.query_named(params));

        match rows.next() {
            Some(row) => row.map(f),
            None      => Err(SqliteError{
                code: ffi::SQLITE_NOTICE,
                message: "Query did not return a row".to_string(),
            })
        }
    }
}

impl<'conn> SqliteStatement<'conn> {
    /*pub fn parameter_names(&self) -> HashMap<String, i32> {
        let n = unsafe { ffi::sqlite3_bind_parameter_count(self.stmt) };
        let mut index_by_name = HashMap::with_capacity(n as usize);
        for i in 1..n+1 {
            let c_name = unsafe { ffi::sqlite3_bind_parameter_name(self.stmt, i) };
            if !c_name.is_null() {
                let c_slice = unsafe { CStr::from_ptr(c_name).to_bytes() };
                index_by_name.insert(str::from_utf8(c_slice).unwrap().to_string(), n);
            }
        }
        index_by_name
    }*/

    /// Return the index of an SQL parameter given its name.
    ///
    /// ## Failures
    /// Return None if `name` is invalid (NulError) or if no matching parameter is found.
    pub fn parameter_index(&self, name: &str) -> Option<i32> {
        unsafe {
            CString::new(name).ok().and_then(|c_name|
                match ffi::sqlite3_bind_parameter_index(self.stmt, c_name.as_ptr()) {
                    0 => None, // A zero is returned if no matching parameter is found.
                    n => Some(n)
                }
            )

        }
    }

    /// Execute the prepared statement with named parameter(s).
    ///
    /// On success, returns the number of rows that were changed or inserted or deleted (via
    /// `sqlite3_changes`).
    pub fn execute_named(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> {
        unsafe {
            try!(self.bind_named_parameters(params));
            self.execute_()
        }
    }

    /// Execute the prepared statement with named parameter(s), returning an iterator over the resulting rows.
    pub fn query_named<'a>(&'a mut self, params: &[(&str, &ToSql)]) -> SqliteResult<SqliteRows<'a>> {
        self.reset_if_needed();

        unsafe {
            try!(self.bind_named_parameters(params));
        }

        self.needs_reset = true;
        Ok(SqliteRows::new(self))
    }

    unsafe fn bind_named_parameters(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<()> {
        for &(name, value) in params {
            let i = try!(self.parameter_index(name).ok_or(SqliteError{
                code: ffi::SQLITE_MISUSE,
                message: format!("Invalid parameter name: {}", name)
            }));
            try!(self.conn.decode_result(value.bind_parameter(self.stmt, i)));
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;

    #[test]
    fn test_execute_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();

        assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)]).unwrap(), 1);
        assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)]).unwrap(), 1);

        assert_eq!(3i32, db.query_named_row("SELECT SUM(x) FROM foo WHERE x > :x", &[(":x", &0i32)], |r| r.get(0)).unwrap());
    }

   #[test]
    fn test_stmt_execute_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER)";
        db.execute_batch(sql).unwrap();

        let mut stmt = db.prepare("INSERT INTO test (id, name, flag) VALUES (:id, :name, :flag)").unwrap();
        stmt.execute_named(&[(":name", &"one")]).unwrap();
    }

   #[test]
    fn test_query_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER)";
        db.execute_batch(sql).unwrap();

        let mut stmt = db.prepare("SELECT * FROM test where name = :name").unwrap();
        stmt.query_named(&[(":name", &"one")]).unwrap();
    }
}<commit_msg>Cleanup use statements.<commit_after>//use std::collections::HashMap;
use std::ffi::CString;
use libc::c_int;

use super::ffi;

use {SqliteResult, SqliteError, SqliteConnection, SqliteStatement, SqliteRows, SqliteRow};
use types::ToSql;

impl SqliteConnection {
    /// Convenience method to prepare and execute a single SQL statement with named parameter(s).
    pub fn execute_named(&self, sql: &str, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> {
        self.prepare(sql).and_then(|mut stmt| stmt.execute_named(params))
    }

    /// Convenience method to execute a query with named parameter(s) that is expected to return a single row.
    ///
    /// If the query returns more than one row, all rows except the first are ignored.
    pub fn query_named_row<T, F>(&self, sql: &str, params: &[(&str, &ToSql)], f: F) -> SqliteResult<T>
                           where F: FnOnce(SqliteRow) -> T {
        let mut stmt = try!(self.prepare(sql));
        let mut rows = try!(stmt.query_named(params));

        match rows.next() {
            Some(row) => row.map(f),
            None      => Err(SqliteError{
                code: ffi::SQLITE_NOTICE,
                message: "Query did not return a row".to_string(),
            })
        }
    }
}

impl<'conn> SqliteStatement<'conn> {
    /*pub fn parameter_names(&self) -> HashMap<String, i32> {
        let n = unsafe { ffi::sqlite3_bind_parameter_count(self.stmt) };
        let mut index_by_name = HashMap::with_capacity(n as usize);
        for i in 1..n+1 {
            let c_name = unsafe { ffi::sqlite3_bind_parameter_name(self.stmt, i) };
            if !c_name.is_null() {
                let c_slice = unsafe { CStr::from_ptr(c_name).to_bytes() };
                index_by_name.insert(str::from_utf8(c_slice).unwrap().to_string(), n);
            }
        }
        index_by_name
    }*/

    /// Return the index of an SQL parameter given its name.
    ///
    /// ## Failures
    /// Return None if `name` is invalid (NulError) or if no matching parameter is found.
    pub fn parameter_index(&self, name: &str) -> Option<i32> {
        unsafe {
            CString::new(name).ok().and_then(|c_name|
                match ffi::sqlite3_bind_parameter_index(self.stmt, c_name.as_ptr()) {
                    0 => None, // A zero is returned if no matching parameter is found.
                    n => Some(n)
                }
            )

        }
    }

    /// Execute the prepared statement with named parameter(s).
    ///
    /// On success, returns the number of rows that were changed or inserted or deleted (via
    /// `sqlite3_changes`).
    pub fn execute_named(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> {
        unsafe {
            try!(self.bind_named_parameters(params));
            self.execute_()
        }
    }

    /// Execute the prepared statement with named parameter(s), returning an iterator over the resulting rows.
    pub fn query_named<'a>(&'a mut self, params: &[(&str, &ToSql)]) -> SqliteResult<SqliteRows<'a>> {
        self.reset_if_needed();

        unsafe {
            try!(self.bind_named_parameters(params));
        }

        self.needs_reset = true;
        Ok(SqliteRows::new(self))
    }

    unsafe fn bind_named_parameters(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<()> {
        for &(name, value) in params {
            let i = try!(self.parameter_index(name).ok_or(SqliteError{
                code: ffi::SQLITE_MISUSE,
                message: format!("Invalid parameter name: {}", name)
            }));
            try!(self.conn.decode_result(value.bind_parameter(self.stmt, i)));
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;

    #[test]
    fn test_execute_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();

        assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)]).unwrap(), 1);
        assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)]).unwrap(), 1);

        assert_eq!(3i32, db.query_named_row("SELECT SUM(x) FROM foo WHERE x > :x", &[(":x", &0i32)], |r| r.get(0)).unwrap());
    }

   #[test]
    fn test_stmt_execute_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER)";
        db.execute_batch(sql).unwrap();

        let mut stmt = db.prepare("INSERT INTO test (id, name, flag) VALUES (:id, :name, :flag)").unwrap();
        stmt.execute_named(&[(":name", &"one")]).unwrap();
    }

   #[test]
    fn test_query_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER)";
        db.execute_batch(sql).unwrap();

        let mut stmt = db.prepare("SELECT * FROM test where name = :name").unwrap();
        stmt.query_named(&[(":name", &"one")]).unwrap();
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Tyler Neely
//
// 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.

mod util;

use std::{fs, io::Read as _};

use rocksdb::{BlockBasedOptions, DataBlockIndexType, Options, ReadOptions, DB};
use util::DBPath;

#[test]
fn test_set_num_levels() {
    let n = DBPath::new("_rust_rocksdb_test_set_num_levels");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_num_levels(2);
        let _db = DB::open(&opts, &n).unwrap();
    }
}

#[test]
fn test_increase_parallelism() {
    let n = DBPath::new("_rust_rocksdb_test_increase_parallelism");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.increase_parallelism(4);
        let _db = DB::open(&opts, &n).unwrap();
    }
}

#[test]
fn test_set_level_compaction_dynamic_level_bytes() {
    let n = DBPath::new("_rust_rocksdb_test_set_level_compaction_dynamic_level_bytes");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_level_compaction_dynamic_level_bytes(true);
        let _db = DB::open(&opts, &n).unwrap();
    }
}

#[test]
fn test_block_based_options() {
    let path = "_rust_rocksdb_test_block_based_options";
    let n = DBPath::new(path);
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);

        let mut block_opts = BlockBasedOptions::default();
        block_opts.set_cache_index_and_filter_blocks(true);
        block_opts.set_pin_l0_filter_and_index_blocks_in_cache(true);
        block_opts.set_format_version(4);
        block_opts.set_index_block_restart_interval(16);

        opts.set_block_based_table_factory(&block_opts);
        let _db = DB::open(&opts, &n).unwrap();

        // read the setting from the LOG file
        let mut rocksdb_log = fs::File::open(format!("{}/LOG", (&n).as_ref().to_str().unwrap()))
            .expect("rocksdb creates a LOG file");
        let mut settings = String::new();
        rocksdb_log.read_to_string(&mut settings).unwrap();

        // check the settings are set in the LOG file
        assert!(settings.contains("cache_index_and_filter_blocks: 1"));
        assert!(settings.contains("pin_l0_filter_and_index_blocks_in_cache: 1"));
        assert!(settings.contains("format_version: 4"));
        assert!(settings.contains("index_block_restart_interval: 16"));
    }
}

#[test]
fn test_read_options() {
    let mut read_opts = ReadOptions::default();
    read_opts.set_verify_checksums(false);
}

#[test]
fn test_set_data_block_index_type() {
    let path = "_rust_rocksdb_test_set_data_block_index_type";
    let n = DBPath::new(path);

    // Default is `BinarySearch`
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);

        let block_opts = BlockBasedOptions::default();
        opts.set_block_based_table_factory(&block_opts);
        let _db = DB::open(&opts, &n).expect("open a db works");

        let mut rocksdb_log = fs::File::open(format!("{}/LOG", (&n).as_ref().to_str().unwrap()))
            .expect("rocksdb creates a LOG file");
        let mut settings = String::new();
        rocksdb_log
            .read_to_string(&mut settings)
            .expect("can read the LOG file");
        assert!(settings.contains("data_block_index_type: 0"));
        assert!(settings.contains("data_block_hash_table_util_ratio: 0.750000"));
    }

    // Setting the index type and hash table utilization ratio works
    {
        let mut opts = Options::default();
        opts.create_if_missing(false);

        let mut block_opts = BlockBasedOptions::default();
        block_opts.set_data_block_index_type(DataBlockIndexType::BinaryAndHash);
        block_opts.set_data_block_hash_ratio(0.35);
        opts.set_block_based_table_factory(&block_opts);
        let _db = DB::open(&opts, &n).expect("open a db works");

        let mut rocksdb_log = fs::File::open(format!("{}/LOG", (&n).as_ref().to_str().unwrap()))
            .expect("rocksdb creates a LOG file");
        let mut settings = String::new();
        rocksdb_log
            .read_to_string(&mut settings)
            .expect("can read the LOG file");
        assert!(settings.contains("data_block_index_type: 1"));
        assert!(settings.contains("data_block_hash_table_util_ratio: 0.350000"));
    }
}

#[test]
fn set_compression_options_zstd_max_train_bytes() {
    let path = DBPath::new("_rust_set_compression_options_zstd_max_train_bytes");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_zstd_max_train_bytes(100);
        let _db = DB::open(&opts, &path).unwrap();
    }
}
<commit_msg>Fix test (set compression options)<commit_after>// Copyright 2020 Tyler Neely
//
// 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.

mod util;

use std::{fs, io::Read as _};

use rocksdb::{BlockBasedOptions, DataBlockIndexType, Options, ReadOptions, DB};
use util::DBPath;

#[test]
fn test_set_num_levels() {
    let n = DBPath::new("_rust_rocksdb_test_set_num_levels");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_num_levels(2);
        let _db = DB::open(&opts, &n).unwrap();
    }
}

#[test]
fn test_increase_parallelism() {
    let n = DBPath::new("_rust_rocksdb_test_increase_parallelism");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.increase_parallelism(4);
        let _db = DB::open(&opts, &n).unwrap();
    }
}

#[test]
fn test_set_level_compaction_dynamic_level_bytes() {
    let n = DBPath::new("_rust_rocksdb_test_set_level_compaction_dynamic_level_bytes");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_level_compaction_dynamic_level_bytes(true);
        let _db = DB::open(&opts, &n).unwrap();
    }
}

#[test]
fn test_block_based_options() {
    let path = "_rust_rocksdb_test_block_based_options";
    let n = DBPath::new(path);
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);

        let mut block_opts = BlockBasedOptions::default();
        block_opts.set_cache_index_and_filter_blocks(true);
        block_opts.set_pin_l0_filter_and_index_blocks_in_cache(true);
        block_opts.set_format_version(4);
        block_opts.set_index_block_restart_interval(16);

        opts.set_block_based_table_factory(&block_opts);
        let _db = DB::open(&opts, &n).unwrap();

        // read the setting from the LOG file
        let mut rocksdb_log = fs::File::open(format!("{}/LOG", (&n).as_ref().to_str().unwrap()))
            .expect("rocksdb creates a LOG file");
        let mut settings = String::new();
        rocksdb_log.read_to_string(&mut settings).unwrap();

        // check the settings are set in the LOG file
        assert!(settings.contains("cache_index_and_filter_blocks: 1"));
        assert!(settings.contains("pin_l0_filter_and_index_blocks_in_cache: 1"));
        assert!(settings.contains("format_version: 4"));
        assert!(settings.contains("index_block_restart_interval: 16"));
    }
}

#[test]
fn test_read_options() {
    let mut read_opts = ReadOptions::default();
    read_opts.set_verify_checksums(false);
}

#[test]
fn test_set_data_block_index_type() {
    let path = "_rust_rocksdb_test_set_data_block_index_type";
    let n = DBPath::new(path);

    // Default is `BinarySearch`
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);

        let block_opts = BlockBasedOptions::default();
        opts.set_block_based_table_factory(&block_opts);
        let _db = DB::open(&opts, &n).expect("open a db works");

        let mut rocksdb_log = fs::File::open(format!("{}/LOG", (&n).as_ref().to_str().unwrap()))
            .expect("rocksdb creates a LOG file");
        let mut settings = String::new();
        rocksdb_log
            .read_to_string(&mut settings)
            .expect("can read the LOG file");
        assert!(settings.contains("data_block_index_type: 0"));
        assert!(settings.contains("data_block_hash_table_util_ratio: 0.750000"));
    }

    // Setting the index type and hash table utilization ratio works
    {
        let mut opts = Options::default();
        opts.create_if_missing(false);

        let mut block_opts = BlockBasedOptions::default();
        block_opts.set_data_block_index_type(DataBlockIndexType::BinaryAndHash);
        block_opts.set_data_block_hash_ratio(0.35);
        opts.set_block_based_table_factory(&block_opts);
        let _db = DB::open(&opts, &n).expect("open a db works");

        let mut rocksdb_log = fs::File::open(format!("{}/LOG", (&n).as_ref().to_str().unwrap()))
            .expect("rocksdb creates a LOG file");
        let mut settings = String::new();
        rocksdb_log
            .read_to_string(&mut settings)
            .expect("can read the LOG file");
        assert!(settings.contains("data_block_index_type: 1"));
        assert!(settings.contains("data_block_hash_table_util_ratio: 0.350000"));
    }
}

#[test]
fn set_compression_options_zstd_max_train_bytes() {
    let path = DBPath::new("_rust_set_compression_options_zstd_max_train_bytes");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_compression_options(4, 5, 6, 7);
        opts.set_zstd_max_train_bytes(100);
        let _db = DB::open(&opts, &path).unwrap();
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "runtime-rng")]
use crate::convert::Convert;
use crate::{AHasher};
#[cfg(all(not(feature = "runtime-rng"), feature = "compile-time-rng"))]
use const_random::const_random;
use core::fmt;
use core::hash::BuildHasher;
use core::hash::Hasher;
#[cfg(feature = "runtime-rng")]
use lazy_static::*;
use core::sync::atomic::{AtomicUsize, Ordering};

#[cfg(feature = "runtime-rng")]
lazy_static! {
    static ref SEEDS: [[u64; 4]; 2] = {
        let mut result: [u8; 64] = [0; 64];
        getrandom::getrandom(&mut result).expect("getrandom::getrandom() failed.");
        result.convert()
    };
}

static COUNTER: AtomicUsize = AtomicUsize::new(0);

pub(crate) const PI: [u64; 4] = [
    0x243f_6a88_85a3_08d3,
    0x1319_8a2e_0370_7344,
    0xa409_3822_299f_31d0,
    0x082e_fa98_ec4e_6c89,
];

#[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
const PI2: [u64; 4] = [
    0x4528_21e6_38d0_1377,
    0xbe54_66cf_34e9_0c6c,
    0xc0ac_29b7_c97c_50dd,
    0x3f84_d5b5_b547_0917,
];

#[inline]
pub(crate) fn seeds() -> [u64; 4] {
    #[cfg(feature = "runtime-rng")]
    { SEEDS[1] }
    #[cfg(all(not(feature = "runtime-rng"), feature = "compile-time-rng"))]
    { [const_random!(u64), const_random!(u64), const_random!(u64), const_random!(u64)] }
    #[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
    { PI }
}

/// Provides a [Hasher] factory. This is typically used (e.g. by [HashMap]) to create
/// [AHasher]s in order to hash the keys of the map. See `build_hasher` below.
///
/// [build_hasher]: ahash::
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
#[derive(Clone)]
pub struct RandomState {
    pub(crate) k0: u64,
    pub(crate) k1: u64,
    pub(crate) k2: u64,
    pub(crate) k3: u64,
}

impl fmt::Debug for RandomState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("RandomState { .. }")
    }
}

impl RandomState {
    /// Use randomly generated keys
    #[inline]
    pub fn new() -> RandomState {
        #[cfg(feature = "runtime-rng")]
        {
            let seeds = *SEEDS;
            RandomState::from_keys(seeds[0], seeds[1])
        }
        #[cfg(all(not(feature = "runtime-rng"), feature = "compile-time-rng"))]
        {
            RandomState::from_keys(
                [const_random!(u64), const_random!(u64), const_random!(u64), const_random!(u64)],
                [const_random!(u64), const_random!(u64), const_random!(u64), const_random!(u64)],
            )
        }
        #[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
        {
            RandomState::from_keys(PI, PI2)
        }
    }

    /// Allows for supplying seeds, but each time it is called the resulting state will be different.
    /// This is done using a static counter, so it can safely be used with a fixed keys.
    #[inline]
    pub fn generate_with(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState {
        RandomState::from_keys(seeds(), [k0, k1, k2, k3])
    }

    fn from_keys(a: [u64; 4], b: [u64; 4]) -> RandomState {
        let [k0, k1, k2, k3] = a;
        let mut hasher = AHasher::from_random_state(&RandomState { k0, k1, k2, k3 });

        let stack_mem_loc = &hasher as *const _ as usize;
        #[cfg(not(all(target_arch="arm", target_os="none")))]
        {
            hasher.write_usize(COUNTER.fetch_add(stack_mem_loc, Ordering::Relaxed));
        }
        #[cfg(all(target_arch="arm", target_os="none"))]
        {
            let previous = COUNTER.load(Ordering::Relaxed);
            let new = previous.wrapping_add(stack_mem_loc);
            COUNTER.store(new, Ordering::Relaxed);
            hasher.write_usize(new);
        }
        #[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
        hasher.write_usize(&PI as *const _ as usize);
        let mix = |k: u64| {
            let mut h = hasher.clone();
            h.write_u64(k);
            h.finish()
        };

        RandomState { k0: mix(b[0]), k1: mix(b[1]), k2: mix(b[2]), k3: mix(b[3]) }
    }

    /// Internal. Used by Default.
    #[inline]
    pub(crate) fn with_fixed_keys() -> RandomState {
        let [k0, k1, k2, k3] = seeds();
        RandomState { k0, k1, k2, k3 }
    }

    /// Allows for explicitly setting the seeds to used.
    #[inline]
    pub const fn with_seeds(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState {
        RandomState { k0, k1, k2, k3 }
    }
}

impl Default for RandomState {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl BuildHasher for RandomState {
    type Hasher = AHasher;

    /// Constructs a new [AHasher] with keys based on this [RandomState] object.
    /// This means that two different [RandomState]s will will generate
    /// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
    /// will generate the same hashes for the same input data.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::{AHasher, RandomState};
    /// use std::hash::{Hasher, BuildHasher};
    ///
    /// let build_hasher = RandomState::new();
    /// let mut hasher_1 = build_hasher.build_hasher();
    /// let mut hasher_2 = build_hasher.build_hasher();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    ///
    /// let other_build_hasher = RandomState::new();
    /// let mut different_hasher = other_build_hasher.build_hasher();
    /// different_hasher.write_u32(1234);
    /// assert_ne!(different_hasher.finish(), hasher_1.finish());
    /// ```
    /// [Hasher]: std::hash::Hasher
    /// [BuildHasher]: std::hash::BuildHasher
    /// [HashMap]: std::collections::HashMap
    #[inline]
    fn build_hasher(&self) -> AHasher {
        AHasher::from_random_state(self)
    }
}

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

    #[test]
    fn test_unique() {
        let a = RandomState::new();
        let b = RandomState::new();
        assert_ne!(a.build_hasher().finish(), b.build_hasher().finish());
    }

    #[cfg(feature = "runtime-rng")]
    #[test]
    fn test_not_pi() {
        assert_ne!(PI, seeds());
    }

    #[test]
    fn test_with_seeds_const() {
        const _CONST_RANDOM_STATE: RandomState = RandomState::with_seeds(17, 19, 21, 23);
    }
}
<commit_msg>Ensure test coverage for const-random case.<commit_after>#[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
use crate::convert::Convert;
use crate::{AHasher};
#[cfg(all(feature = "compile-time-rng", any(not(feature = "runtime-rng"), test)))]
use const_random::const_random;
use core::fmt;
use core::hash::BuildHasher;
use core::hash::Hasher;
#[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
use lazy_static::*;
use core::sync::atomic::{AtomicUsize, Ordering};

#[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
lazy_static! {
    static ref SEEDS: [[u64; 4]; 2] = {
        let mut result: [u8; 64] = [0; 64];
        getrandom::getrandom(&mut result).expect("getrandom::getrandom() failed.");
        result.convert()
    };
}

static COUNTER: AtomicUsize = AtomicUsize::new(0);

pub(crate) const PI: [u64; 4] = [
    0x243f_6a88_85a3_08d3,
    0x1319_8a2e_0370_7344,
    0xa409_3822_299f_31d0,
    0x082e_fa98_ec4e_6c89,
];

#[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
const PI2: [u64; 4] = [
    0x4528_21e6_38d0_1377,
    0xbe54_66cf_34e9_0c6c,
    0xc0ac_29b7_c97c_50dd,
    0x3f84_d5b5_b547_0917,
];

#[inline]
pub(crate) fn seeds() -> [u64; 4] {
    #[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
    { SEEDS[1] }
    #[cfg(all(feature = "compile-time-rng", any(not(feature = "runtime-rng"), test)))]
    { [const_random!(u64), const_random!(u64), const_random!(u64), const_random!(u64)] }
    #[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
    { PI }
}

/// Provides a [Hasher] factory. This is typically used (e.g. by [HashMap]) to create
/// [AHasher]s in order to hash the keys of the map. See `build_hasher` below.
///
/// [build_hasher]: ahash::
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
#[derive(Clone)]
pub struct RandomState {
    pub(crate) k0: u64,
    pub(crate) k1: u64,
    pub(crate) k2: u64,
    pub(crate) k3: u64,
}

impl fmt::Debug for RandomState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("RandomState { .. }")
    }
}

impl RandomState {
    /// Use randomly generated keys
    #[inline]
    pub fn new() -> RandomState {
        #[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
        {
            let seeds = *SEEDS;
            RandomState::from_keys(seeds[0], seeds[1])
        }
        #[cfg(all(feature = "compile-time-rng", any(not(feature = "runtime-rng"), test)))]
        {
            RandomState::from_keys(
                [const_random!(u64), const_random!(u64), const_random!(u64), const_random!(u64)],
                [const_random!(u64), const_random!(u64), const_random!(u64), const_random!(u64)],
            )
        }
        #[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
        {
            RandomState::from_keys(PI, PI2)
        }
    }

    /// Allows for supplying seeds, but each time it is called the resulting state will be different.
    /// This is done using a static counter, so it can safely be used with a fixed keys.
    #[inline]
    pub fn generate_with(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState {
        RandomState::from_keys(seeds(), [k0, k1, k2, k3])
    }

    fn from_keys(a: [u64; 4], b: [u64; 4]) -> RandomState {
        let [k0, k1, k2, k3] = a;
        let mut hasher = AHasher::from_random_state(&RandomState { k0, k1, k2, k3 });

        let stack_mem_loc = &hasher as *const _ as usize;
        #[cfg(not(all(target_arch="arm", target_os="none")))]
        {
            hasher.write_usize(COUNTER.fetch_add(stack_mem_loc, Ordering::Relaxed));
        }
        #[cfg(all(target_arch="arm", target_os="none"))]
        {
            let previous = COUNTER.load(Ordering::Relaxed);
            let new = previous.wrapping_add(stack_mem_loc);
            COUNTER.store(new, Ordering::Relaxed);
            hasher.write_usize(new);
        }
        #[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
        hasher.write_usize(&PI as *const _ as usize);
        let mix = |k: u64| {
            let mut h = hasher.clone();
            h.write_u64(k);
            h.finish()
        };

        RandomState { k0: mix(b[0]), k1: mix(b[1]), k2: mix(b[2]), k3: mix(b[3]) }
    }

    /// Internal. Used by Default.
    #[inline]
    pub(crate) fn with_fixed_keys() -> RandomState {
        let [k0, k1, k2, k3] = seeds();
        RandomState { k0, k1, k2, k3 }
    }

    /// Allows for explicitly setting the seeds to used.
    #[inline]
    pub const fn with_seeds(k0: u64, k1: u64, k2: u64, k3: u64) -> RandomState {
        RandomState { k0, k1, k2, k3 }
    }
}

impl Default for RandomState {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl BuildHasher for RandomState {
    type Hasher = AHasher;

    /// Constructs a new [AHasher] with keys based on this [RandomState] object.
    /// This means that two different [RandomState]s will will generate
    /// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
    /// will generate the same hashes for the same input data.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::{AHasher, RandomState};
    /// use std::hash::{Hasher, BuildHasher};
    ///
    /// let build_hasher = RandomState::new();
    /// let mut hasher_1 = build_hasher.build_hasher();
    /// let mut hasher_2 = build_hasher.build_hasher();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    ///
    /// let other_build_hasher = RandomState::new();
    /// let mut different_hasher = other_build_hasher.build_hasher();
    /// different_hasher.write_u32(1234);
    /// assert_ne!(different_hasher.finish(), hasher_1.finish());
    /// ```
    /// [Hasher]: std::hash::Hasher
    /// [BuildHasher]: std::hash::BuildHasher
    /// [HashMap]: std::collections::HashMap
    #[inline]
    fn build_hasher(&self) -> AHasher {
        AHasher::from_random_state(self)
    }
}

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

    #[test]
    fn test_unique() {
        let a = RandomState::new();
        let b = RandomState::new();
        assert_ne!(a.build_hasher().finish(), b.build_hasher().finish());
    }

    #[cfg(all(feature = "runtime-rng", not(all(feature = "compile-time-rng", test))))]
    #[test]
    fn test_not_pi() {
        assert_ne!(PI, seeds());
    }

    #[cfg(all(feature = "compile-time-rng", any(not(feature = "runtime-rng"), test)))]
    #[test]
    fn test_not_pi_const() {
        assert_ne!(PI, seeds());
    }

    #[cfg(all(not(feature = "runtime-rng"), not(feature = "compile-time-rng")))]
    #[test]
    fn test_pi() {
        assert_eq!(PI, seeds());
    }

    #[test]
    fn test_with_seeds_const() {
        const _CONST_RANDOM_STATE: RandomState = RandomState::with_seeds(17, 19, 21, 23);
    }
}
<|endoftext|>


<commit_before>extern crate zmq;

use std::thread;
use std::str;

#[test]
fn test_inproc() {
    shared_context("inproc://pub");
}

#[test]
fn test_tcp() {
    shared_context("tcp://127.0.0.1:*");
}

fn shared_context(address: &str) {
    let ctx = zmq::Context::new();

    let push_socket = ctx.socket(zmq::PUSH).unwrap();
    push_socket.bind(address).unwrap();
    let endpoint = push_socket.get_last_endpoint().unwrap().unwrap();
    let worker1 = fork(&ctx, endpoint);

    push_socket.send(b"Message1", 0).unwrap();

    worker1.join().unwrap();
}

fn fork(ctx: &zmq::Context, endpoint: String) -> thread::JoinHandle<()> {
    let w_ctx = ctx.clone();
    thread::spawn(move || { worker(&w_ctx, &endpoint); })
}

fn worker(ctx: &zmq::Context, endpoint: &str) {
    let pull_socket = connect_socket(ctx, zmq::PULL, endpoint).unwrap();

    let mut msg = zmq::Message::new().unwrap();
    pull_socket.recv(&mut msg, 0).unwrap();
    assert_eq!(&msg[..], b"Message1");
}

fn connect_socket(ctx: &zmq::Context,
                  typ: zmq::SocketType,
                  address: &str) -> Result<zmq::Socket, zmq::Error> {
    ctx.socket(typ).and_then(|socket| socket.connect(address).map(|_| socket))
}
<commit_msg>Tiny simplification in tests<commit_after>extern crate zmq;

use std::thread;
use std::str;

#[test]
fn test_inproc() {
    shared_context("inproc://pub");
}

#[test]
fn test_tcp() {
    shared_context("tcp://127.0.0.1:*");
}

fn shared_context(address: &str) {
    let ctx = zmq::Context::new();

    let push_socket = ctx.socket(zmq::PUSH).unwrap();
    push_socket.bind(address).unwrap();
    let endpoint = push_socket.get_last_endpoint().unwrap().unwrap();
    let worker1 = fork(&ctx, endpoint);

    push_socket.send(b"Message1", 0).unwrap();

    worker1.join().unwrap();
}

fn fork(ctx: &zmq::Context, endpoint: String) -> thread::JoinHandle<()> {
    let w_ctx = ctx.clone();
    thread::spawn(move || { worker(&w_ctx, &endpoint); })
}

fn worker(ctx: &zmq::Context, endpoint: &str) {
    let pull_socket = connect_socket(ctx, zmq::PULL, endpoint).unwrap();

    let msg = pull_socket.recv_msg(0).unwrap();
    assert_eq!(&msg[..], b"Message1");
}

fn connect_socket(ctx: &zmq::Context,
                  typ: zmq::SocketType,
                  address: &str) -> Result<zmq::Socket, zmq::Error> {
    ctx.socket(typ).and_then(|socket| socket.connect(address).map(|_| socket))
}
<|endoftext|>


<commit_before>use crate::common::BinarySerializable;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::borrow::Borrow;
use std::borrow::Cow;
use std::fmt::{self, Debug, Display, Formatter};
use std::io::{self, Read, Write};
use std::str;
use std::string::FromUtf8Error;

const SLASH_BYTE: u8 = b'/';
const ESCAPE_BYTE: u8 = b'\\';

/// BYTE used as a level separation in the binary
/// representation of facets.
pub const FACET_SEP_BYTE: u8 = 0u8;

/// `char` used as a level separation in the binary
/// representation of facets. (It is the null codepoint.)
pub const FACET_SEP_CHAR: char = '\u{0}';

/// A Facet represent a point in a given hierarchy.
///
/// They are typically represented similarly to a filepath.
/// For instance, an e-commerce website could
/// have a `Facet` for `/electronics/tv_and_video/led_tv`.
///
/// A document can be associated to any number of facets.
/// The hierarchy implicitely imply that a document
/// belonging to a facet also belongs to the ancestor of
/// its facet. In the example above, `/electronics/tv_and_video/`
/// and `/electronics`.
#[derive(Clone, Eq, Hash, PartialEq, Ord, PartialOrd)]
pub struct Facet(String);

impl Facet {
    /// Returns a new instance of the "root facet"
    /// Equivalent to `/`.
    pub fn root() -> Facet {
        Facet("".to_string())
    }

    /// Returns true iff the facet is the root facet `/`.
    pub fn is_root(&self) -> bool {
        self.encoded_str().is_empty()
    }

    /// Returns a binary representation of the facet.
    ///
    /// In this representation, `0u8` is used as a separator
    /// and the string parts of the facet are unescaped.
    /// (The first `/` is not encoded at all).
    ///
    /// This representation has the benefit of making it possible to
    /// express "being a child of a given facet" as a range over
    /// the term ordinals.
    pub fn encoded_str(&self) -> &str {
        &self.0
    }

    pub(crate) fn from_encoded_string(facet_string: String) -> Facet {
        Facet(facet_string)
    }

    /// Creates a `Facet` from its binary representation.
    pub fn from_encoded(encoded_bytes: Vec<u8>) -> Result<Facet, FromUtf8Error> {
        // facet bytes validation. `0u8` is used a separator but that is still legal utf-8
        //Ok(Facet(String::from_utf8(encoded_bytes)?))
        String::from_utf8(encoded_bytes).map(Facet)
    }

    /// Parse a text representation of a facet.
    ///
    /// It is conceptually, if one of the steps of this path
    /// contains a `/` or a `\`, it should be escaped
    /// using an anti-slash `/`.
    pub fn from_text<T>(path: &T) -> Facet
    where
        T: ?Sized + AsRef<str>,
    {
        From::from(path)
    }

    /// Returns a `Facet` from an iterator over the different
    /// steps of the facet path.
    ///
    /// The steps are expected to be unescaped.
    pub fn from_path<Path>(path: Path) -> Facet
    where
        Path: IntoIterator,
        Path::Item: ToString,
    {
        let mut facet_string: String = String::with_capacity(100);
        let mut step_it = path.into_iter();
        if let Some(step) = step_it.next() {
            facet_string.push_str(&step.to_string());
        }
        for step in step_it {
            facet_string.push(FACET_SEP_CHAR);
            facet_string.push_str(&step.to_string());
        }
        Facet(facet_string)
    }

    /// Accessor for the inner buffer of the `Facet`.
    pub(crate) fn set_facet_str(&mut self, facet_str: &str) {
        self.0.clear();
        self.0.push_str(facet_str);
    }

    /// Returns `true` iff other is a subfacet of `self`.
    pub fn is_prefix_of(&self, other: &Facet) -> bool {
        let self_str = self.encoded_str();
        let other_str = other.encoded_str();
        self_str.len() < other_str.len()
            && other_str.starts_with(self_str)
            && other_str.as_bytes()[self_str.len()] == FACET_SEP_BYTE
    }

    /// Extract path from the `Facet`.
    pub fn to_path(&self) -> Vec<&str> {
        self.encoded_str().split(|c| c == FACET_SEP_CHAR).collect()
    }
}

impl Borrow<str> for Facet {
    fn borrow(&self) -> &str {
        self.encoded_str()
    }
}

impl<'a, T: ?Sized + AsRef<str>> From<&'a T> for Facet {
    fn from(path_asref: &'a T) -> Facet {
        #[derive(Copy, Clone)]
        enum State {
            Escaped,
            Idle,
        }
        let path: &str = path_asref.as_ref();
        assert!(!path.is_empty());
        assert!(path.starts_with('/'));
        let mut facet_encoded = String::new();
        let mut state = State::Idle;
        let path_bytes = path.as_bytes();
        let mut last_offset = 1;
        for i in 1..path_bytes.len() {
            let c = path_bytes[i];
            match (state, c) {
                (State::Idle, ESCAPE_BYTE) => {
                    facet_encoded.push_str(&path[last_offset..i]);
                    last_offset = i + 1;
                    state = State::Escaped
                }
                (State::Idle, SLASH_BYTE) => {
                    facet_encoded.push_str(&path[last_offset..i]);
                    facet_encoded.push(FACET_SEP_CHAR);
                    last_offset = i + 1;
                }
                (State::Escaped, _escaped_char) => {
                    state = State::Idle;
                }
                (State::Idle, _any_char) => {}
            }
        }
        facet_encoded.push_str(&path[last_offset..]);
        Facet(facet_encoded)
    }
}

impl BinarySerializable for Facet {
    fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
        <String as BinarySerializable>::serialize(&self.0, writer)
    }

    fn deserialize<R: Read>(reader: &mut R) -> io::Result<Self> {
        Ok(Facet(<String as BinarySerializable>::deserialize(reader)?))
    }
}

impl Display for Facet {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        for step in self.0.split(FACET_SEP_CHAR) {
            write!(f, "/")?;
            write!(f, "{}", escape_slashes(step))?;
        }
        Ok(())
    }
}

fn escape_slashes(s: &str) -> Cow<'_, str> {
    static SLASH_PTN: Lazy<Regex> = Lazy::new(|| Regex::new(r"[\\/]").unwrap());
    SLASH_PTN.replace_all(s, "\\/")
}

impl Serialize for Facet {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

impl<'de> Deserialize<'de> for Facet {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        <&'de str as Deserialize<'de>>::deserialize(deserializer).map(Facet::from)
    }
}

impl Debug for Facet {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "Facet({})", self)?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {

    use super::Facet;

    #[test]
    fn test_root() {
        assert_eq!(Facet::root(), Facet::from("/"));
        assert_eq!(format!("{}", Facet::root()), "/");
        assert!(Facet::root().is_root());
    }

    #[test]
    fn test_from_path() {
        assert_eq!(
            Facet::from_path(vec!["top", "a", "firstdoc"]),
            Facet::from("/top/a/firstdoc")
        );
    }

    #[test]
    fn test_facet_display() {
        {
            let v = ["first", "second", "third"];
            let facet = Facet::from_path(v.iter());
            assert_eq!(format!("{}", facet), "/first/second/third");
        }
        {
            let v = ["first", "sec/ond", "third"];
            let facet = Facet::from_path(v.iter());
            assert_eq!(format!("{}", facet), "/first/sec\\/ond/third");
        }
    }

    #[test]
    fn test_facet_debug() {
        let v = ["first", "second", "third"];
        let facet = Facet::from_path(v.iter());
        assert_eq!(format!("{:?}", facet), "Facet(/first/second/third)");
    }

    #[test]
    fn test_to_path() {
        let v = ["first", "second", "third\\/not_fourth"];
        let facet = Facet::from_path(v.iter());
        assert_eq!(facet.to_path(), v);
    }
}
<commit_msg>Facet path string (#759)<commit_after>use crate::common::BinarySerializable;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::borrow::Borrow;
use std::borrow::Cow;
use std::fmt::{self, Debug, Display, Formatter};
use std::io::{self, Read, Write};
use std::str;
use std::string::FromUtf8Error;

const SLASH_BYTE: u8 = b'/';
const ESCAPE_BYTE: u8 = b'\\';

/// BYTE used as a level separation in the binary
/// representation of facets.
pub const FACET_SEP_BYTE: u8 = 0u8;

/// `char` used as a level separation in the binary
/// representation of facets. (It is the null codepoint.)
pub const FACET_SEP_CHAR: char = '\u{0}';

/// A Facet represent a point in a given hierarchy.
///
/// They are typically represented similarly to a filepath.
/// For instance, an e-commerce website could
/// have a `Facet` for `/electronics/tv_and_video/led_tv`.
///
/// A document can be associated to any number of facets.
/// The hierarchy implicitely imply that a document
/// belonging to a facet also belongs to the ancestor of
/// its facet. In the example above, `/electronics/tv_and_video/`
/// and `/electronics`.
#[derive(Clone, Eq, Hash, PartialEq, Ord, PartialOrd)]
pub struct Facet(String);

impl Facet {
    /// Returns a new instance of the "root facet"
    /// Equivalent to `/`.
    pub fn root() -> Facet {
        Facet("".to_string())
    }

    /// Returns true iff the facet is the root facet `/`.
    pub fn is_root(&self) -> bool {
        self.encoded_str().is_empty()
    }

    /// Returns a binary representation of the facet.
    ///
    /// In this representation, `0u8` is used as a separator
    /// and the string parts of the facet are unescaped.
    /// (The first `/` is not encoded at all).
    ///
    /// This representation has the benefit of making it possible to
    /// express "being a child of a given facet" as a range over
    /// the term ordinals.
    pub fn encoded_str(&self) -> &str {
        &self.0
    }

    pub(crate) fn from_encoded_string(facet_string: String) -> Facet {
        Facet(facet_string)
    }

    /// Creates a `Facet` from its binary representation.
    pub fn from_encoded(encoded_bytes: Vec<u8>) -> Result<Facet, FromUtf8Error> {
        // facet bytes validation. `0u8` is used a separator but that is still legal utf-8
        //Ok(Facet(String::from_utf8(encoded_bytes)?))
        String::from_utf8(encoded_bytes).map(Facet)
    }

    /// Parse a text representation of a facet.
    ///
    /// It is conceptually, if one of the steps of this path
    /// contains a `/` or a `\`, it should be escaped
    /// using an anti-slash `/`.
    pub fn from_text<T>(path: &T) -> Facet
    where
        T: ?Sized + AsRef<str>,
    {
        From::from(path)
    }

    /// Returns a `Facet` from an iterator over the different
    /// steps of the facet path.
    ///
    /// The steps are expected to be unescaped.
    pub fn from_path<Path>(path: Path) -> Facet
    where
        Path: IntoIterator,
        Path::Item: ToString,
    {
        let mut facet_string: String = String::with_capacity(100);
        let mut step_it = path.into_iter();
        if let Some(step) = step_it.next() {
            facet_string.push_str(&step.to_string());
        }
        for step in step_it {
            facet_string.push(FACET_SEP_CHAR);
            facet_string.push_str(&step.to_string());
        }
        Facet(facet_string)
    }

    /// Accessor for the inner buffer of the `Facet`.
    pub(crate) fn set_facet_str(&mut self, facet_str: &str) {
        self.0.clear();
        self.0.push_str(facet_str);
    }

    /// Returns `true` iff other is a subfacet of `self`.
    pub fn is_prefix_of(&self, other: &Facet) -> bool {
        let self_str = self.encoded_str();
        let other_str = other.encoded_str();
        self_str.len() < other_str.len()
            && other_str.starts_with(self_str)
            && other_str.as_bytes()[self_str.len()] == FACET_SEP_BYTE
    }

    /// Extract path from the `Facet`.
    pub fn to_path(&self) -> Vec<&str> {
        self.encoded_str().split(|c| c == FACET_SEP_CHAR).collect()
    }

    /// This function is the inverse of Facet::from(&str).
    pub fn to_path_string(&self) -> String {
        format!("{}", self.to_string())
    }
}

impl Borrow<str> for Facet {
    fn borrow(&self) -> &str {
        self.encoded_str()
    }
}

impl<'a, T: ?Sized + AsRef<str>> From<&'a T> for Facet {
    fn from(path_asref: &'a T) -> Facet {
        #[derive(Copy, Clone)]
        enum State {
            Escaped,
            Idle,
        }
        let path: &str = path_asref.as_ref();
        assert!(!path.is_empty());
        assert!(path.starts_with('/'));
        let mut facet_encoded = String::new();
        let mut state = State::Idle;
        let path_bytes = path.as_bytes();
        let mut last_offset = 1;
        for i in 1..path_bytes.len() {
            let c = path_bytes[i];
            match (state, c) {
                (State::Idle, ESCAPE_BYTE) => {
                    facet_encoded.push_str(&path[last_offset..i]);
                    last_offset = i + 1;
                    state = State::Escaped
                }
                (State::Idle, SLASH_BYTE) => {
                    facet_encoded.push_str(&path[last_offset..i]);
                    facet_encoded.push(FACET_SEP_CHAR);
                    last_offset = i + 1;
                }
                (State::Escaped, _escaped_char) => {
                    state = State::Idle;
                }
                (State::Idle, _any_char) => {}
            }
        }
        facet_encoded.push_str(&path[last_offset..]);
        Facet(facet_encoded)
    }
}

impl BinarySerializable for Facet {
    fn serialize<W: Write>(&self, writer: &mut W) -> io::Result<()> {
        <String as BinarySerializable>::serialize(&self.0, writer)
    }

    fn deserialize<R: Read>(reader: &mut R) -> io::Result<Self> {
        Ok(Facet(<String as BinarySerializable>::deserialize(reader)?))
    }
}

impl Display for Facet {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        for step in self.0.split(FACET_SEP_CHAR) {
            write!(f, "/")?;
            write!(f, "{}", escape_slashes(step))?;
        }
        Ok(())
    }
}

fn escape_slashes(s: &str) -> Cow<'_, str> {
    static SLASH_PTN: Lazy<Regex> = Lazy::new(|| Regex::new(r"[\\/]").unwrap());
    SLASH_PTN.replace_all(s, "\\/")
}

impl Serialize for Facet {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

impl<'de> Deserialize<'de> for Facet {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        <&'de str as Deserialize<'de>>::deserialize(deserializer).map(Facet::from)
    }
}

impl Debug for Facet {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "Facet({})", self)?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {

    use super::Facet;

    #[test]
    fn test_root() {
        assert_eq!(Facet::root(), Facet::from("/"));
        assert_eq!(format!("{}", Facet::root()), "/");
        assert!(Facet::root().is_root());
    }

    #[test]
    fn test_from_path() {
        assert_eq!(
            Facet::from_path(vec!["top", "a", "firstdoc"]),
            Facet::from("/top/a/firstdoc")
        );
    }

    #[test]
    fn test_facet_display() {
        {
            let v = ["first", "second", "third"];
            let facet = Facet::from_path(v.iter());
            assert_eq!(format!("{}", facet), "/first/second/third");
        }
        {
            let v = ["first", "sec/ond", "third"];
            let facet = Facet::from_path(v.iter());
            assert_eq!(format!("{}", facet), "/first/sec\\/ond/third");
        }
    }

    #[test]
    fn test_facet_debug() {
        let v = ["first", "second", "third"];
        let facet = Facet::from_path(v.iter());
        assert_eq!(format!("{:?}", facet), "Facet(/first/second/third)");
    }

    #[test]
    fn test_to_path() {
        let v = ["first", "second", "third\\/not_fourth"];
        let facet = Facet::from_path(v.iter());
        assert_eq!(facet.to_path(), v);
    }

    #[test]
    fn test_to_path_string() {
        let v = ["first", "second", "third/not_fourth"];
        let facet = Facet::from_path(v.iter());
        assert_eq!(
            facet.to_path_string(),
            String::from("/first/second/third\\/not_fourth")
        );
    }

    #[test]
    fn test_to_path_string_empty() {
        let v: Vec<&str> = vec![];
        let facet = Facet::from_path(v.iter());
        assert_eq!(facet.to_path_string(), "/");
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// 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.

use logging::*;
use scheduler::*;

#[no_mangle]
pub extern "C" fn sys_exit(status: i32)
{
	info!("enter syscall exit {}", status);
	do_exit();
}
<commit_msg>remove debug message<commit_after>// Copyright (c) 2017 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// 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.

use scheduler::*;

#[no_mangle]
pub extern "C" fn sys_exit(_status: i32)
{
	do_exit();
}
<|endoftext|>


<commit_before>use tensor::{Tensor, NumLimits, THVec, THVecGeneric, THDims};
use num::NumCast;

impl<T: NumLimits> THVec<T> {
    pub fn new(dims: Vec<usize>, data: Vec<T>) -> Self {
        THVec {
            dims: dims,
            data: data,
        }
    }
}
impl THVecGeneric {
    pub fn new(dims: Vec<usize>, data: Vec<i64>) -> Self {
        THVecGeneric {
            dims: dims,
            data: data,
        }
    }
}
impl THDims {
    fn new(dims: Vec<usize>) -> Self {
        THDims { dims: dims }
    }
}
impl<T: NumLimits> From<Vec<Vec<Vec<T>>>> for THVec<T> {
    fn from(input: Vec<Vec<Vec<T>>>) -> Self {
        let dims = vec![input.len(), input[0].len(), input[0][0].len()];
        let v = input
            .iter()
            .flat_map(|d| d.iter())
            .flat_map(|d| d.iter())
            .map(|d| *d)
            .collect();
        THVec::new(dims, v)
    }
}

impl<T: NumLimits> From<Vec<Vec<T>>> for THVec<T> {
    fn from(input: Vec<Vec<T>>) -> Self {
        let dims = vec![input.len(), input[0].len()];
        let v = input.iter().flat_map(|d| d.iter()).map(|d| *d).collect();
        THVec::new(dims, v)
    }
}
impl<T: NumLimits> From<Vec<T>> for THVec<T> {
    fn from(input: Vec<T>) -> Self {
        let dims = vec![input.len()];
        THVec::new(dims, input)
    }
}
impl<T: NumLimits> From<T> for THVec<T> {
    fn from(input: T) -> Self {
        let v = vec![input];
        THVec::new(vec![1], v)
    }
}
impl<T: NumLimits> From<T> for THVecGeneric {
    fn from(input: T) -> Self {
        let v: Vec<i64> = vec![<i64 as NumCast>::from(input).unwrap()];
        THVecGeneric::new(vec![1], v)
    }
}

#[allow(unused_variables)]
impl<T: NumLimits> From<()> for THVec<T> {
    fn from(input: ()) -> Self {
        THVec::new(vec![], vec![])
    }
}
#[allow(unused_variables)]
impl From<()> for THVecGeneric {
    fn from(input: ()) -> Self {
        THVecGeneric::new(vec![], vec![])
    }
}
#[allow(unused_variables)]
impl From<()> for THDims {
    fn from(input: ()) -> Self {
        THDims::new(vec![])
    }
}
impl<T: NumLimits> From<[usize; 2]> for THVec<T> {
    fn from(input: [usize; 2]) -> Self {
        THVec::new(input.to_vec(), vec![])
    }
}
impl<T: NumLimits> From<[usize; 4]> for THVec<T> {
    fn from(input: [usize; 4]) -> Self {
        THVec::new(input.to_vec(), vec![])
    }
}
impl<T: NumLimits> From<(usize, usize)> for THVec<T> {
    fn from(input: (usize, usize)) -> Self {
        THVec::new(vec![input.0, input.1], vec![])
    }
}
impl From<(usize, usize)> for THVecGeneric {
    fn from(input: (usize, usize)) -> Self {

        THVecGeneric::new(vec![input.0, input.1], vec![])
    }
}
impl From<(usize)> for THVecGeneric {
    fn from(input: (usize)) -> Self {

        THVecGeneric::new(vec![input], vec![])
    }
}
impl<T: NumLimits> From<(usize)> for THVec<T> {
    fn from(input: (usize)) -> Self {
        THVec::new(vec![input], vec![])
    }
}
impl<T: NumLimits> From<Vec<usize>> for THVec<T> {
    fn from(input: Vec<usize>) -> Self {
        THVec::new(input, vec![])
    }
}
impl From<Vec<usize>> for THVecGeneric {
    fn from(input: Vec<usize>) -> Self {
        THVecGeneric::new(input, vec![])
    }
}
impl From<Vec<usize>> for THDims {
    fn from(input: Vec<usize>) -> Self {
        THDims::new(input)
    }
}
impl<S: NumLimits, D: NumLimits> From<Tensor<S>> for THVec<D> {
    fn from(input: Tensor<S>) -> Self {
        unimplemented!()
    }
}
impl<T: NumLimits> From<Vec<THVec<T>>> for THVec<T> {
    fn from(input: Vec<THVec<T>>) -> Self {
        unimplemented!()
    }
}
impl<S: NumLimits, D: NumLimits> From<Vec<Tensor<S>>> for THVec<D> {
    fn from(input: Vec<Tensor<S>>) -> Self {
        let mut d: Vec<D> = Vec::with_capacity(input.len() * input[0].len());
        let len = input[0].len();
        let mut tmp: Vec<S> = Vec::with_capacity(len);
        unsafe {
            d.set_len(input.len() * input[0].len());
            tmp.set_len(len);
        }
        for i in 0..input.len() {
            input[i].get_storage(&mut tmp, len);
            for j in 0..len {
                unsafe {
                    *(d.get_unchecked_mut(i * len + j)) = <D as ::num::NumCast>::from(tmp[j])
                        .unwrap();
                }
            }
        }
        let mut sizes = input[0].size();
        let mut dims = vec![input.len()];
        dims.append(&mut sizes);
        THVec::new(dims, d)
    }
}
impl From<THVecGeneric> for THVec<u8> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<u8> = input
            .data
            .iter()
            .map(|t| <u8 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}
impl From<THVecGeneric> for THVec<f32> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<f32> = input
            .data
            .iter()
            .map(|t| <f32 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}
impl From<THVecGeneric> for THVec<i64> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<i64> = input
            .data
            .iter()
            .map(|t| <i64 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}

impl<T: NumLimits> From<THVec<T>> for THDims {
    fn from(input: THVec<T>) -> Self {
        THDims::new(input.dims.clone())
    }
}
impl From<THVecGeneric> for THDims {
    fn from(input: THVecGeneric) -> Self {
        THDims::new(input.dims.clone())
    }
}

trait TensorNew<T: NumLimits> {
    fn tensor_new(arg: THDims) -> Tensor<T>;
}

impl<T: NumLimits> TensorNew<T> for Tensor<T> {
    #[allow(unused_variables)]
    default fn tensor_new(arg: THDims) -> Tensor<T> {
        unreachable!()
    }
}

impl TensorNew<u8> for Tensor<u8> {
    fn tensor_new(arg: THDims) -> Tensor<u8> {
        let t = ::RcMutNew(::tensor::ByteTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<i64> for Tensor<i64> {
    fn tensor_new(arg: THDims) -> Tensor<i64> {
        let t = ::RcMutNew(::tensor::LongTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<f32> for Tensor<f32> {
    fn tensor_new(arg: THDims) -> Tensor<f32> {
        let t = ::RcMutNew(::tensor::FloatTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<f64> for Tensor<f64> {
    fn tensor_new(arg: THDims) -> Tensor<f64> {
        let t = ::RcMutNew(::tensor::DoubleTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}

pub fn byte_tensor<T>(arg: T) -> Tensor<u8>
    where T: Into<THVec<u8>>
{
    tensor(arg)
}
pub fn long_tensor<T>(arg: T) -> Tensor<i64>
    where T: Into<THVec<i64>>
{
    tensor(arg)
}
pub fn float_tensor<T>(arg: T) -> Tensor<f32>
    where T: Into<THVec<f32>>
{
    tensor(arg)
}
pub fn double_tensor<T>(arg: T) -> Tensor<f64>
    where T: Into<THVec<f64>>
{
    tensor(arg)
}
pub fn zeros<S, T>(arg: S) -> Tensor<T>
    where T: NumLimits,
          S: Into<THVec<T>>
{
    tensor(arg).zero_()
}
pub fn tensor<S, T>(arg: S) -> Tensor<T>
    where T: NumLimits,
          S: Into<THVec<T>>
{
    let t: THVec<T> = arg.into();
    let dims = t.dims.clone().into();
    let mut out = Tensor::tensor_new(dims);
    if t.data.len() > 0 {
        out.set_storage(t.data);
    }
    out
}
<commit_msg>s/len/numel/, silence warnings<commit_after>use tensor::{Tensor, NumLimits, THVec, THVecGeneric, THDims};
use num::NumCast;

impl<T: NumLimits> THVec<T> {
    pub fn new(dims: Vec<usize>, data: Vec<T>) -> Self {
        THVec {
            dims: dims,
            data: data,
        }
    }
}
impl THVecGeneric {
    pub fn new(dims: Vec<usize>, data: Vec<i64>) -> Self {
        THVecGeneric {
            dims: dims,
            data: data,
        }
    }
}
impl THDims {
    fn new(dims: Vec<usize>) -> Self {
        THDims { dims: dims }
    }
}
impl<T: NumLimits> From<Vec<Vec<Vec<T>>>> for THVec<T> {
    fn from(input: Vec<Vec<Vec<T>>>) -> Self {
        let dims = vec![input.len(), input[0].len(), input[0][0].len()];
        let v = input
            .iter()
            .flat_map(|d| d.iter())
            .flat_map(|d| d.iter())
            .map(|d| *d)
            .collect();
        THVec::new(dims, v)
    }
}

impl<T: NumLimits> From<Vec<Vec<T>>> for THVec<T> {
    fn from(input: Vec<Vec<T>>) -> Self {
        let dims = vec![input.len(), input[0].len()];
        let v = input.iter().flat_map(|d| d.iter()).map(|d| *d).collect();
        THVec::new(dims, v)
    }
}
impl<T: NumLimits> From<Vec<T>> for THVec<T> {
    fn from(input: Vec<T>) -> Self {
        let dims = vec![input.len()];
        THVec::new(dims, input)
    }
}
impl<T: NumLimits> From<T> for THVec<T> {
    fn from(input: T) -> Self {
        let v = vec![input];
        THVec::new(vec![1], v)
    }
}
impl<T: NumLimits> From<T> for THVecGeneric {
    fn from(input: T) -> Self {
        let v: Vec<i64> = vec![<i64 as NumCast>::from(input).unwrap()];
        THVecGeneric::new(vec![1], v)
    }
}

#[allow(unused_variables)]
impl<T: NumLimits> From<()> for THVec<T> {
    fn from(input: ()) -> Self {
        THVec::new(vec![], vec![])
    }
}
#[allow(unused_variables)]
impl From<()> for THVecGeneric {
    fn from(input: ()) -> Self {
        THVecGeneric::new(vec![], vec![])
    }
}
#[allow(unused_variables)]
impl From<()> for THDims {
    fn from(input: ()) -> Self {
        THDims::new(vec![])
    }
}
impl<T: NumLimits> From<[usize; 2]> for THVec<T> {
    fn from(input: [usize; 2]) -> Self {
        THVec::new(input.to_vec(), vec![])
    }
}
impl<T: NumLimits> From<[usize; 4]> for THVec<T> {
    fn from(input: [usize; 4]) -> Self {
        THVec::new(input.to_vec(), vec![])
    }
}
impl<T: NumLimits> From<(usize, usize)> for THVec<T> {
    fn from(input: (usize, usize)) -> Self {
        THVec::new(vec![input.0, input.1], vec![])
    }
}
impl From<(usize, usize)> for THVecGeneric {
    fn from(input: (usize, usize)) -> Self {

        THVecGeneric::new(vec![input.0, input.1], vec![])
    }
}
impl From<(usize)> for THVecGeneric {
    fn from(input: (usize)) -> Self {

        THVecGeneric::new(vec![input], vec![])
    }
}
impl<T: NumLimits> From<(usize)> for THVec<T> {
    fn from(input: (usize)) -> Self {
        THVec::new(vec![input], vec![])
    }
}
impl<T: NumLimits> From<Vec<usize>> for THVec<T> {
    fn from(input: Vec<usize>) -> Self {
        THVec::new(input, vec![])
    }
}
impl From<Vec<usize>> for THVecGeneric {
    fn from(input: Vec<usize>) -> Self {
        THVecGeneric::new(input, vec![])
    }
}
impl From<Vec<usize>> for THDims {
    fn from(input: Vec<usize>) -> Self {
        THDims::new(input)
    }
}
impl<S: NumLimits, D: NumLimits> From<Tensor<S>> for THVec<D> {
    #[allow(unused_variables)]
    fn from(input: Tensor<S>) -> Self {
        unimplemented!()
    }
}
impl<T: NumLimits> From<Vec<THVec<T>>> for THVec<T> {
    #[allow(unused_variables)]
    fn from(input: Vec<THVec<T>>) -> Self {
        unimplemented!()
    }
}
impl<S: NumLimits, D: NumLimits> From<Vec<Tensor<S>>> for THVec<D> {
    fn from(input: Vec<Tensor<S>>) -> Self {
        let mut d: Vec<D> = Vec::with_capacity(input.len() * input[0].numel());
        let len = input[0].numel();
        let mut tmp: Vec<S> = Vec::with_capacity(len);
        unsafe {
            d.set_len(input.len() * input[0].numel());
            tmp.set_len(len);
        }
        for i in 0..input.len() {
            input[i].get_storage(&mut tmp, len);
            for j in 0..len {
                unsafe {
                    *(d.get_unchecked_mut(i * len + j)) = <D as ::num::NumCast>::from(tmp[j])
                        .unwrap();
                }
            }
        }
        let mut sizes = input[0].size();
        let mut dims = vec![input.len()];
        dims.append(&mut sizes);
        THVec::new(dims, d)
    }
}
impl From<THVecGeneric> for THVec<u8> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<u8> = input
            .data
            .iter()
            .map(|t| <u8 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}
impl From<THVecGeneric> for THVec<f32> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<f32> = input
            .data
            .iter()
            .map(|t| <f32 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}
impl From<THVecGeneric> for THVec<i64> {
    fn from(input: THVecGeneric) -> Self {
        let data: Vec<i64> = input
            .data
            .iter()
            .map(|t| <i64 as NumCast>::from(*t).unwrap())
            .collect();
        THVec::new(input.dims.clone(), data)
    }
}

impl<T: NumLimits> From<THVec<T>> for THDims {
    fn from(input: THVec<T>) -> Self {
        THDims::new(input.dims.clone())
    }
}
impl From<THVecGeneric> for THDims {
    fn from(input: THVecGeneric) -> Self {
        THDims::new(input.dims.clone())
    }
}

trait TensorNew<T: NumLimits> {
    fn tensor_new(arg: THDims) -> Tensor<T>;
}

impl<T: NumLimits> TensorNew<T> for Tensor<T> {
    #[allow(unused_variables)]
    default fn tensor_new(arg: THDims) -> Tensor<T> {
        unreachable!()
    }
}

impl TensorNew<u8> for Tensor<u8> {
    fn tensor_new(arg: THDims) -> Tensor<u8> {
        let t = ::RcMutNew(::tensor::ByteTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<i64> for Tensor<i64> {
    fn tensor_new(arg: THDims) -> Tensor<i64> {
        let t = ::RcMutNew(::tensor::LongTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<f32> for Tensor<f32> {
    fn tensor_new(arg: THDims) -> Tensor<f32> {
        let t = ::RcMutNew(::tensor::FloatTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}
impl TensorNew<f64> for Tensor<f64> {
    fn tensor_new(arg: THDims) -> Tensor<f64> {
        let t = ::RcMutNew(::tensor::DoubleTensor::with_capacity(arg.dims.as_slice()));
        ::tensor::Tensor { value: t }
    }
}

pub fn byte_tensor<T>(arg: T) -> Tensor<u8>
    where T: Into<THVec<u8>>
{
    tensor(arg)
}
pub fn long_tensor<T>(arg: T) -> Tensor<i64>
    where T: Into<THVec<i64>>
{
    tensor(arg)
}
pub fn float_tensor<T>(arg: T) -> Tensor<f32>
    where T: Into<THVec<f32>>
{
    tensor(arg)
}
pub fn double_tensor<T>(arg: T) -> Tensor<f64>
    where T: Into<THVec<f64>>
{
    tensor(arg)
}
pub fn zeros<S, T>(arg: S) -> Tensor<T>
    where T: NumLimits,
          S: Into<THVec<T>>
{
    tensor(arg).zero_()
}
pub fn tensor<S, T>(arg: S) -> Tensor<T>
    where T: NumLimits,
          S: Into<THVec<T>>
{
    let t: THVec<T> = arg.into();
    let dims = t.dims.clone().into();
    let mut out = Tensor::tensor_new(dims);
    if t.data.len() > 0 {
        out.set_storage(t.data);
    }
    out
}
<|endoftext|>