<commit_before>use std::marker::PhantomData;
use std::io::{self};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};
use std::fmt;

use bincode::serde::{DeserializeError, SerializeError, serialize, deserialize};
use bincode;
use serde::{Serialize, Deserialize};

pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
}

#[derive(Debug)]
pub enum TransitError {
    IoError(io::Error),
    SerializeError(SerializeError),
    DeserializeError(DeserializeError),
}

impl Error for TransitError {
    fn description(&self) -> &str {
        match *self {
            TransitError::IoError(ref err) => Error::description(err),
            TransitError::SerializeError(ref err) => Error::description(err),
            TransitError::DeserializeError(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TransitError::IoError(ref err) => err.cause(),
            TransitError::SerializeError(ref err) => err.cause(),
            TransitError::DeserializeError(ref err) => err.cause(),
        }
    }
}

impl From<io::Error> for TransitError {
    fn from(err: io::Error) -> TransitError {
        TransitError::IoError(err)
    }
}

impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(err)
    }
}

impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(err)
    }
}

impl fmt::Display for TransitError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TransitError::IoError(ref err) =>
                write!(fmt, "IoError: {}", err),
            TransitError::DeserializeError(ref err) =>
                write!(fmt, "DeserializeError: {}", err),
            TransitError::SerializeError(ref err) =>
                write!(fmt, "SerializeError: {}", err),
        }
    }
}

/// Sends and receives types over UDP, removing any knowledge of buffers and dealing with the std
/// library.
///
/// This use the `bincode` crate to serialize objects. Does not currently support securely sending
/// packets over the network or ensuring that only packets of the correct type are serialized.
///
/// # Examples
///
/// ```rust
/// use std::io;
/// use transit::udp::*;
///
/// let transit = Transit::new("localhost:65000").unwrap();
/// let transit2 = Transit::new("localhost:65001").unwrap();
/// let test = String::from("hello, rust");
///
/// let res = transit.send_to(&test, "localhost:65001");
/// assert!(res.is_ok());
/// let res: Result<(String, _), TransitError> = transit2.recv_from();
/// assert!(res.is_ok());
/// let (data, _addr) = res.unwrap();
/// assert_eq!(data, "hello, rust");
/// ```
impl<T> Transit<T> {
    pub fn new<A>(addr: A) -> io::Result<Transit<T>> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
        })
    }

    /// On success, this function returns the type deserialized using the Deserialize trait
    /// implementation. It is not defined what happens when Transit trys to deserialize a different
    /// type into another currently.
    pub fn recv_from(&self) -> Result<(T, SocketAddr), TransitError> where T: Deserialize {
        let mut buf = [0; 65535]; // Max size of UDP packet
        let (n, addr) = try!(self.socket.recv_from(&mut buf));
        let data = try!(deserialize(&buf[..n]));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let sizelimit = bincode::SizeLimit::Bounded(65535);
        let vec = try!(serialize(pkt, sizelimit));
        try!(self.socket.send_to(&vec[..], addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> io::Result<SocketAddr> {
        self.socket.local_addr()
    }
}

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

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: String,
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_string() {
        let addr1 = "127.0.0.1:63001";
        let addr2 = "127.0.0.1:63002";
        let transit1: Transit<String> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = String::from("hello");

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_bytes() {
        let addr1 = "127.0.0.1:64001";
        let addr2 = "127.0.0.1:64002";
        let transit1 = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let vec = vec!(9u8);
        let slice = &vec[..];

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res: Result<(Vec<u8>, _), TransitError> = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, vec);
    }

    // TODO: How to ensure different types are not deserialized as each other with bincode?
    // #[test]
    // fn test_packet_type() {
    //     let addr1 = "127.0.0.1:62001";
    //     let addr2 = "127.0.0.1:62002";
    //     let transit1: Transit<Another> = Transit::new(addr1).unwrap();
    //     let transit2: Transit<Test> = Transit::new(addr2).unwrap();
    //     let test = Another { data: String::from("Hello") };

    //     let res = transit1.send_to(&test, addr2);
    //     assert!(res.is_ok());
    //     let res = transit2.recv_from();
    //     assert!(res.is_err());
    // }
}
<commit_msg>Use TransitError  in the return values<commit_after>use std::marker::PhantomData;
use std::io::{self};
use std::error::Error;
use std::net::{UdpSocket, SocketAddr, ToSocketAddrs};
use std::fmt;

use bincode::serde::{DeserializeError, SerializeError, serialize, deserialize};
use bincode;
use serde::{Serialize, Deserialize};

pub struct Transit<T> {
    socket: UdpSocket,
    packet_type: PhantomData<T>,
}

#[derive(Debug)]
pub enum TransitError {
    IoError(io::Error),
    SerializeError(SerializeError),
    DeserializeError(DeserializeError),
}

impl Error for TransitError {
    fn description(&self) -> &str {
        match *self {
            TransitError::IoError(ref err) => Error::description(err),
            TransitError::SerializeError(ref err) => Error::description(err),
            TransitError::DeserializeError(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            TransitError::IoError(ref err) => err.cause(),
            TransitError::SerializeError(ref err) => err.cause(),
            TransitError::DeserializeError(ref err) => err.cause(),
        }
    }
}

impl From<io::Error> for TransitError {
    fn from(err: io::Error) -> TransitError {
        TransitError::IoError(err)
    }
}

impl From<DeserializeError> for TransitError {
    fn from(err: DeserializeError) -> TransitError {
        TransitError::DeserializeError(err)
    }
}

impl From<SerializeError> for TransitError {
    fn from(err: SerializeError) -> TransitError {
        TransitError::SerializeError(err)
    }
}

impl fmt::Display for TransitError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            TransitError::IoError(ref err) =>
                write!(fmt, "IoError: {}", err),
            TransitError::DeserializeError(ref err) =>
                write!(fmt, "DeserializeError: {}", err),
            TransitError::SerializeError(ref err) =>
                write!(fmt, "SerializeError: {}", err),
        }
    }
}

/// Sends and receives types over UDP, removing any knowledge of buffers and dealing with the std
/// library.
///
/// This use the `bincode` crate to serialize objects. Does not currently support securely sending
/// packets over the network or ensuring that only packets of the correct type are serialized.
///
/// # Examples
///
/// ```rust
/// use std::io;
/// use transit::udp::*;
///
/// let transit = Transit::new("localhost:65000").unwrap();
/// let transit2 = Transit::new("localhost:65001").unwrap();
/// let test = String::from("hello, rust");
///
/// let res = transit.send_to(&test, "localhost:65001");
/// assert!(res.is_ok());
/// let res: Result<(String, _), TransitError> = transit2.recv_from();
/// assert!(res.is_ok());
/// let (data, _addr) = res.unwrap();
/// assert_eq!(data, "hello, rust");
/// ```
impl<T> Transit<T> {
    pub fn new<A>(addr: A) -> Result<Transit<T>, TransitError> where A: ToSocketAddrs {
        let socket = try!(UdpSocket::bind(addr));
        Ok(Transit {
            socket: socket,
            packet_type: PhantomData,
        })
    }

    /// On success, this function returns the type deserialized using the Deserialize trait
    /// implementation. It is not defined what happens when Transit trys to deserialize a different
    /// type into another currently.
    pub fn recv_from(&self) -> Result<(T, SocketAddr), TransitError> where T: Deserialize {
        let mut buf = [0; 65535]; // Max size of UDP packet
        let (n, addr) = try!(self.socket.recv_from(&mut buf));
        let data = try!(deserialize(&buf[..n]));
        Ok((data, addr))
    }

    /// Transforms the packet into a byte array and sends it to the associated address.
    pub fn send_to<A>(&self, pkt: &T, addr: A) -> Result<(), TransitError> where T: Serialize, A: ToSocketAddrs {
        let sizelimit = bincode::SizeLimit::Bounded(65535);
        let vec = try!(serialize(pkt, sizelimit));
        try!(self.socket.send_to(&vec[..], addr));
        Ok(())
    }

    pub fn local_addr(&self)  -> Result<SocketAddr, TransitError> {
        let addr = try!(self.socket.local_addr());
        Ok(addr)
    }
}

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

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Test {
        ten: u8,
    }

    #[derive(Serialize, Deserialize, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
    struct Another {
        data: String,
    }

    #[test]
    fn test_send_recv() {
        let addr1 = "127.0.0.1:61001";
        let addr2 = "127.0.0.1:61002";
        let transit1: Transit<Test> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = Test { ten: 10 };

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_string() {
        let addr1 = "127.0.0.1:63001";
        let addr2 = "127.0.0.1:63002";
        let transit1: Transit<String> = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let test = String::from("hello");

        let res = transit2.send_to(&test, addr1);
        assert!(res.is_ok());
        let res = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, test);
    }

    #[test]
    fn test_send_recv_bytes() {
        let addr1 = "127.0.0.1:64001";
        let addr2 = "127.0.0.1:64002";
        let transit1 = Transit::new(addr1).unwrap();
        let transit2 = Transit::new(addr2).unwrap();
        let vec = vec!(9u8);
        let slice = &vec[..];

        let res = transit2.send_to(&slice, addr1);
        assert!(res.is_ok());
        let res: Result<(Vec<u8>, _), TransitError> = transit1.recv_from();
        assert!(res.is_ok());
        let (data, _addr) = res.unwrap();
        assert_eq!(data, vec);
    }

    // TODO: How to ensure different types are not deserialized as each other with bincode?
    // #[test]
    // fn test_packet_type() {
    //     let addr1 = "127.0.0.1:62001";
    //     let addr2 = "127.0.0.1:62002";
    //     let transit1: Transit<Another> = Transit::new(addr1).unwrap();
    //     let transit2: Transit<Test> = Transit::new(addr2).unwrap();
    //     let test = Another { data: String::from("Hello") };

    //     let res = transit1.send_to(&test, addr2);
    //     assert!(res.is_ok());
    //     let res = transit2.recv_from();
    //     assert!(res.is_err());
    // }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! This module provides a generic set of traits for dealing with cryptographic primitives.
//!
//! For examples on how to use these traits, see the implementations of the [`ed25519`] or
//! [`bls12381`] modules.

use core::convert::{From, TryFrom};
use crypto::hash::HashValue;
use failure::prelude::*;
use std::{fmt::Debug, hash::Hash};

/// An error type for key and signature validation issues, see [`ValidKey`][ValidKey].
///
/// This enum reflects there are two interesting causes of validation
/// failure for the ingestion of key or signature material: deserialization errors
/// (often, due to mangled material or curve equation failure for ECC) and
/// validation errors (material recognizable but unacceptable for use,
/// e.g. unsafe).
#[derive(Clone, Debug, PartialEq, Eq, failure::prelude::Fail)]
pub enum CryptoMaterialError {
    /// Key or signature material does not deserialize correctly.
    #[fail(display = "DeserializationError")]
    DeserializationError,
    /// Key or signature material deserializes, but is otherwise not valid.
    #[fail(display = "ValidationError")]
    ValidationError,
    /// Key or signature material does not have the expected size.
    #[fail(display = "WrongLengthError")]
    WrongLengthError,
    /// Part of the signature or key is not canonical resulting to malleability issues.
    #[fail(display = "CanonicalRepresentationError")]
    CanonicalRepresentationError,
    /// A curve point (i.e., a public key) lies on a small group.
    #[fail(display = "SmallSubgroupError")]
    SmallSubgroupError,
    /// A curve point (i.e., a public key) does not satisfy the curve equation.
    #[fail(display = "PointNotOnCurveError")]
    PointNotOnCurveError,
}

/// Key material with a notion of byte validation.
///
/// A type family for material that knows how to serialize and
/// deserialize, as well as validate byte-encoded material. The
/// validation must be implemented as a [`TryFrom`][TryFrom] which
/// classifies its failures against the above
/// [`CryptoMaterialError`][CryptoMaterialError].
///
/// This provides an implementation for a validation that relies on a
/// round-trip to bytes and corresponding [`TryFrom`][TryFrom].
pub trait ValidKey:
    // The for<'a> exactly matches the assumption "deserializable from any lifetime".
    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError> + Debug
{
    /// TryFrom is the source of truth on whether we can build a valid key.
    /// => we can use it once we've built, to validate!
    fn validate(&self) -> std::result::Result<(), CryptoMaterialError> {
        Self::try_from(self.to_bytes().as_slice())?;
        Ok(())
    }

    /// Convert the valid key to bytes.
    fn to_bytes(&self) -> Vec<u8>;
}

/// An extension to to/from Strings for [`ValidKey`][ValidKey].
///
/// Relies on [`hex`][::hex] for string encoding / decoding.
/// No required fields, provides a default implementation.
pub trait ValidKeyStringExt: ValidKey {
    /// When trying to convert from bytes, we simply decode the string into
    /// bytes before checking if we can convert.
    fn from_encoded_string(encoded_str: &str) -> std::result::Result<Self, CryptoMaterialError> {
        let bytes_out = ::hex::decode(encoded_str);
        // We defer to `try_from` to make sure we only produce valid keys.
        bytes_out
            // We reinterpret a failure to serialize: key is mangled someway.
            .or(Err(CryptoMaterialError::DeserializationError))
            .and_then(|ref bytes| Self::try_from(bytes))
    }
    /// A function to encode into hex-string after serializing.
    fn to_encoded_string(&self) -> Result<String> {
        Ok(::hex::encode(&self.to_bytes()))
    }
}

// There's nothing required in this extension, so let's just derive it
// for anybody that has a ValidKey.
impl<T: ValidKey> ValidKeyStringExt for T {}

/// A type family for key material that should remain secret and has an
/// associated type of the [`PublicKey`][PublicKey] family.
pub trait PrivateKey: ValidKey {
    /// We require public / private types to be coupled, i.e. their
    /// associated type is each other.
    type PublicKeyMaterial: PublicKey<PrivateKeyMaterial = Self>;

    /// Returns the associated public key
    fn public_key(&self) -> Self::PublicKeyMaterial {
        self.into()
    }
}

/// A type family of valid keys that know how to sign.
///
/// A trait for a [`ValidKey`][ValidKey] which knows how to sign a
/// message, and return an associated `Signature` type.
pub trait SigningKey:
    PrivateKey<PublicKeyMaterial = <Self as SigningKey>::VerifyingKeyMaterial>
{
    /// The associated verifying key type for this signing key.
    type VerifyingKeyMaterial: VerifyingKey<SigningKeyMaterial = Self>;
    /// The associated signature type for this signing key.
    type SignatureMaterial: Signature<SigningKeyMaterial = Self>;

    /// Signs an input message.
    fn sign_message(&self, message: &HashValue) -> Self::SignatureMaterial;

    /// Returns the associated verifying key
    fn verifying_key(&self) -> Self::VerifyingKeyMaterial {
        self.public_key()
    }
}

/// A type for key material that can be publicly shared, and in asymmetric
/// fashion, can be obtained from a [`PrivateKey`][PrivateKey]
/// reference.
/// This convertibility requirement ensures the existence of a
/// deterministic, canonical public key construction from a private key.
pub trait PublicKey: ValidKey + Clone + Eq + Hash +
    // This unsightly turbofish type parameter is the precise constraint
    // needed to require that there exists an
    //
    // ```
    // impl From<&MyPrivateKeyMaterial> for MyPublicKeyMaterial
    // ```
    //
    // declaration, for any `MyPrivateKeyMaterial`, `MyPublicKeyMaterial`
    // on which we register (respectively) `PublicKey` and `PrivateKey`
    // implementations.
    for<'a> From<&'a <Self as PublicKey>::PrivateKeyMaterial> {
    /// We require public / private types to be coupled, i.e. their
    /// associated type is each other.
    type PrivateKeyMaterial: PrivateKey<PublicKeyMaterial = Self>;
    /// The length of the [`PublicKey`]
    fn length() -> usize;

}

/// A type family of public keys that are used for signing.
///
/// It is linked to a type of the Signature family, which carries the
/// verification implementation.
pub trait VerifyingKey:
    PublicKey<PrivateKeyMaterial = <Self as VerifyingKey>::SigningKeyMaterial>
{
    /// The associated signing key type for this verifying key.
    type SigningKeyMaterial: SigningKey<VerifyingKeyMaterial = Self>;
    /// The associated signature type for this verifying key.
    type SignatureMaterial: Signature<VerifyingKeyMaterial = Self>;

    /// We provide the logical implementation which dispatches to the signature.
    fn verify_signature(
        &self,
        message: &HashValue,
        signature: &Self::SignatureMaterial,
    ) -> Result<()> {
        signature.verify(message, self)
    }

    /// We provide the implementation which dispatches to the signature.
    fn batch_verify_signatures(
        message: &HashValue,
        keys_and_signatures: Vec<(Self, Self::SignatureMaterial)>,
    ) -> Result<()> {
        Self::SignatureMaterial::batch_verify_signatures(message, keys_and_signatures)
    }
}

/// A type family for signature material that knows which public key type
/// is needed to verify it, and given such a public key, knows how to
/// verify.
///
/// This trait simply requires an association to some type of the
/// [`PublicKey`][PublicKey] family of which we are the `SignatureMaterial`.
///
/// It should be possible to write a generic signature function that
/// checks signature material passed as `&[u8]` and only returns Ok when
/// that material de-serializes to a signature of the expected concrete
/// scheme. This would be done as an extension trait of
/// [`Signature`][Signature].
pub trait Signature:
    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError> + Sized + Debug + Clone + Eq + Hash
{
    /// The associated verifying key type for this signature.
    type VerifyingKeyMaterial: VerifyingKey<SignatureMaterial = Self>;
    /// The associated signing key type for this signature
    type SigningKeyMaterial: SigningKey<SignatureMaterial = Self>;

    /// The verification function.
    fn verify(&self, message: &HashValue, public_key: &Self::VerifyingKeyMaterial) -> Result<()>;

    /// Native verification function.
    fn verify_arbitrary_msg(
        &self,
        message: &[u8],
        public_key: &Self::VerifyingKeyMaterial,
    ) -> Result<()>;

    /// Convert the signature into a byte representation.
    fn to_bytes(&self) -> Vec<u8>;

    /// The implementer can override a batch verification implementation
    /// that by default iterates over each signature. More efficient
    /// implementations exist and should be implemented for many schemes.
    fn batch_verify_signatures(
        message: &HashValue,
        keys_and_signatures: Vec<(Self::VerifyingKeyMaterial, Self)>,
    ) -> Result<()> {
        for (key, signature) in keys_and_signatures {
            signature.verify(message, &key)?
        }
        Ok(())
    }
}

/// A type family for schemes which know how to generate key material from
/// a cryptographically-secure [`CryptoRng`][::rand::CryptoRng].
pub trait Uniform {
    /// Generate key material from an RNG for testing purposes.
    fn generate_for_testing<R>(rng: &mut R) -> Self
    where
        R: ::rand::SeedableRng + ::rand::RngCore + ::rand::CryptoRng;
}

/// A type family with a by-convention notion of genesis private key.
pub trait Genesis: PrivateKey {
    /// Produces the genesis private key.
    fn genesis() -> Self;
}
<commit_msg>Make PublicKey + PrivateKey a mixin<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! This module provides a generic set of traits for dealing with cryptographic primitives.
//!
//! For examples on how to use these traits, see the implementations of the [`ed25519`] or
//! [`bls12381`] modules.

use core::convert::{From, TryFrom};
use crypto::hash::HashValue;
use failure::prelude::*;
use std::{fmt::Debug, hash::Hash};

/// An error type for key and signature validation issues, see [`ValidKey`][ValidKey].
///
/// This enum reflects there are two interesting causes of validation
/// failure for the ingestion of key or signature material: deserialization errors
/// (often, due to mangled material or curve equation failure for ECC) and
/// validation errors (material recognizable but unacceptable for use,
/// e.g. unsafe).
#[derive(Clone, Debug, PartialEq, Eq, failure::prelude::Fail)]
pub enum CryptoMaterialError {
    /// Key or signature material does not deserialize correctly.
    #[fail(display = "DeserializationError")]
    DeserializationError,
    /// Key or signature material deserializes, but is otherwise not valid.
    #[fail(display = "ValidationError")]
    ValidationError,
    /// Key or signature material does not have the expected size.
    #[fail(display = "WrongLengthError")]
    WrongLengthError,
    /// Part of the signature or key is not canonical resulting to malleability issues.
    #[fail(display = "CanonicalRepresentationError")]
    CanonicalRepresentationError,
    /// A curve point (i.e., a public key) lies on a small group.
    #[fail(display = "SmallSubgroupError")]
    SmallSubgroupError,
    /// A curve point (i.e., a public key) does not satisfy the curve equation.
    #[fail(display = "PointNotOnCurveError")]
    PointNotOnCurveError,
}

/// Key material with a notion of byte validation.
///
/// A type family for material that knows how to serialize and
/// deserialize, as well as validate byte-encoded material. The
/// validation must be implemented as a [`TryFrom`][TryFrom] which
/// classifies its failures against the above
/// [`CryptoMaterialError`][CryptoMaterialError].
///
/// This provides an implementation for a validation that relies on a
/// round-trip to bytes and corresponding [`TryFrom`][TryFrom].
pub trait ValidKey:
    // The for<'a> exactly matches the assumption "deserializable from any lifetime".
    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError> + Debug
{
    /// TryFrom is the source of truth on whether we can build a valid key.
    /// => we can use it once we've built, to validate!
    fn validate(&self) -> std::result::Result<(), CryptoMaterialError> {
        Self::try_from(self.to_bytes().as_slice())?;
        Ok(())
    }

    /// Convert the valid key to bytes.
    fn to_bytes(&self) -> Vec<u8>;
}

/// An extension to to/from Strings for [`ValidKey`][ValidKey].
///
/// Relies on [`hex`][::hex] for string encoding / decoding.
/// No required fields, provides a default implementation.
pub trait ValidKeyStringExt: ValidKey {
    /// When trying to convert from bytes, we simply decode the string into
    /// bytes before checking if we can convert.
    fn from_encoded_string(encoded_str: &str) -> std::result::Result<Self, CryptoMaterialError> {
        let bytes_out = ::hex::decode(encoded_str);
        // We defer to `try_from` to make sure we only produce valid keys.
        bytes_out
            // We reinterpret a failure to serialize: key is mangled someway.
            .or(Err(CryptoMaterialError::DeserializationError))
            .and_then(|ref bytes| Self::try_from(bytes))
    }
    /// A function to encode into hex-string after serializing.
    fn to_encoded_string(&self) -> Result<String> {
        Ok(::hex::encode(&self.to_bytes()))
    }
}

// There's nothing required in this extension, so let's just derive it
// for anybody that has a ValidKey.
impl<T: ValidKey> ValidKeyStringExt for T {}

/// A type family for key material that should remain secret and has an
/// associated type of the [`PublicKey`][PublicKey] family.
pub trait PrivateKey: Sized {
    /// We require public / private types to be coupled, i.e. their
    /// associated type is each other.
    type PublicKeyMaterial: PublicKey<PrivateKeyMaterial = Self>;

    /// Returns the associated public key
    fn public_key(&self) -> Self::PublicKeyMaterial {
        self.into()
    }
}

/// A type family of valid keys that know how to sign.
///
/// A trait for a [`ValidKey`][ValidKey] which knows how to sign a
/// message, and return an associated `Signature` type.
pub trait SigningKey:
    PrivateKey<PublicKeyMaterial = <Self as SigningKey>::VerifyingKeyMaterial> + ValidKey
{
    /// The associated verifying key type for this signing key.
    type VerifyingKeyMaterial: VerifyingKey<SigningKeyMaterial = Self>;
    /// The associated signature type for this signing key.
    type SignatureMaterial: Signature<SigningKeyMaterial = Self>;

    /// Signs an input message.
    fn sign_message(&self, message: &HashValue) -> Self::SignatureMaterial;

    /// Returns the associated verifying key
    fn verifying_key(&self) -> Self::VerifyingKeyMaterial {
        self.public_key()
    }
}

/// A type for key material that can be publicly shared, and in asymmetric
/// fashion, can be obtained from a [`PrivateKey`][PrivateKey]
/// reference.
/// This convertibility requirement ensures the existence of a
/// deterministic, canonical public key construction from a private key.
pub trait PublicKey: Sized + Clone + Eq + Hash +
    // This unsightly turbofish type parameter is the precise constraint
    // needed to require that there exists an
    //
    // ```
    // impl From<&MyPrivateKeyMaterial> for MyPublicKeyMaterial
    // ```
    //
    // declaration, for any `MyPrivateKeyMaterial`, `MyPublicKeyMaterial`
    // on which we register (respectively) `PublicKey` and `PrivateKey`
    // implementations.
    for<'a> From<&'a <Self as PublicKey>::PrivateKeyMaterial> {
    /// We require public / private types to be coupled, i.e. their
    /// associated type is each other.
    type PrivateKeyMaterial: PrivateKey<PublicKeyMaterial = Self>;
    /// The length of the [`PublicKey`]
    fn length() -> usize;

}

/// A type family of public keys that are used for signing.
///
/// It is linked to a type of the Signature family, which carries the
/// verification implementation.
pub trait VerifyingKey:
    PublicKey<PrivateKeyMaterial = <Self as VerifyingKey>::SigningKeyMaterial> + ValidKey
{
    /// The associated signing key type for this verifying key.
    type SigningKeyMaterial: SigningKey<VerifyingKeyMaterial = Self>;
    /// The associated signature type for this verifying key.
    type SignatureMaterial: Signature<VerifyingKeyMaterial = Self>;

    /// We provide the logical implementation which dispatches to the signature.
    fn verify_signature(
        &self,
        message: &HashValue,
        signature: &Self::SignatureMaterial,
    ) -> Result<()> {
        signature.verify(message, self)
    }

    /// We provide the implementation which dispatches to the signature.
    fn batch_verify_signatures(
        message: &HashValue,
        keys_and_signatures: Vec<(Self, Self::SignatureMaterial)>,
    ) -> Result<()> {
        Self::SignatureMaterial::batch_verify_signatures(message, keys_and_signatures)
    }
}

/// A type family for signature material that knows which public key type
/// is needed to verify it, and given such a public key, knows how to
/// verify.
///
/// This trait simply requires an association to some type of the
/// [`PublicKey`][PublicKey] family of which we are the `SignatureMaterial`.
///
/// It should be possible to write a generic signature function that
/// checks signature material passed as `&[u8]` and only returns Ok when
/// that material de-serializes to a signature of the expected concrete
/// scheme. This would be done as an extension trait of
/// [`Signature`][Signature].
pub trait Signature:
    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError> + Sized + Debug + Clone + Eq + Hash
{
    /// The associated verifying key type for this signature.
    type VerifyingKeyMaterial: VerifyingKey<SignatureMaterial = Self>;
    /// The associated signing key type for this signature
    type SigningKeyMaterial: SigningKey<SignatureMaterial = Self>;

    /// The verification function.
    fn verify(&self, message: &HashValue, public_key: &Self::VerifyingKeyMaterial) -> Result<()>;

    /// Native verification function.
    fn verify_arbitrary_msg(
        &self,
        message: &[u8],
        public_key: &Self::VerifyingKeyMaterial,
    ) -> Result<()>;

    /// Convert the signature into a byte representation.
    fn to_bytes(&self) -> Vec<u8>;

    /// The implementer can override a batch verification implementation
    /// that by default iterates over each signature. More efficient
    /// implementations exist and should be implemented for many schemes.
    fn batch_verify_signatures(
        message: &HashValue,
        keys_and_signatures: Vec<(Self::VerifyingKeyMaterial, Self)>,
    ) -> Result<()> {
        for (key, signature) in keys_and_signatures {
            signature.verify(message, &key)?
        }
        Ok(())
    }
}

/// A type family for schemes which know how to generate key material from
/// a cryptographically-secure [`CryptoRng`][::rand::CryptoRng].
pub trait Uniform {
    /// Generate key material from an RNG for testing purposes.
    fn generate_for_testing<R>(rng: &mut R) -> Self
    where
        R: ::rand::SeedableRng + ::rand::RngCore + ::rand::CryptoRng;
}

/// A type family with a by-convention notion of genesis private key.
pub trait Genesis: PrivateKey {
    /// Produces the genesis private key.
    fn genesis() -> Self;
}
<|endoftext|>


<commit_before>use super::{Group, Key, Symbols};
use crate::pad::PadAdapter;
use std::io::{Result, Write};

pub trait ToXkb {
    fn write_xkb(&self, w: impl Write) -> Result<()>;
}

impl ToXkb for Symbols {
    fn write_xkb(&self, mut w: impl Write) -> Result<()> {
        writeln!(w, r#"default partial alphanumeric_keys"#)?;
        writeln!(w, r#"xkb_symbols "basic" {{"#)?;

        let mut inner = PadAdapter::wrap(&mut w);
        writeln!(&mut inner, r#"include "latin""#)?;
        writeln!(&mut inner)?;

        for group in &self.groups {
            group.write_xkb(&mut inner)?;
        }

        writeln!(w, r#"}}"#)?;
        writeln!(w)?;

        Ok(())
    }
}

impl ToXkb for Group {
    fn write_xkb(&self, mut w: impl Write) -> Result<()> {
        writeln!(w, r#"name[Group1] = "{}";"#, self.name)?;
        writeln!(w)?;

        let mut inner = PadAdapter::wrap(&mut w);
        for include in &self.leading_includes {
            writeln!(&mut inner, r#"include "{}""#, include)?;
        }
        if !self.leading_includes.is_empty() {
            writeln!(w)?;
        }

        let mut inner = PadAdapter::wrap(&mut w);
        for key in &self.keys {
            key.write_xkb(&mut inner)?;
        }

        let mut inner = PadAdapter::wrap(&mut w);
        for include in &self.trailing_includes {
            writeln!(&mut inner, r#"include "{}""#, include)?;
        }

        Ok(())
    }
}

impl ToXkb for Key {
    fn write_xkb(&self, mut w: impl Write) -> Result<()> {
        write!(w, "key <A{}> {{ [ ", self.iso_code)?;

        /// Since modifiers are ordered, we need to make sure we don't continue
        /// emitting them when the previous one was empty.
        fn collect_keys(key: &Key, mut w: impl Write) -> Result<()> {
            if let Some(k) = &key.default {
                write!(w, "{}", k)?;
            } else {
                return Ok(());
            }
            if let Some(k) = &key.shift {
                write!(w, ", {}", k)?;
            } else {
                return Ok(());
            }
            if let Some(k) = &key.alt {
                write!(w, ", {}", k)?;
            } else {
                return Ok(());
            }
            if let Some(k) = &key.alt_shift {
                write!(w, ", {}", k)?;
            } else {
                return Ok(());
            }
            Ok(())
        }

        collect_keys(self, &mut w)?;

        write!(w, " ] }};")?;
        writeln!(w)?;

        Ok(())
    }
}
<commit_msg>Fix typo<commit_after>use super::{Group, Key, Symbols};
use crate::pad::PadAdapter;
use std::io::{Result, Write};

pub trait ToXkb {
    fn write_xkb(&self, w: impl Write) -> Result<()>;
}

impl ToXkb for Symbols {
    fn write_xkb(&self, mut w: impl Write) -> Result<()> {
        writeln!(w, r#"default partial alphanumeric_keys"#)?;
        writeln!(w, r#"xkb_symbols "basic" {{"#)?;

        let mut inner = PadAdapter::wrap(&mut w);
        writeln!(&mut inner, r#"include "latin""#)?;
        writeln!(&mut inner)?;

        for group in &self.groups {
            group.write_xkb(&mut inner)?;
        }

        writeln!(w, r#"}};"#)?;
        writeln!(w)?;

        Ok(())
    }
}

impl ToXkb for Group {
    fn write_xkb(&self, mut w: impl Write) -> Result<()> {
        writeln!(w, r#"name[Group1] = "{}";"#, self.name)?;
        writeln!(w)?;

        let mut inner = PadAdapter::wrap(&mut w);
        for include in &self.leading_includes {
            writeln!(&mut inner, r#"include "{}""#, include)?;
        }
        if !self.leading_includes.is_empty() {
            writeln!(w)?;
        }

        let mut inner = PadAdapter::wrap(&mut w);
        for key in &self.keys {
            key.write_xkb(&mut inner)?;
        }

        let mut inner = PadAdapter::wrap(&mut w);
        for include in &self.trailing_includes {
            writeln!(&mut inner, r#"include "{}""#, include)?;
        }

        Ok(())
    }
}

impl ToXkb for Key {
    fn write_xkb(&self, mut w: impl Write) -> Result<()> {
        write!(w, "key <A{}> {{ [ ", self.iso_code)?;

        /// Since modifiers are ordered, we need to make sure we don't continue
        /// emitting them when the previous one was empty.
        fn collect_keys(key: &Key, mut w: impl Write) -> Result<()> {
            if let Some(k) = &key.default {
                write!(w, "{}", k)?;
            } else {
                return Ok(());
            }
            if let Some(k) = &key.shift {
                write!(w, ", {}", k)?;
            } else {
                return Ok(());
            }
            if let Some(k) = &key.alt {
                write!(w, ", {}", k)?;
            } else {
                return Ok(());
            }
            if let Some(k) = &key.alt_shift {
                write!(w, ", {}", k)?;
            } else {
                return Ok(());
            }
            Ok(())
        }

        collect_keys(self, &mut w)?;

        write!(w, " ] }};")?;
        writeln!(w)?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::env;
use hyper::Client;
use hyper::header::Connection;
use std::collections::BTreeMap;
use rustc_serialize::json;
use std::fs::File;

static BASE_URL:    &'static str = "https://www.googleapis.com/youtube/v3";
lazy_static! {
    static ref API_KEY: String = {
        let opt_key = env::var("YOUTUBE_API_KEY");
        match opt_key {
            Ok(key) => key,
            Err(_) => {
                let mut f = File::open("youtube.txt").unwrap();
                let mut s = String::new();
                let _ = f.read_to_string(&mut s);
                s
            }
        }
    };
}

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct Thumbnail {
    pub url:    String,
    pub width:  i32,
    pub height: i32
}

impl PartialEq for Thumbnail {
    fn eq(&self, t: &Thumbnail) -> bool {
        return self.url == t.url;
    }
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct PlaylistItemResponse {
    pub kind:          String,
    pub etag:          String,
    pub nextPageToken: String,
    pub pageInfo:      BTreeMap<String, i32>,
    pub items:         Vec<PlaylistItem>,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct PlaylistItem {
    pub kind:    String,
    pub etag:    String,
    pub id:      String,
    pub snippet: PlaylistItemSnippet,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct PlaylistItemSnippet {
    pub title:         String,
    pub description:   String,
    pub publishedAt:   String,
    pub channelId:     String,
    pub channelTitle:  String,
    pub thumbnails:    BTreeMap<String, Thumbnail>,
    pub position:      i32,
    pub playlistId:    String,
    pub resourceId:    BTreeMap<String, String>
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct VideoResponse {
    pub kind:          String,
    pub etag:          String,
    pub pageInfo:      BTreeMap<String, i32>,
    pub items:         Vec<Video>,
}

#[allow(non_snake_case)]
#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct Video {
    pub kind:    String,
    pub etag:    String,
    pub id:      String,
    pub snippet: VideoSnippet,
}

#[allow(non_snake_case)]
#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct VideoSnippet {
    pub title:                String,
    pub description:          String,
    pub publishedAt:          String,
    pub channelId:            String,
    pub channelTitle:         String,
    pub thumbnails:           BTreeMap<String, Thumbnail>,
    pub tags:                 Vec<String>,
    pub categoryId:           String,
    pub liveBroadcastContent: String,
}

pub fn fetch_playlist(id: &str) -> json::DecodeResult<PlaylistItemResponse> {
    let params = format!("key={}&part=snippet&playlistId={}", *API_KEY, id);
    let url    = format!("{}/{}?{}", BASE_URL, "playlistItems", params);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    json::decode::<PlaylistItemResponse>(&body)
}

pub fn fetch_video(id: &str) -> json::DecodeResult<Video> {
    let params = format!("key={}&part=snippet&id={}", *API_KEY, id);
    let url    = format!("{}/{}?{}", BASE_URL, "videos", params);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    let res = try!(json::decode::<VideoResponse>(&body));
    if res.items.len() > 0 {
        return Ok(res.items[0].clone());
    }
    Err(json::DecoderError::ApplicationError("track not found".to_string()))
}
<commit_msg>video tags properties in YouTube api are optional<commit_after>use std::io::Read;
use std::env;
use hyper::Client;
use hyper::header::Connection;
use std::collections::BTreeMap;
use rustc_serialize::json;
use std::fs::File;

static BASE_URL:    &'static str = "https://www.googleapis.com/youtube/v3";
lazy_static! {
    static ref API_KEY: String = {
        let opt_key = env::var("YOUTUBE_API_KEY");
        match opt_key {
            Ok(key) => key,
            Err(_) => {
                let mut f = File::open("youtube.txt").unwrap();
                let mut s = String::new();
                let _ = f.read_to_string(&mut s);
                s
            }
        }
    };
}

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct Thumbnail {
    pub url:    String,
    pub width:  i32,
    pub height: i32
}

impl PartialEq for Thumbnail {
    fn eq(&self, t: &Thumbnail) -> bool {
        return self.url == t.url;
    }
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct PlaylistItemResponse {
    pub kind:          String,
    pub etag:          String,
    pub nextPageToken: String,
    pub pageInfo:      BTreeMap<String, i32>,
    pub items:         Vec<PlaylistItem>,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct PlaylistItem {
    pub kind:    String,
    pub etag:    String,
    pub id:      String,
    pub snippet: PlaylistItemSnippet,
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct PlaylistItemSnippet {
    pub title:         String,
    pub description:   String,
    pub publishedAt:   String,
    pub channelId:     String,
    pub channelTitle:  String,
    pub thumbnails:    BTreeMap<String, Thumbnail>,
    pub position:      i32,
    pub playlistId:    String,
    pub resourceId:    BTreeMap<String, String>
}

#[allow(non_snake_case)]
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct VideoResponse {
    pub kind:          String,
    pub etag:          String,
    pub pageInfo:      BTreeMap<String, i32>,
    pub items:         Vec<Video>,
}

#[allow(non_snake_case)]
#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct Video {
    pub kind:    String,
    pub etag:    String,
    pub id:      String,
    pub snippet: VideoSnippet,
}

#[allow(non_snake_case)]
#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct VideoSnippet {
    pub title:                String,
    pub description:          String,
    pub publishedAt:          String,
    pub channelId:            String,
    pub channelTitle:         String,
    pub thumbnails:           BTreeMap<String, Thumbnail>,
    pub tags:                 Option<Vec<String>>,
    pub categoryId:           String,
    pub liveBroadcastContent: String,
}

pub fn fetch_playlist(id: &str) -> json::DecodeResult<PlaylistItemResponse> {
    let params = format!("key={}&part=snippet&playlistId={}", *API_KEY, id);
    let url    = format!("{}/{}?{}", BASE_URL, "playlistItems", params);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    json::decode::<PlaylistItemResponse>(&body)
}

pub fn fetch_video(id: &str) -> json::DecodeResult<Video> {
    let params = format!("key={}&part=snippet&id={}", *API_KEY, id);
    let url    = format!("{}/{}?{}", BASE_URL, "videos", params);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    let res = try!(json::decode::<VideoResponse>(&body));
    if res.items.len() > 0 {
        return Ok(res.items[0].clone());
    }
    Err(json::DecoderError::ApplicationError("track not found".to_string()))
}
<|endoftext|>


<commit_before>extern crate serde_derive;

use std::collections::{BTreeMap, HashSet};
use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::{BufRead, BufReader, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};

use chrono::offset::TimeZone;
use chrono::{DateTime, Utc};
use clap::{App, Arg, ArgMatches, SubCommand};
use glob::glob;
use serde_derive::{Deserialize, Serialize};

#[derive(Deserialize, Debug, Clone)]
struct RepoConfig {
    path: String,
    #[serde(default = "default_false")]
    commit: bool,
    #[serde(default = "default_false")]
    sync_updates: bool,
}

fn default_false() -> bool {
    false
}

#[derive(Deserialize, Debug)]
struct Supfile {
    repo: RepoConfig,
    editor: Option<String>,
}

impl Supfile {
    pub fn from(str: &str) -> Result<Self, toml::de::Error> {
        toml::from_str(&str)
    }

    pub fn find() -> PathBuf {
        // TODO: pull in XDG crate for paths
        let default_dir = "~/.config/sup/";

        ["./", default_dir]
            .iter()
            .map(|dir| Path::new(dir).join("Supfile"))
            .find(|p| p.exists())
            .unwrap_or_else(|| {
                // TODO: offer to create path somehow
                panic!("can't find supfile")
            })
    }
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
enum TaskState {
    Todo,
    InProgress,
    Complete,
    Canceled,
    Deferred,
}

impl TaskState {
    fn is_open(self) -> bool {
        match self {
            TaskState::Todo | TaskState::InProgress | TaskState::Deferred => true,
            _ => false,
        }
    }
}

impl std::fmt::Display for TaskState {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let value = match self {
            TaskState::Todo => " ",
            TaskState::InProgress => "•",
            TaskState::Complete => "✔",
            TaskState::Canceled => "-",
            TaskState::Deferred => "⟫",
        };
        write!(f, "{}", value)
    }
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
enum Action {
    Create {
        task: String,
        #[serde(default)]
        notes: Option<String>,
        #[serde(default)]
        tags: Vec<String>,
    },
    EditTags {
        add: Vec<String>,
        remove: Vec<String>,
    },
    EditTask(String),
    EditNotes(Option<String>),
    EditState(TaskState),
}

#[derive(Deserialize, Serialize)]
struct TaskUpdate {
    id: String,
    timestamp: DateTime<Utc>,
    action: Action,
}

impl TaskUpdate {
    fn from_str(line: &str) -> serde_json::Result<Self> {
        serde_json::from_str(line).map_err(|e| {
            println!("nuts: {:?}", e);
            e
        })
    }

    /// Create a basic TaskUpdate. The `id` is left unset and must be set before being written.
    fn new_todo(
        id: String,
        task: String,
        notes: Option<String>,
        tags: Vec<String>,
    ) -> Self {
        Self {
            id: id,
            timestamp: Utc::now(),
            action: Action::Create { task, notes, tags },
        }
    }
}

#[derive(Clone, Debug)]
struct Task {
    id: String,
    created_at: DateTime<Utc>,
    completed_at: Option<DateTime<Utc>>,
    state: TaskState,
    task: String,
    notes: Option<String>,
    tags: HashSet<String>,
}

impl Task {
    fn apply(&mut self, update: &TaskUpdate) {
        match &update.action {
            Action::Create { task, notes, tags } => {
                self.task = task.clone();
                self.notes = notes.clone();
                for tag in tags.iter() {
                    self.tags.insert(tag.clone());
                }
            }
            Action::EditTags { add, remove } => {
                for tag in remove.iter() {
                    self.tags.remove(tag);
                }

                for tag in add.iter() {
                    self.tags.insert(tag.clone());
                }
            }
            Action::EditTask(task) => self.task = task.clone(),
            Action::EditNotes(notes) => self.notes = notes.clone(),
            Action::EditState(state) => {
                self.state = state.clone();
                if state == &TaskState::Complete {
                    self.completed_at = Some(update.timestamp);
                }
            }
        }
    }

    fn summary(&self) -> String {
        format!("{} [{}] {}", self.id, self.state, self.task)
    }
}

impl From<&TaskUpdate> for Task {
    fn from(update: &TaskUpdate) -> Self {
        let mut task = Task {
            id: update.id.clone(),
            created_at: update.timestamp.clone(),
            completed_at: None,
            state: TaskState::Todo,
            task: "untitled".to_string(),
            notes: None,
            tags: HashSet::new(),
        };

        task.apply(update);
        return task;
    }
}

#[derive(Debug)]
struct SupdateLog {
    name: String,
    path: String,

    timestamp: DateTime<Utc>,
}

impl SupdateLog {
    fn new(path: &Path) -> Self {
        let name: String = path
            .file_name()
            .expect("need file, not directory")
            .to_string_lossy()
            .into();

        let timestamp = Utc
            .datetime_from_str(&name, "%Y%m%d_%H%M%S.sup")
            .unwrap_or_else(|_| {
                println!("{:?} appears to be improperly named!", path);
                Utc.timestamp(0, 0)
            });

        // TODO: Support versioning in line
        SupdateLog {
            name,
            path: path.to_string_lossy().into(),
            timestamp,
        }
    }

    fn write_update(&self, task: &TaskUpdate) -> std::io::Result<()> {
        let mut file = self.open_file()?;
        file.seek(SeekFrom::End(0)).expect("could not seek to end");

        serde_json::ser::to_writer(&file, task)?;
        file.write_all(b"\n")?;

        Ok(())
    }

    fn iter(&self) -> SupdateIterator {
        let mut file = self.open_file().expect("could not open file");
        file.seek(SeekFrom::Start(0)).expect("could not rewind");

        SupdateIterator {
            reader: BufReader::new(file),
        }
    }

    /// Open the log file or create it if it doesn't exist.
    fn open_file(&self) -> std::io::Result<File> {
        OpenOptions::new()
            .read(true)
            .append(true)
            .create(true)
            .open(&self.path)
    }
}

struct SupdateIterator {
    reader: BufReader<File>,
}

impl Iterator for SupdateIterator {
    type Item = TaskUpdate;

    fn next(&mut self) -> Option<TaskUpdate> {
        let mut line = String::new();
        return match self.reader.read_line(&mut line) {
            // End of file
            Ok(0) => None,

            Ok(_) => {
                //println!("line = {:?}", line);
                // TODO: alert when we don't succeed at parsing
                TaskUpdate::from_str(&line).ok()
            }

            Err(e) => {
                println!("Failed to read line: {:?}", e);
                None
            }
        };
    }
}

/**
 * A Repository represents a directory containing SupdateLogs.
 *
 * The directory structure is something like this:
 *
 * repo/
 *   2019/
 *     08/
 *       20190801_235959.sup
 *       20190802_003030.sup
 *       20190802_123030.sup
 *
 * TODO: Support concept of `rollup` files to put an upper limit on
 * how far we need to look back to fully reconstruct the state of
 * everything.
 */

struct Repository {
    config: RepoConfig,
}

impl Repository {
    fn new(cfg: RepoConfig) -> Self {
        // TODO: Handle error, return Result
        if !Path::new(&cfg.path).exists() {
            panic!("given repository does not exist")
        }

        Repository { config: cfg }
    }

    fn open_journal(&self) -> Journal {
        let updates = self.list_update_logs();
        self.build_journal(updates)
    }

    fn build_journal(&self, updates: Vec<SupdateLog>) -> Journal {
        let mut journal = Journal::new();

        // Reverse ordering so that we consume oldest elements first.
        for log in updates.into_iter().rev() {
            println!("reading: {:?}", log);

            for ref update in log.iter() {
                journal.add(update);
            }
        }

        journal
    }

    fn list_update_logs(&self) -> Vec<SupdateLog> {
        let path = Path::new(&self.config.path).join("**/*.sup");

        // TODO: This is really wasteful. Make this an iterator
        // Get list of all files in the repo
        let mut updates = glob(path.to_str().unwrap())
            .expect("glob failed")
            .filter_map(|f| f.map(|p| SupdateLog::new(&p)).ok())
            .collect::<Vec<SupdateLog>>();

        // We want sorted (chronological, desc) order, based on file name.
        updates.sort_by(|a, b| b.name.cmp(&a.name));
        return updates;
    }

    fn active_update_log(&self) -> SupdateLog {
        let now = Utc::now();

        let last_update = self.list_update_logs().pop();

        // Use the last update if it's still the same day, otherwise create a new one.
        last_update
            .filter(|log| log.timestamp.date() == now.date())
            .unwrap_or_else(|| {
                let log_path = now.format("%Y/%m/%Y%m%d_%H%M%S.sup").to_string();
                let abs_path = Path::new(&self.config.path).join(log_path);

                let dir = abs_path.parent().unwrap();

                std::fs::create_dir_all(dir).expect("create directory failed");

                SupdateLog::new(&abs_path)
            })
    }
}

/**
 * A collection of Updates.
 *
 * Represents the cumulative, "rolled up" set of task updates.
 */
#[derive(Debug)]
struct Journal {
    /// id -> task
    entries: BTreeMap<String, Task>,
    last_id: u64,
}

impl Journal {
    fn new() -> Self {
        return Self {
            entries: BTreeMap::new(),
            last_id: 0,
        };
    }

    fn add(&mut self, update: &TaskUpdate) {
        let id = &update.id;

        // Keep track of higest id value we've seen.
        let id_int = id.parse::<u64>().unwrap();
        self.last_id = std::cmp::max(self.last_id, id_int);

        let task = self.entries.get_mut(id);

        match task {
            Some(t) => t.apply(update),
            None => {
                self.entries.insert(id.clone(), Task::from(update));
            }
        }
    }

    fn next_id(&mut self) -> String {
        self.last_id += 1;

        format!("{:04}", self.last_id)
    }

    // TODO: Hack until a custom iterator is implemented.
    fn for_each(&self, f: &Fn(&Task) -> ()) {
        self.entries.values().for_each(f)
    }
}

struct SupCli {
    matches: ArgMatches<'static>,
}

impl SupCli {
    fn new() -> Self {
        Self {
            matches: Self::parse_args(),
        }
    }

    fn parse_args<'a>() -> ArgMatches<'a> {
        App::new("sup")
            .version("0.0.0")
            .about("Keep track of what's up.")
            .arg(
                Arg::with_name("config")
                    .short("c")
                    .long("config")
                    .value_name("FILE")
                    .takes_value(true)
                    .help("Set custom location for Supfile"),
            )
            .subcommand(
                SubCommand::with_name("todo")
                    .about("create a new todo item")
                    .arg(Arg::with_name("TASK").takes_value(true).multiple(true)),
            )
            .subcommand(
                SubCommand::with_name("show")
                    .about("asdf")
                    .arg(Arg::with_name("DATE").takes_value(true).help("asdf")),
            )
            .subcommand(
                SubCommand::with_name("serve")
                    .about("launch web interface")
                    .arg(
                        Arg::with_name("port")
                            .short("p")
                            .long("port")
                            .takes_value(true),
                    ),
            )
            .get_matches()
    }

    fn load_config(&self) -> Result<Supfile, Box<dyn Error>> {
        let path = self
            .matches
            .value_of("config")
            .map(|p| Path::new(p).to_path_buf())
            .unwrap_or_else(Supfile::find);

        let bytes = std::fs::read_to_string(path.as_os_str())?;
        Ok(Supfile::from(&bytes)?)
    }

    fn run(&self) -> Result<(), Box<dyn Error>> {
        let cfg = self.load_config().expect("error in config file");
        let mut app = SupApp::new(&cfg);

        match self.matches.subcommand() {
            ("show", Some(m)) => println!("TODO: show {:?}", m),
            ("serve", Some(m)) => println!("TODO: serve {:?}", m),
            ("todo", Some(m)) => {
                let task = m.values_of("TASK").map(|v| {
                    let vec = v.collect::<Vec<_>>();
                    vec.join(" ")
                });

                app.run_add_task(task)?;
            }

            _ => app.run_show_updates()?,
        };

        Ok(())
    }
}

struct SupApp {
    repo: Repository,
    journal: Journal,
}

impl SupApp {
    fn new(cfg: &Supfile) -> Self {
        let repo = Repository::new(cfg.repo.clone());
        let journal = repo.open_journal();

        Self { repo, journal }
    }

    fn run_add_task(&mut self, task: Option<String>) -> Result<(), Box<dyn Error>> {
        println!("journal: {:?}: {:?}", self.journal, task);
        let task = task.expect("TODO: ui task creation");
        let id = self.journal.next_id();

        let update = TaskUpdate::new_todo(id, task, None, vec![]);
        self.repo.active_update_log().write_update(&update)?;

        Ok(())
    }

    fn run_show_updates(&self) -> Result<(), Box<dyn Error>> {
        self.journal.for_each(&|task| {
            println!("{}", task.summary());
        });

        Ok(())
    }
}

// TODO: Investiage this instead of Box<Error>
// https://github.com/rust-lang-nursery/failure
fn main() {
    let app = SupCli::new();
    match app.run() {
        Err(e) => println!("oh no! {:?}", e),
        Ok(_) => (),
    };
}
<commit_msg>Show journal after adding update<commit_after>extern crate serde_derive;

use std::collections::{BTreeMap, HashSet};
use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::{BufRead, BufReader, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};

use chrono::offset::TimeZone;
use chrono::{DateTime, Utc};
use clap::{App, Arg, ArgMatches, SubCommand};
use glob::glob;
use serde_derive::{Deserialize, Serialize};

#[derive(Deserialize, Debug, Clone)]
struct RepoConfig {
    path: String,
    #[serde(default = "default_false")]
    commit: bool,
    #[serde(default = "default_false")]
    sync_updates: bool,
}

fn default_false() -> bool {
    false
}

#[derive(Deserialize, Debug)]
struct Supfile {
    repo: RepoConfig,
    editor: Option<String>,
}

impl Supfile {
    pub fn from(str: &str) -> Result<Self, toml::de::Error> {
        toml::from_str(&str)
    }

    pub fn find() -> PathBuf {
        // TODO: pull in XDG crate for paths
        let default_dir = "~/.config/sup/";

        ["./", default_dir]
            .iter()
            .map(|dir| Path::new(dir).join("Supfile"))
            .find(|p| p.exists())
            .unwrap_or_else(|| {
                // TODO: offer to create path somehow
                panic!("can't find supfile")
            })
    }
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
enum TaskState {
    Todo,
    InProgress,
    Complete,
    Canceled,
    Deferred,
}

impl TaskState {
    fn is_open(self) -> bool {
        match self {
            TaskState::Todo | TaskState::InProgress | TaskState::Deferred => true,
            _ => false,
        }
    }
}

impl std::fmt::Display for TaskState {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let value = match self {
            TaskState::Todo => " ",
            TaskState::InProgress => "•",
            TaskState::Complete => "✔",
            TaskState::Canceled => "-",
            TaskState::Deferred => "⟫",
        };
        write!(f, "{}", value)
    }
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
enum Action {
    Create {
        task: String,
        #[serde(default)]
        notes: Option<String>,
        #[serde(default)]
        tags: Vec<String>,
    },
    EditTags {
        add: Vec<String>,
        remove: Vec<String>,
    },
    EditTask(String),
    EditNotes(Option<String>),
    EditState(TaskState),
}

#[derive(Deserialize, Serialize)]
struct TaskUpdate {
    id: String,
    timestamp: DateTime<Utc>,
    action: Action,
}

impl TaskUpdate {
    fn from_str(line: &str) -> serde_json::Result<Self> {
        serde_json::from_str(line).map_err(|e| {
            println!("nuts: {:?}", e);
            e
        })
    }

    /// Create a basic TaskUpdate. The `id` is left unset and must be set before being written.
    fn new_todo(
        id: String,
        task: String,
        notes: Option<String>,
        tags: Vec<String>,
    ) -> Self {
        Self {
            id: id,
            timestamp: Utc::now(),
            action: Action::Create { task, notes, tags },
        }
    }
}

#[derive(Clone, Debug)]
struct Task {
    id: String,
    created_at: DateTime<Utc>,
    completed_at: Option<DateTime<Utc>>,
    state: TaskState,
    task: String,
    notes: Option<String>,
    tags: HashSet<String>,
}

impl Task {
    fn apply(&mut self, update: &TaskUpdate) {
        match &update.action {
            Action::Create { task, notes, tags } => {
                self.task = task.clone();
                self.notes = notes.clone();
                for tag in tags.iter() {
                    self.tags.insert(tag.clone());
                }
            }
            Action::EditTags { add, remove } => {
                for tag in remove.iter() {
                    self.tags.remove(tag);
                }

                for tag in add.iter() {
                    self.tags.insert(tag.clone());
                }
            }
            Action::EditTask(task) => self.task = task.clone(),
            Action::EditNotes(notes) => self.notes = notes.clone(),
            Action::EditState(state) => {
                self.state = state.clone();
                if state == &TaskState::Complete {
                    self.completed_at = Some(update.timestamp);
                }
            }
        }
    }

    fn summary(&self) -> String {
        format!("{} [{}] {}", self.id, self.state, self.task)
    }
}

impl From<&TaskUpdate> for Task {
    fn from(update: &TaskUpdate) -> Self {
        let mut task = Task {
            id: update.id.clone(),
            created_at: update.timestamp.clone(),
            completed_at: None,
            state: TaskState::Todo,
            task: "untitled".to_string(),
            notes: None,
            tags: HashSet::new(),
        };

        task.apply(update);
        return task;
    }
}

#[derive(Debug)]
struct SupdateLog {
    name: String,
    path: String,

    timestamp: DateTime<Utc>,
}

impl SupdateLog {
    fn new(path: &Path) -> Self {
        let name: String = path
            .file_name()
            .expect("need file, not directory")
            .to_string_lossy()
            .into();

        let timestamp = Utc
            .datetime_from_str(&name, "%Y%m%d_%H%M%S.sup")
            .unwrap_or_else(|_| {
                println!("{:?} appears to be improperly named!", path);
                Utc.timestamp(0, 0)
            });

        // TODO: Support versioning in line
        SupdateLog {
            name,
            path: path.to_string_lossy().into(),
            timestamp,
        }
    }

    fn write_update(&self, task: &TaskUpdate) -> std::io::Result<()> {
        let mut file = self.open_file()?;
        file.seek(SeekFrom::End(0)).expect("could not seek to end");

        serde_json::ser::to_writer(&file, task)?;
        file.write_all(b"\n")?;

        Ok(())
    }

    fn iter(&self) -> SupdateIterator {
        let mut file = self.open_file().expect("could not open file");
        file.seek(SeekFrom::Start(0)).expect("could not rewind");

        SupdateIterator {
            reader: BufReader::new(file),
        }
    }

    /// Open the log file or create it if it doesn't exist.
    fn open_file(&self) -> std::io::Result<File> {
        OpenOptions::new()
            .read(true)
            .append(true)
            .create(true)
            .open(&self.path)
    }
}

struct SupdateIterator {
    reader: BufReader<File>,
}

impl Iterator for SupdateIterator {
    type Item = TaskUpdate;

    fn next(&mut self) -> Option<TaskUpdate> {
        let mut line = String::new();
        return match self.reader.read_line(&mut line) {
            // End of file
            Ok(0) => None,

            Ok(_) => {
                //println!("line = {:?}", line);
                // TODO: alert when we don't succeed at parsing
                TaskUpdate::from_str(&line).ok()
            }

            Err(e) => {
                println!("Failed to read line: {:?}", e);
                None
            }
        };
    }
}

/**
 * A Repository represents a directory containing SupdateLogs.
 *
 * The directory structure is something like this:
 *
 * repo/
 *   2019/
 *     08/
 *       20190801_235959.sup
 *       20190802_003030.sup
 *       20190802_123030.sup
 *
 * TODO: Support concept of `rollup` files to put an upper limit on
 * how far we need to look back to fully reconstruct the state of
 * everything.
 */

struct Repository {
    config: RepoConfig,
}

impl Repository {
    fn new(cfg: RepoConfig) -> Self {
        // TODO: Handle error, return Result
        if !Path::new(&cfg.path).exists() {
            panic!("given repository does not exist")
        }

        Repository { config: cfg }
    }

    fn open_journal(&self) -> Journal {
        let updates = self.list_update_logs();
        self.build_journal(updates)
    }

    fn build_journal(&self, updates: Vec<SupdateLog>) -> Journal {
        let mut journal = Journal::new();

        // Reverse ordering so that we consume oldest elements first.
        for log in updates.into_iter().rev() {
            println!("reading: {:?}", log);

            for ref update in log.iter() {
                journal.add(update);
            }
        }

        journal
    }

    fn list_update_logs(&self) -> Vec<SupdateLog> {
        let path = Path::new(&self.config.path).join("**/*.sup");

        // TODO: This is really wasteful. Make this an iterator
        // Get list of all files in the repo
        let mut updates = glob(path.to_str().unwrap())
            .expect("glob failed")
            .filter_map(|f| f.map(|p| SupdateLog::new(&p)).ok())
            .collect::<Vec<SupdateLog>>();

        // We want sorted (chronological, desc) order, based on file name.
        updates.sort_by(|a, b| b.name.cmp(&a.name));
        return updates;
    }

    fn active_update_log(&self) -> SupdateLog {
        let now = Utc::now();

        let last_update = self.list_update_logs().pop();

        // Use the last update if it's still the same day, otherwise create a new one.
        last_update
            .filter(|log| log.timestamp.date() == now.date())
            .unwrap_or_else(|| {
                let log_path = now.format("%Y/%m/%Y%m%d_%H%M%S.sup").to_string();
                let abs_path = Path::new(&self.config.path).join(log_path);

                let dir = abs_path.parent().unwrap();

                std::fs::create_dir_all(dir).expect("create directory failed");

                SupdateLog::new(&abs_path)
            })
    }
}

/**
 * A collection of Updates.
 *
 * Represents the cumulative, "rolled up" set of task updates.
 */
#[derive(Debug)]
struct Journal {
    /// id -> task
    entries: BTreeMap<String, Task>,
    last_id: u64,
}

impl Journal {
    fn new() -> Self {
        return Self {
            entries: BTreeMap::new(),
            last_id: 0,
        };
    }

    fn add(&mut self, update: &TaskUpdate) {
        let id = &update.id;

        // Keep track of higest id value we've seen.
        let id_int = id.parse::<u64>().unwrap();
        self.last_id = std::cmp::max(self.last_id, id_int);

        let task = self.entries.get_mut(id);

        match task {
            Some(t) => t.apply(update),
            None => {
                self.entries.insert(id.clone(), Task::from(update));
            }
        }
    }

    fn next_id(&mut self) -> String {
        self.last_id += 1;

        format!("{:04}", self.last_id)
    }

    // TODO: Hack until a custom iterator is implemented.
    fn for_each(&self, f: &Fn(&Task) -> ()) {
        self.entries.values().for_each(f)
    }
}

struct SupCli {
    matches: ArgMatches<'static>,
}

impl SupCli {
    fn new() -> Self {
        Self {
            matches: Self::parse_args(),
        }
    }

    fn parse_args<'a>() -> ArgMatches<'a> {
        App::new("sup")
            .version("0.0.0")
            .about("Keep track of what's up.")
            .arg(
                Arg::with_name("config")
                    .short("c")
                    .long("config")
                    .value_name("FILE")
                    .takes_value(true)
                    .help("Set custom location for Supfile"),
            )
            .subcommand(
                SubCommand::with_name("todo")
                    .about("create a new todo item")
                    .arg(Arg::with_name("TASK").takes_value(true).multiple(true)),
            )
            .subcommand(
                SubCommand::with_name("show")
                    .about("asdf")
                    .arg(Arg::with_name("DATE").takes_value(true).help("asdf")),
            )
            .subcommand(
                SubCommand::with_name("serve")
                    .about("launch web interface")
                    .arg(
                        Arg::with_name("port")
                            .short("p")
                            .long("port")
                            .takes_value(true),
                    ),
            )
            .get_matches()
    }

    fn load_config(&self) -> Result<Supfile, Box<dyn Error>> {
        let path = self
            .matches
            .value_of("config")
            .map(|p| Path::new(p).to_path_buf())
            .unwrap_or_else(Supfile::find);

        let bytes = std::fs::read_to_string(path.as_os_str())?;
        Ok(Supfile::from(&bytes)?)
    }

    fn run(&self) -> Result<(), Box<dyn Error>> {
        let cfg = self.load_config().expect("error in config file");
        let mut app = SupApp::new(&cfg);

        match self.matches.subcommand() {
            ("show", Some(m)) => println!("TODO: show {:?}", m),
            ("serve", Some(m)) => println!("TODO: serve {:?}", m),
            ("todo", Some(m)) => {
                let task = m.values_of("TASK").map(|v| {
                    let vec = v.collect::<Vec<_>>();
                    vec.join(" ")
                });

                app.run_add_task(task)?;
            }

            _ => app.run_show_updates()?,
        };

        Ok(())
    }
}

struct SupApp {
    repo: Repository,
}

impl SupApp {
    fn new(cfg: &Supfile) -> Self {
        let repo = Repository::new(cfg.repo.clone());

        Self { repo }
    }

    fn run_add_task(&mut self, task: Option<String>) -> Result<(), Box<dyn Error>> {
        let mut journal = self.repo.open_journal();

        let task = task.expect("TODO: ui task creation");
        let id = journal.next_id();

        let update = TaskUpdate::new_todo(id, task, None, vec![]);
        self.repo.active_update_log().write_update(&update)?;

        self.run_show_updates()
    }

    fn run_show_updates(&self) -> Result<(), Box<dyn Error>> {
        let journal = self.repo.open_journal();
        journal.for_each(&|task| {
            println!("{}", task.summary());
        });

        Ok(())
    }
}

// TODO: Investiage this instead of Box<Error>
// https://github.com/rust-lang-nursery/failure
fn main() {
    let app = SupCli::new();
    match app.run() {
        Err(e) => println!("oh no! {:?}", e),
        Ok(_) => (),
    };
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::codegen::Bindings::XRStationaryReferenceSpaceBinding;
use crate::dom::bindings::codegen::Bindings::XRStationaryReferenceSpaceBinding::XRStationaryReferenceSpaceSubtype;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::DomRoot;
use crate::dom::globalscope::GlobalScope;
use crate::dom::xrreferencespace::XRReferenceSpace;
use crate::dom::xrrigidtransform::XRRigidTransform;
use crate::dom::xrsession::XRSession;
use crate::dom::xrspace::XRSpace;
use dom_struct::dom_struct;
use euclid::RigidTransform3D;
use webvr_traits::WebVRFrameData;

#[dom_struct]
pub struct XRStationaryReferenceSpace {
    xrreferencespace: XRReferenceSpace,
    ty: XRStationaryReferenceSpaceSubtype,
}

#[allow(unused)]
impl XRStationaryReferenceSpace {
    pub fn new_inherited(
        session: &XRSession,
        ty: XRStationaryReferenceSpaceSubtype,
        transform: &XRRigidTransform,
    ) -> XRStationaryReferenceSpace {
        XRStationaryReferenceSpace {
            xrreferencespace: XRReferenceSpace::new_inherited(session, transform),
            ty,
        }
    }

    pub fn new(
        global: &GlobalScope,
        session: &XRSession,
        ty: XRStationaryReferenceSpaceSubtype,
    ) -> DomRoot<XRStationaryReferenceSpace> {
        let transform = XRRigidTransform::identity(global);
        reflect_dom_object(
            Box::new(XRStationaryReferenceSpace::new_inherited(
                session, ty, &transform,
            )),
            global,
            XRStationaryReferenceSpaceBinding::Wrap,
        )
    }
}

impl XRStationaryReferenceSpace {
    /// Gets pose of the viewer with respect to this space
    ///
    /// Does not apply originOffset, use get_viewer_pose on XRReferenceSpace instead
    pub fn get_unoffset_viewer_pose(&self, viewer_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
        let viewer_pose = XRSpace::viewer_pose_from_frame_data(viewer_pose);
        match self.ty {
            XRStationaryReferenceSpaceSubtype::Eye_level => {
                // we get viewer poses in eye-level space by default
                viewer_pose
            }
            XRStationaryReferenceSpaceSubtype::Floor_level => {
                // XXXManishearth support floor-level
                viewer_pose
            }
            XRStationaryReferenceSpaceSubtype::Position_disabled => {
                // This space follows the user around, but does not mirror the user's orientation
                // Thus, the viewer's pose relative to this space is simply their orientation
                viewer_pose.rotation.into()
            }
        }

    }

    /// Gets pose represented by this space
    ///
    /// Does not apply originOffset, use get_pose on XRReferenceSpace instead
    pub fn get_unoffset_pose(&self, viewer_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
        // XXXManishearth add floor-level transform for floor-level and disable position in position-disabled
        match self.ty {
            XRStationaryReferenceSpaceSubtype::Eye_level => {
                // The eye-level pose is basically whatever the headset pose was at t=0, which
                // for most devices is (0, 0, 0)
                RigidTransform3D::identity()
            }
            XRStationaryReferenceSpaceSubtype::Floor_level => {
                // XXXManishearth support floor-level
                RigidTransform3D::identity()
            }
            XRStationaryReferenceSpaceSubtype::Position_disabled => {
                // This space follows the user around, but does not mirror the user's orientation
                let viewer_pose = XRSpace::viewer_pose_from_frame_data(viewer_pose);
                viewer_pose.translation.into()
            }
        }
    }
}
<commit_msg>Add rough support for floor-level space<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::codegen::Bindings::XRStationaryReferenceSpaceBinding;
use crate::dom::bindings::codegen::Bindings::XRStationaryReferenceSpaceBinding::XRStationaryReferenceSpaceSubtype;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::DomRoot;
use crate::dom::globalscope::GlobalScope;
use crate::dom::xrreferencespace::XRReferenceSpace;
use crate::dom::xrrigidtransform::XRRigidTransform;
use crate::dom::xrsession::XRSession;
use crate::dom::xrspace::XRSpace;
use dom_struct::dom_struct;
use euclid::{RigidTransform3D, Vector3D};
use webvr_traits::WebVRFrameData;

#[dom_struct]
pub struct XRStationaryReferenceSpace {
    xrreferencespace: XRReferenceSpace,
    ty: XRStationaryReferenceSpaceSubtype,
}

#[allow(unused)]
impl XRStationaryReferenceSpace {
    pub fn new_inherited(
        session: &XRSession,
        ty: XRStationaryReferenceSpaceSubtype,
        transform: &XRRigidTransform,
    ) -> XRStationaryReferenceSpace {
        XRStationaryReferenceSpace {
            xrreferencespace: XRReferenceSpace::new_inherited(session, transform),
            ty,
        }
    }

    pub fn new(
        global: &GlobalScope,
        session: &XRSession,
        ty: XRStationaryReferenceSpaceSubtype,
    ) -> DomRoot<XRStationaryReferenceSpace> {
        let transform = XRRigidTransform::identity(global);
        reflect_dom_object(
            Box::new(XRStationaryReferenceSpace::new_inherited(
                session, ty, &transform,
            )),
            global,
            XRStationaryReferenceSpaceBinding::Wrap,
        )
    }
}

impl XRStationaryReferenceSpace {
    /// Gets pose of the viewer with respect to this space
    ///
    /// Does not apply originOffset, use get_viewer_pose on XRReferenceSpace instead
    pub fn get_unoffset_viewer_pose(&self, viewer_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
        let viewer_pose = XRSpace::viewer_pose_from_frame_data(viewer_pose);
        match self.ty {
            XRStationaryReferenceSpaceSubtype::Eye_level => {
                // we get viewer poses in eye-level space by default
                viewer_pose
            }
            XRStationaryReferenceSpaceSubtype::Floor_level => {
                // XXXManishearth support getting floor info from stage parameters

                // assume approximate user height of 2 meters
                let floor_to_eye: RigidTransform3D<f64> = Vector3D::new(0., 2., 0.).into();
                floor_to_eye.pre_mul(&viewer_pose)
            }
            XRStationaryReferenceSpaceSubtype::Position_disabled => {
                // This space follows the user around, but does not mirror the user's orientation
                // Thus, the viewer's pose relative to this space is simply their orientation
                viewer_pose.rotation.into()
            }
        }

    }

    /// Gets pose represented by this space
    ///
    /// Does not apply originOffset, use get_pose on XRReferenceSpace instead
    pub fn get_unoffset_pose(&self, viewer_pose: &WebVRFrameData) -> RigidTransform3D<f64> {
        // XXXManishearth add floor-level transform for floor-level and disable position in position-disabled
        match self.ty {
            XRStationaryReferenceSpaceSubtype::Eye_level => {
                // The eye-level pose is basically whatever the headset pose was at t=0, which
                // for most devices is (0, 0, 0)
                RigidTransform3D::identity()
            },
            XRStationaryReferenceSpaceSubtype::Floor_level => {
                // XXXManishearth support getting floor info from stage parameters

                // Assume approximate height of 2m
                // the floor-level space is 2m below the eye-level space, which is (0, 0, 0)
                Vector3D::new(0., -2., 0.).into()
            },
            XRStationaryReferenceSpaceSubtype::Position_disabled => {
                // This space follows the user around, but does not mirror the user's orientation
                let viewer_pose = XRSpace::viewer_pose_from_frame_data(viewer_pose);
                viewer_pose.translation.into()
            },
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp;
use std::io::{self, BufRead, Read, Write};

#[derive(Debug)]
enum Phase {
    Read { head: usize, tail: usize },
    Write {
        read_tail: usize,
        head: usize,
        tail: usize,
    },
}
impl Phase {
    fn head(&self) -> usize {
        match *self {
            Phase::Read { head, .. } => head,
            Phase::Write { head, .. } => head,
        }
    }
    fn tail(&self) -> usize {
        match *self {
            Phase::Read { tail, .. } => tail,
            Phase::Write { tail, .. } => tail,
        }
    }
    fn head_mut(&mut self) -> &mut usize {
        match *self {
            Phase::Read { ref mut head, .. } => head,
            Phase::Write { ref mut head, .. } => head,
        }
    }
    fn tail_mut(&mut self) -> &mut usize {
        match *self {
            Phase::Read { ref mut tail, .. } => tail,
            Phase::Write { ref mut tail, .. } => tail,
        }
    }
}

#[derive(Debug)]
pub struct Buffer {
    bytes: Vec<u8>,
    phase: Phase,
    max_len: usize,
}
impl Buffer {
    pub fn new(min_len: usize, max_len: usize) -> Self {
        assert!(min_len <= max_len);
        Buffer {
            bytes: vec![0; min_len],
            phase: Phase::Read { head: 0, tail: 0 },
            max_len: max_len,
        }
    }
    pub fn is_empty(&self) -> bool {
        self.phase.head() == self.phase.tail()
    }
    pub fn enter_read_phase(&mut self) {
        if let Phase::Write { read_tail, .. } = self.phase {
            self.phase = Phase::Read {
                head: 0,
                tail: read_tail,
            };
        }
    }
    pub fn enter_write_phase(&mut self) {
        if let Phase::Read { head, tail } = self.phase {
            let read_tail = tail - head;
            self.bytes.drain(..read_tail);
            self.phase = Phase::Write {
                read_tail: read_tail,
                head: read_tail,
                tail: read_tail,
            };
        }
    }
    pub fn fill_from<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
        self.expand_if_needed();
        self.check_overflow()?;
        let tail = self.phase.tail_mut();
        let buf = &mut self.bytes[*tail..];
        let read_size = reader.read(buf)?;
        *tail += read_size;
        Ok(read_size)
    }
    pub fn as_slice(&self) -> &[u8] {
        &self.bytes[self.phase.head()..self.phase.tail()]
    }
    fn expand_if_needed(&mut self) {
        if self.phase.tail() == self.bytes.len() {
            let new_len = cmp::min(self.bytes.len() * 2, self.max_len);
            self.bytes.resize(new_len, 0);
        }
    }
    fn check_overflow(&self) -> io::Result<()> {
        if self.phase.tail() == self.max_len {
            let message = format!("Buffer for HTTP non-body part is overflowed: max_len={}",
                                  self.max_len);
            Err(io::Error::new(io::ErrorKind::WriteZero, message))
        } else {
            Ok(())
        }
    }
}
impl Read for Buffer {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let size;
        {
            let src = self.as_slice();
            size = cmp::min(buf.len(), src.len());
            (&mut buf[..size]).copy_from_slice(&src[..size]);
        }
        self.consume(size);
        Ok(size)
    }
}
impl BufRead for Buffer {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        Ok(self.as_slice())
    }
    fn consume(&mut self, amt: usize) {
        let tail = self.phase.tail();
        let head = self.phase.head_mut();
        *head += amt;
        assert!(*head <= tail)
    }
}
impl Write for Buffer {
    fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> {
        self.fill_from(&mut buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.check_overflow()
    }
}
<commit_msg>Fix buffer management bug<commit_after>use std::cmp;
use std::io::{self, BufRead, Read, Write};

#[derive(Debug)]
enum Phase {
    Read { head: usize, tail: usize },
    Write {
        read_tail: usize,
        head: usize,
        tail: usize,
    },
}
impl Phase {
    fn head(&self) -> usize {
        match *self {
            Phase::Read { head, .. } => head,
            Phase::Write { head, .. } => head,
        }
    }
    fn tail(&self) -> usize {
        match *self {
            Phase::Read { tail, .. } => tail,
            Phase::Write { tail, .. } => tail,
        }
    }
    fn head_mut(&mut self) -> &mut usize {
        match *self {
            Phase::Read { ref mut head, .. } => head,
            Phase::Write { ref mut head, .. } => head,
        }
    }
    fn tail_mut(&mut self) -> &mut usize {
        match *self {
            Phase::Read { ref mut tail, .. } => tail,
            Phase::Write { ref mut tail, .. } => tail,
        }
    }
}

#[derive(Debug)]
pub struct Buffer {
    bytes: Vec<u8>,
    phase: Phase,
    max_len: usize,
}
impl Buffer {
    pub fn new(min_len: usize, max_len: usize) -> Self {
        assert!(min_len <= max_len);
        Buffer {
            bytes: vec![0; min_len],
            phase: Phase::Read { head: 0, tail: 0 },
            max_len: max_len,
        }
    }
    pub fn is_empty(&self) -> bool {
        self.phase.head() == self.phase.tail()
    }
    pub fn enter_read_phase(&mut self) {
        if let Phase::Write { read_tail, .. } = self.phase {
            self.phase = Phase::Read {
                head: 0,
                tail: read_tail,
            };
        }
    }
    pub fn enter_write_phase(&mut self) {
        if let Phase::Read { head, tail } = self.phase {
            let read_tail = tail - head;

            // Shift to front
            let len = self.bytes.len();
            self.bytes.drain(..read_tail);
            self.bytes.resize(len, 0);

            self.phase = Phase::Write {
                read_tail: read_tail,
                head: read_tail,
                tail: read_tail,
            };
        }
    }
    pub fn fill_from<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
        self.expand_if_needed();
        self.check_overflow()?;
        let tail = self.phase.tail_mut();
        let buf = &mut self.bytes[*tail..];
        let read_size = reader.read(buf)?;
        *tail += read_size;
        Ok(read_size)
    }
    pub fn as_slice(&self) -> &[u8] {
        &self.bytes[self.phase.head()..self.phase.tail()]
    }
    fn expand_if_needed(&mut self) {
        if self.phase.tail() == self.bytes.len() {
            let new_len = cmp::min(self.bytes.len() * 2, self.max_len);
            self.bytes.resize(new_len, 0);
        }
    }
    fn check_overflow(&self) -> io::Result<()> {
        if self.phase.tail() == self.max_len {
            let message = format!("Buffer for HTTP non-body part is overflowed: max_len={}",
                                  self.max_len);
            Err(io::Error::new(io::ErrorKind::WriteZero, message))
        } else {
            Ok(())
        }
    }
}
impl Read for Buffer {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let size;
        {
            let src = self.as_slice();
            size = cmp::min(buf.len(), src.len());
            (&mut buf[..size]).copy_from_slice(&src[..size]);
        }
        self.consume(size);
        Ok(size)
    }
}
impl BufRead for Buffer {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        Ok(self.as_slice())
    }
    fn consume(&mut self, amt: usize) {
        let tail = self.phase.tail();
        let head = self.phase.head_mut();
        *head += amt;
        assert!(*head <= tail)
    }
}
impl Write for Buffer {
    fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> {
        self.fill_from(&mut buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.check_overflow()
    }
}
<|endoftext|>


<commit_before>use lexer::*;
use std::iter::Iterator;
use std::iter::Peekable;
use std::result;
// use itertools::Itertools;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Const {
  Data,
  Codata,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Var {
  name: String,
  idx: i32,
}

impl Var {
  pub fn new(name: &str, idx: i32) -> Var {
    Var {
      name: name.to_string(),
      idx: idx,
    }
  }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Tree {
  // Type system constants
  Const(Const),
  // Bound variables
  Var(Var),
  // Lambda
  Lam(Var, Box<Tree>, Box<Tree>),
  // "forall"
  Pi(Var, Box<Tree>, Box<Tree>),
  // Function application
  App(Box<Tree>, Box<Tree>),
}

pub struct Parser<I>
  where I: Clone + Iterator<Item = char>
{
  lexer: Peekable<Lexer<I>>,
}

pub type Error = String;
pub type Result<T> = result::Result<T, Error>;

impl<I: Clone + Iterator<Item = char>> Parser<I> {
  fn new(lexer: Lexer<I>) -> Parser<I> {
    Parser { lexer: lexer.peekable() }
  }

  pub fn parse(&mut self) -> Result<Tree> {
    match self.lexer.peek() {
      None => Err("eof".to_string()),
      Some(tok) => {
        match *tok {
          Token::Variable(ref name) => Ok(Tree::Var(Var::new(name, 0))),
          _ => Err("eof".to_string()),
        }
      }
    }
  }
}

pub fn parse<I: Clone + Iterator<Item = char>>(chars: I) -> Result<Tree> {
  let lexer = lex(chars);
  let mut parser = Parser::new(lexer);
  parser.parse()
}

// impl<I: Clone + Iterator<Item = char>> Iterator for Parser<I> {
//   type Item = Tree;
//   fn next(&mut self) -> Option<Tree> {
//     match self.lexer.peek() {
//       None => None,
//       Some(tok) => {
//         match tok {
//           _ => None,
//         }
//       }
//     }
//   }
// }

#[test]
fn test_app() {
  let p = parse("a b".chars());
  // assert_eq!(p.next(), None);
  assert_eq!(p.ok().unwrap(), Tree::Var(Var::new("a", 0)));
}
<commit_msg>Continue work on parser.<commit_after>use lexer::*;
use std::iter::Iterator;
use std::iter::Peekable;
use std::result;
// use itertools::Itertools;

/*
Informal BNF grammar for System Zero

definition = <variable> <equal> expr <dot>
           | <variable> <colon> expr <dot>

expr = const
     | var
     | lam
     | pi
     | app
     | <lparen> expr <rparen>

const = <variable>("data")
      | <variable>("codata")

var = <variable>

lam = <lparen> <variable> <colon> expr <rparen> <arrow> expr
    | expr <arrow> expr

pi = <forall> <lparen> <variable> <colon> expr <rparen> <arrow> expr

app = expr expr

*/

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Const {
  Data,
  Codata,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Var {
  name: String
}

impl Var {
  pub fn new(name: &str) -> Var {
    Var {
      name: name.to_string()
    }
  }
}

impl ToString for Var {
  fn to_string(&self) -> String {
    self.name.clone()
  }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Tree {
  // Type system constants
  Const(Const),
  // Bound variables
  Var(Var),
  // Lambda
  Lam(Var, Box<Tree>, Box<Tree>),
  // "forall"
  Pi(Var, Box<Tree>, Box<Tree>),
  // Function application
  App(Box<Tree>, Box<Tree>),
}

pub struct Parser<I>
  where I: Clone + Iterator<Item = char>
{
  lexer: Peekable<Lexer<I>>,
}

pub type Error = String;
pub type Result<T> = result::Result<T, Error>;

impl<I: Clone + Iterator<Item = char>> Parser<I> {
  fn new(lexer: Lexer<I>) -> Parser<I> {
    Parser { lexer: lexer.peekable() }
  }

  pub fn parse(&mut self) -> Result<Tree> {
    match self.lexer.peek() {
      None => Err("eof".to_string()),
      Some(tok) => {
        match *tok {
          Token::Variable(ref name) => Ok(Tree::Var(Var::new(name))),
          _ => Err("eof".to_string()),
        }
      }
    }
  }
}

pub fn parse<I: Clone + Iterator<Item = char>>(chars: I) -> Result<Tree> {
  let lexer = lex(chars);
  let mut parser = Parser::new(lexer);
  parser.parse()
}

#[test]
fn test_app() {
  let p = parse("a b".chars());
  // assert_eq!(p.next(), None);
  assert_eq!(p.ok().unwrap(), Tree::Var(Var::new("a")));
}
<|endoftext|>