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

use meta::Meta;
use signature::Signature;
use rustc_serialize::json;
use rustc_serialize::Encodable;
use rustc_serialize::Encoder;
use rustc_serialize::Decoder;
use chrono;
use ed25519;
use lzma;
use chrono::UTC;

/// This is the amount of bytes a single ed25519 signature takes up
pub const SIGNATURE_LEN: usize = 64 + CERTIFICATE_BYTE_LEN;

/// This is the amount of bytes a single key takes up.
pub const PRIVATE_KEY_LEN: usize = 64;
pub const PUBLIC_KEY_LEN: usize = 32;

pub const CERTIFICATE_BYTE_LEN: usize =
    25 /* expires as string */ + 64 /* hash of meta */ + PUBLIC_KEY_LEN;

#[derive(Clone,RustcDecodable,RustcEncodable,Debug)]
pub struct Certificate {
    /// The meta element contains data associated with the certificate
    /// Common data is "use-for" which contains a list of permissions
    meta: Meta,

    /// the public key of this certificate
    public_key: Vec<u8>,

    /// the private key, if it is known
    private_key: Option<Vec<u8>>,

    /// a timestamp when this certificate expires
    expires: String,

    /// a signature for trust-chaining certificates
    /// if the certificate is not signed yet, this is None
    signature: Option<Signature>,
}

impl Certificate {
    //    pub fn new(public_key: Vec<u8>,
    //               expires: chrono::DateTime<chrono::UTC>)
    //               -> Certificate {
    //        Certificate {
    //            meta: Meta::new(),
    //            signature: None,
    //            public_key: public_key,
    //            private_key: None,
    //            expires: expires,
    //        }
    //    }

    pub fn get_meta_mut(&mut self) -> &mut Meta {
        &mut self.meta
    }

    pub fn get_meta(&self) -> &Meta {
        &self.meta
    }

    pub fn get_public_key(&self) -> &Vec<u8> {
        &self.public_key
    }

    /// This method returns the private key, if it is known, or None if the certificate has been initialized without the private key
    pub fn get_private_key(&self) -> &Option<Vec<u8>> {
        &self.private_key
    }

    /// This method returns true, if the private key is saved in the certificate
    pub fn has_private_key(&self) -> bool {
        self.private_key.is_some()
    }

    pub fn get_expires(&self) -> &str {
    	&self.expires
    }

    pub fn is_signed(&self) -> bool {
        self.signature.is_some()
    }

    /// This method signs the given data and returns the signature
    pub fn sign(&self, data: &[u8]) -> Option<Vec<u8>> {
        if self.has_private_key() {

            let signature = ed25519::sign(data, &self.private_key.as_ref().unwrap());
            Some(signature)

        } else {
            None
        }
    }

    pub fn sign_with_master(&mut self, master_private_key: &Vec<u8>) {
        let bytes = self.as_bytes();
        let hash = ed25519::sign(&bytes, master_private_key);
        self.signature = Some(Signature::new_without_parent(hash));
    }

    /// This method verifies that the given signature is valid for the given data
    pub fn verify(&self, data: &[u8], _: usize, signature: &Vec<u8>) -> bool {
        let result = ed25519::verify(data, &signature, &self.public_key);
        result
    }

    pub fn as_bytes(&self) -> [u8; CERTIFICATE_BYTE_LEN] {
        let mut bytes = [0; CERTIFICATE_BYTE_LEN];

        self.meta.fill_bytes(&mut bytes[0..64]);
        copy_bytes(&mut bytes[64..],
                   self.expires.as_bytes(),
                   0,
                   0,
                   25);
        copy_bytes(&mut bytes[89..], &*self.public_key, 0, 0, PUBLIC_KEY_LEN);

        bytes
    }

    pub fn get_parent(&self) -> Option<&Certificate> {
        if self.signature.is_some() {
            let sig = &self.signature.as_ref().unwrap();
            sig.get_parent()
        } else {
            None
        }
    }

    /// This method verifies that this certificate is valid by analyzing the trust chain
    pub fn is_valid(&self, master_pk: &Vec<u8>) -> Result<(), &'static str> {
        if !self.is_signed() {
            Err("This certificate isn't signed, so it can't be valid.")
        } else {
            let bytes: [u8; CERTIFICATE_BYTE_LEN] = self.as_bytes();

            let signature = self.signature.as_ref().expect("lel");

            if signature.is_signed_by_master() {

                let r = ed25519::verify(&bytes, signature.get_hash(), master_pk);

                if r {

                    // FIXME: hier expires checken

                    Ok(())
                } else {
                    Err("Failed to verify master signature")
                }

            } else {
                let parent: &Certificate = signature.get_parent().unwrap();
                let sign_real = parent.verify(&bytes, CERTIFICATE_BYTE_LEN, &signature.get_hash());
                let parent_real = parent.is_valid(&master_pk).is_ok();

                if sign_real {
                    if parent_real {

                        let expires = match chrono::DateTime::parse_from_rfc3339(&self.expires) {
                        	Err(_) => return Err("Failed to parse expiration time"),
                        	Ok(expires) => expires.with_timezone(&chrono::UTC),
                        };

                        if expires > chrono::UTC::now() {
                        	Ok(())
						} else {
							Err("The certificate is expired")
						}
                    } else {
                        Err("The parent is invalid.")
                    }
                } else {
                    Err("The signature of the parent isn invalid.")
                }
            }
        }
    }

    /// This method generates a random public/private keypair and a certificate for it
    pub fn generate_random(meta: Meta, expires: chrono::DateTime<chrono::UTC>) -> Certificate {

        let (public_key, private_key) = ed25519::generate_keypair();

        Certificate {
            private_key: Some(private_key),
            public_key: public_key,
            expires: expires.to_rfc3339(),
            meta: meta,
            signature: None,
        }
    }

    pub fn as_json(&self) -> Vec<u8> {
    	let jsoncode = json::encode(self).expect("Failed to encode certificate");
		let mut compressed = lzma::compress(&jsoncode.as_bytes(), 6).expect("failed to compress");
		let magic = "edcert".as_bytes();
		copy_bytes(&mut compressed[0..6], magic, 0, 0, 6);
		compressed
    }

    /// Saves this certificate into a folder: one file for the certificate and one file for the private key
    pub fn save(&self, folder: &str) {
        use std::fs::File;
        use std::fs::DirBuilder;
        use std::fs::metadata;
        use std::io::Write;

        let folder: String = folder.to_string();

        if metadata(&folder).is_err() {
            DirBuilder::new().create(&folder).expect("Failed to create folder");
        }

        if self.has_private_key() {
            let mut private_keyfile: File = File::create(folder.clone() + "/private.key")
                                                .expect("Failed to create private key file.");
            let bytes: &[u8] = self.private_key.as_ref().unwrap();
            private_keyfile.write_all(bytes).expect("Failed to write private key file.");
        }

        let folder: String = folder.to_string();
        let mut certificate_file: File = File::create(folder + "/certificate.ec")
                                             .expect("Failed to create certificate file.");

		let compressed = self.as_json();
        certificate_file.write(&*compressed)
                        .expect("Failed to write certificate file.");
    }

	pub fn load(compressed : &[u8]) -> Result<Certificate, &'static str> {

		let mut bytes : Vec<u8> = Vec::new();
		let magic : [u8; 6] = [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00];
		bytes.extend(compressed);
		copy_bytes(&mut bytes[0..7], &magic,0,0,6);

		let o = lzma::decompress(&bytes[..]);
		if o.is_err() {
			return Err("Failed to decompress certificate");
		}

		let o = String::from_utf8(o.unwrap());
		if o.is_err() {
			return Err("Failed to read UTF8 from decompressed vector");
		}

        let o = json::decode(&o.unwrap());
        if o.is_err() {
        	Err("Failed to decode JSON")
        }
        else
        {
        	Ok(o.unwrap())
        }
	}

    /// This method loads a certificate from a folder
    pub fn load_from_folder(folder: &str) -> Result<Certificate, &'static str> {

        use std::fs::File;
        // use std::fs::DirBuilder;
        use std::io::Read;

        let folder: String = folder.to_string();
        let mut certificate_file: File = File::open(folder + "/certificate.ec")
                                             .expect("Failed to open certificate file.");
        let mut compressed = Vec::new();
        certificate_file.read_to_end(&mut compressed).expect("Failed to read certificate");
		Certificate::load(&*compressed)
    }

    /// This method signs another certificate with the private key of this certificate
    pub fn sign_certificate(&self, other: &mut Certificate) -> Result<(), &'static str> {

        if self.has_private_key() {
            let child_bytes = other.as_bytes();
            let signature_bytes = self.sign(&child_bytes).unwrap().to_vec();
            let parent = Box::new(self.clone());
            let signature = Signature::new(parent, signature_bytes);

            other.signature = Some(signature);

            Ok(())
        } else {
            Err("This certificate has no private key")
        }
    }
}

/// This is a simple copy function. This should be replaced by memcpy or something...
fn copy_bytes(dest: &mut [u8], src: &[u8], start_dest: usize, start_src: usize, len: usize) {
    for i in 0..len {
        dest[start_dest + i] = src[start_src + i];
    }
}

#[test]
fn test_generate_certificate() {

	use chrono::Timelike;
	use time::Duration;

	let meta = Meta::new_empty();
    let expires = UTC::now()
                  .checked_add(Duration::days(90))
                  .expect("Fehler: Ein Tag konnte nicht auf heute addiert werden.")
                  .with_nanosecond(0)
                  .unwrap();

	let a = Certificate::generate_random(meta, expires);

	let meta = Meta::new_empty();

	let b = Certificate::generate_random(meta, expires);

	assert!(a.get_public_key() != b.get_public_key());
}

#[test]
fn test_all() {

	use chrono::Timelike;
	use time::Duration;

	let mut meta_parent = Meta::new_empty();
    meta_parent.set("name", "Amke Root Certificate");
    meta_parent.set("use-for", "[amke.certificate-signing]");
    let meta_parent = meta_parent;

    let mut meta_child = Meta::new_empty();
    meta_child.set("name", "Amke Rombie Root Certificate");
    meta_child.set("use-for", "[amke.certificate-signing, amke.rombie.*]");
    let meta_child = meta_child;

    let expires = UTC::now()
                      .checked_add(Duration::days(90))
                      .expect("Fehler: Ein Tag konnte nicht auf heute addiert werden.")
                      .with_nanosecond(0)
                      .unwrap();

    let (master_pk, master_sk) = ed25519::generate_keypair();

    let mut child = Certificate::generate_random(meta_child, expires);
    let mut parent = Certificate::generate_random(meta_parent, expires);

    parent.sign_with_master(&master_sk);

    parent.sign_certificate(&mut child).expect("Failed to sign child!");

    let time_str = UTC::now().with_nanosecond(0).unwrap().to_rfc3339();

    println!("Ist Child valid? {:?}", child.is_valid(&master_pk));

    child.save(&time_str);

    child = Certificate::load_from_folder(&time_str).expect("Failed to load certificate");

    println!("Ist Child nach laden noch valid? {:?}",
             child.is_valid(&master_pk));

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

use meta::Meta;
use signature::Signature;
use rustc_serialize::json;
use rustc_serialize::Encodable;
use rustc_serialize::Encoder;
use rustc_serialize::Decoder;
use chrono;
use ed25519;
use lzma;
use chrono::UTC;

/// This is the amount of bytes a single ed25519 signature takes up
pub const SIGNATURE_LEN: usize = 64 + CERTIFICATE_BYTE_LEN;

/// This is the amount of bytes a single key takes up.
pub const PRIVATE_KEY_LEN: usize = 64;
pub const PUBLIC_KEY_LEN: usize = 32;

pub const CERTIFICATE_BYTE_LEN: usize =
    25 /* expires as string */ + 64 /* hash of meta */ + PUBLIC_KEY_LEN;

#[derive(Clone,RustcDecodable,RustcEncodable,Debug)]
pub struct Certificate {
    /// The meta element contains data associated with the certificate
    /// Common data is "use-for" which contains a list of permissions
    meta: Meta,

    /// the public key of this certificate
    public_key: Vec<u8>,

    /// the private key, if it is known
    private_key: Option<Vec<u8>>,

    /// a timestamp when this certificate expires
    expires: String,

    /// a signature for trust-chaining certificates
    /// if the certificate is not signed yet, this is None
    signature: Option<Signature>,
}

impl Certificate {
    /// This method generates a random public/private keypair and a certificate for it
    pub fn generate_random(meta: Meta, expires: chrono::DateTime<chrono::UTC>) -> Certificate {

        let (public_key, private_key) = ed25519::generate_keypair();

        Certificate {
            private_key: Some(private_key),
            public_key: public_key,
            expires: expires.to_rfc3339(),
            meta: meta,
            signature: None,
        }
    }

    /// This method returns a mutable reference to the meta structure
    pub fn get_meta_mut(&mut self) -> &mut Meta {
        &mut self.meta
    }

    /// This method returns a reference to the meta structure
    pub fn get_meta(&self) -> &Meta {
        &self.meta
    }

    /// This method returns a reference to the public key
    pub fn get_public_key(&self) -> &Vec<u8> {
        &self.public_key
    }

    /// This method returns the private key, if it is known, or None if the certificate has been initialized without the private key
    pub fn get_private_key(&self) -> &Option<Vec<u8>> {
        &self.private_key
    }

    /// This method returns true, if the private key is saved in the certificate
    pub fn has_private_key(&self) -> bool {
        self.private_key.is_some()
    }

    /// This method returns the expiration date as a RFC 3339 string
    pub fn get_expires(&self) -> &str {
        &self.expires
    }

    /// This method replaces the current private key of this certificate with the given one
    pub fn set_private_key(&mut self, private_key: Vec<u8>) {
        self.private_key = Some(private_key);
    }

    /// This method checks, if this certificates expiration date is now or in the past
    pub fn is_expired(&self) -> bool {
        let expires = match chrono::DateTime::parse_from_rfc3339(&self.expires) {
            Err(_) => return true,
            Ok(expires) => expires.with_timezone(&chrono::UTC),
        };

        if expires > chrono::UTC::now() {
            false
        } else {
            true
        }
    }

    /// This method returns a "hash". This is used to validate the certificate.
    /// All relevant information of the certificate is used to produce the hash,
    /// including the public key, meta data and the expiration date.
    pub fn safehash(&self) -> [u8; CERTIFICATE_BYTE_LEN] {
        let mut bytes = [0; CERTIFICATE_BYTE_LEN];

        self.meta.fill_bytes(&mut bytes[0..64]);
        copy_bytes(&mut bytes[64..], self.expires.as_bytes(), 0, 0, 25);
        copy_bytes(&mut bytes[89..], &*self.public_key, 0, 0, PUBLIC_KEY_LEN);

        bytes
    }

    /// This method returns the parent certificate of this certificate, if it exists
    pub fn get_parent(&self) -> Option<&Certificate> {
        if self.signature.is_some() {
            let sig = &self.signature.as_ref().unwrap();
            sig.get_parent()
        } else {
            None
        }
    }

    /// This method returns true, if a signature exists (is not None). This doesn't validate the signature
    pub fn is_signed(&self) -> bool {
        self.signature.is_some()
    }

    /// This method signs the given data and returns the signature
    pub fn sign(&self, data: &[u8]) -> Option<Vec<u8>> {
        if self.has_private_key() {

            let signature = ed25519::sign(data, &self.private_key.as_ref().unwrap());
            Some(signature)

        } else {
            None
        }
    }

    /// This method signs this certificate with the given private master key
    pub fn sign_with_master(&mut self, master_private_key: &Vec<u8>) {
        let bytes = self.safehash();
        let hash = ed25519::sign(&bytes, master_private_key);
        self.signature = Some(Signature::new_without_parent(hash));
    }

    /// This method signs another certificate with the private key of this certificate
    pub fn sign_certificate(&self, other: &mut Certificate) -> Result<(), &'static str> {

        if self.has_private_key() {
            let child_bytes = other.safehash();
            let signature_bytes = self.sign(&child_bytes).unwrap().to_vec();
            let parent = Box::new(self.clone());
            let signature = Signature::new(parent, signature_bytes);

            other.signature = Some(signature);

            Ok(())
        } else {
            Err("This certificate has no private key")
        }
    }

    /// This method verifies that this certificate is valid by analyzing the trust chain
    pub fn is_valid(&self, master_pk: &Vec<u8>) -> Result<(), &'static str> {
        if !self.is_signed() {
            Err("This certificate isn't signed, so it can't be valid.")
        } else {
            let bytes: [u8; CERTIFICATE_BYTE_LEN] = self.safehash();

            let signature = self.signature.as_ref().expect("lel");

            if signature.is_signed_by_master() {

                let r = ed25519::verify(&bytes, signature.get_hash(), master_pk);

                if r {

                    if self.is_expired() {
                        Err("This certificate is expired")
                    } else {
                        Ok(())
                    }
                } else {
                    Err("Failed to verify master signature")
                }

            } else {
                let parent: &Certificate = signature.get_parent().unwrap();
                let sign_real = parent.verify(&bytes, CERTIFICATE_BYTE_LEN, &signature.get_hash());
                let parent_real = parent.is_valid(&master_pk).is_ok();

                if sign_real {
                    if parent_real {
                        if !self.is_expired() {
                            Ok(())
                        } else {
                            Err("The certificate is expired")
                        }
                    } else {
                        Err("The parent is invalid.")
                    }
                } else {
                    Err("The signature of the parent isn invalid.")
                }
            }
        }
    }

    /// This method verifies that the given signature is valid for the given data
    pub fn verify(&self, data: &[u8], _: usize, signature: &Vec<u8>) -> bool {
        let result = ed25519::verify(data, &signature, &self.public_key);
        result
    }

    /// takes a json-encoded byte vector and tries to create a certificate from it
    pub fn from_json(compressed: &[u8]) -> Result<Certificate, &'static str> {

        let mut bytes: Vec<u8> = Vec::new();
        let magic: [u8; 6] = [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00];
        bytes.extend(compressed);
        copy_bytes(&mut bytes[0..7], &magic, 0, 0, 6);

        let o = lzma::decompress(&bytes[..]);
        if o.is_err() {
            return Err("Failed to decompress certificate");
        }

        let o = String::from_utf8(o.unwrap());
        if o.is_err() {
            return Err("Failed to read UTF8 from decompressed vector");
        }

        let o = json::decode(&o.unwrap());
        if o.is_err() {
            Err("Failed to decode JSON")
        } else {
            Ok(o.unwrap())
        }
    }

    /// Converts this certificate in a json-encoded byte vector
    pub fn as_json(&self) -> Vec<u8> {
        let jsoncode = json::encode(self).expect("Failed to encode certificate");
        let mut compressed = lzma::compress(&jsoncode.as_bytes(), 6).expect("failed to compress");
        let magic = "edcert".as_bytes();
        copy_bytes(&mut compressed[0..6], magic, 0, 0, 6);
        compressed
    }

    /// Saves this certificate into a folder: one file for the certificate and one file for the private key
    pub fn save(&self, folder: &str) {
        use std::fs::File;
        use std::fs::DirBuilder;
        use std::fs::metadata;
        use std::io::Write;

        let folder: String = folder.to_string();

        if metadata(&folder).is_err() {
            DirBuilder::new().create(&folder).expect("Failed to create folder");
        }

        if self.has_private_key() {
            let mut private_keyfile: File = File::create(folder.clone() + "/private.key")
                                                .expect("Failed to create private key file.");
            let bytes: &[u8] = self.private_key.as_ref().unwrap();
            private_keyfile.write_all(bytes).expect("Failed to write private key file.");
        }

        let folder: String = folder.to_string();
        let mut certificate_file: File = File::create(folder + "/certificate.ec")
                                             .expect("Failed to create certificate file.");

        let compressed = self.as_json();
        certificate_file.write(&*compressed)
                        .expect("Failed to write certificate file.");
    }

    /// This method loads a certificate from a folder
    pub fn load_from_file(filename: &str) -> Result<Certificate, &'static str> {

        use std::fs::File;
        use std::io::Read;

        let filename: String = filename.to_string();
        let mut certificate_file: File = File::open(filename)
                                             .expect("Failed to open certificate file.");
        let mut compressed = Vec::new();
        certificate_file.read_to_end(&mut compressed).expect("Failed to read certificate");
        Certificate::from_json(&*compressed)
    }

    /// This method reads a privtae key from a file and sets it in this certificate
    pub fn load_private_key(&mut self, filename: &str) -> Result<(), &'static str> {
        use std::fs::File;
        use std::io::Read;

        let filename: String = filename.to_string();
        let mut private_key_file: File = File::open(filename)
                                             .expect("Failed to open private kye file.");
        let mut private_key = Vec::new();
        private_key_file.read_to_end(&mut private_key).expect("Failed to read private key");
        self.set_private_key(private_key);
        Ok(())
    }
}

/// This is a simple copy function. This should be replaced by memcpy or something...
fn copy_bytes(dest: &mut [u8], src: &[u8], start_dest: usize, start_src: usize, len: usize) {
    for i in 0..len {
        dest[start_dest + i] = src[start_src + i];
    }
}

#[test]
fn test_generate_certificate() {
    use chrono::Timelike;
    use time::Duration;

    let meta = Meta::new_empty();
    let expires = UTC::now()
                      .checked_add(Duration::days(90))
                      .expect("Fehler: Ein Tag konnte nicht auf heute addiert werden.")
                      .with_nanosecond(0)
                      .unwrap();

    let a = Certificate::generate_random(meta, expires);

    let meta = Meta::new_empty();

    let b = Certificate::generate_random(meta, expires);

    assert!(a.get_public_key() != b.get_public_key());
}

#[test]
fn test_all() {

    use chrono::Timelike;
    use time::Duration;

    let mut meta_parent = Meta::new_empty();
    meta_parent.set("name", "Amke Root Certificate");
    meta_parent.set("use-for", "[amke.certificate-signing]");
    let meta_parent = meta_parent;

    let mut meta_child = Meta::new_empty();
    meta_child.set("name", "Amke Rombie Root Certificate");
    meta_child.set("use-for", "[amke.certificate-signing, amke.rombie.*]");
    let meta_child = meta_child;

    let expires = UTC::now()
                      .checked_add(Duration::days(90))
                      .expect("Fehler: Ein Tag konnte nicht auf heute addiert werden.")
                      .with_nanosecond(0)
                      .unwrap();

    let (master_pk, master_sk) = ed25519::generate_keypair();

    let mut child = Certificate::generate_random(meta_child, expires);
    let mut parent = Certificate::generate_random(meta_parent, expires);

    parent.sign_with_master(&master_sk);

    parent.sign_certificate(&mut child).expect("Failed to sign child!");

    let time_str: String = UTC::now().with_nanosecond(0).unwrap().to_rfc3339();

    let certfilename = time_str.clone() + "/certificate.ec";
    let prvkeyfilename = time_str.clone() + "/private.key";

    assert!(child.is_valid(&master_pk).is_ok());

    child.save(&time_str);

    child = Certificate::load_from_file(&certfilename).expect("Failed to load certificate");
    child.load_private_key(&prvkeyfilename).expect("Failed to load private key");

    assert!(child.is_valid(&master_pk).is_ok());

    child.save(&time_str);
}
<|endoftext|>


<commit_before>//! Thread-safe connections on IrcStreams.
#![stable]
#[cfg(feature = "ssl")] use std::borrow::ToOwned;
#[cfg(feature = "ssl")] use std::error::Error;
use std::old_io::{BufferedReader, BufferedWriter, IoResult, TcpStream};
#[cfg(any(feature = "encode", feature = "ssl"))] use std::old_io::{IoError, IoErrorKind};
use std::sync::{Mutex, MutexGuard};
#[cfg(feature = "encode")] use encoding::{DecoderTrap, EncoderTrap, Encoding};
#[cfg(feature = "encode")] use encoding::label::encoding_from_whatwg_label;
use client::data::kinds::{IrcReader, IrcWriter};
use client::data::message::ToMessage;
#[cfg(feature = "ssl")] use openssl::ssl::{SslContext, SslMethod, SslStream};
#[cfg(feature = "ssl")] use openssl::ssl::error::SslError;

/// A thread-safe connection.
#[stable]
pub struct Connection<T: IrcReader, U: IrcWriter> {
    reader: Mutex<T>,
    writer: Mutex<U>,
}

/// A Connection over a buffered NetStream.
#[stable]
pub type NetConnection = Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>>;
/// An internal type
type NetReaderWriterPair = (BufferedReader<NetStream>, BufferedWriter<NetStream>);

#[stable]
impl Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>> {
    /// Creates a thread-safe TCP connection to the specified server.
    #[stable]
    pub fn connect(host: &str, port: u16) -> IoResult<NetConnection> {
        let (reader, writer) = try!(Connection::connect_internal(host, port));
        Ok(Connection::new(reader, writer))
    }

    /// connects to the specified server and returns a reader-writer pair.
    fn connect_internal(host: &str, port: u16) -> IoResult<NetReaderWriterPair> {
        let socket = try!(TcpStream::connect(&format!("{}:{}", host, port)[..]));
        Ok((BufferedReader::new(NetStream::UnsecuredTcpStream(socket.clone())),
            BufferedWriter::new(NetStream::UnsecuredTcpStream(socket))))
    }

    /// Creates a thread-safe TCP connection to the specified server over SSL.
    /// If the library is compiled without SSL support, this method panics.
    #[stable]
    pub fn connect_ssl(host: &str, port: u16) -> IoResult<NetConnection> {
        let (reader, writer) = try!(Connection::connect_ssl_internal(host, port));
        Ok(Connection::new(reader, writer))
    }

    /// Connects over SSL to the specified server and returns a reader-writer pair.
    #[cfg(feature = "ssl")]
    fn connect_ssl_internal(host: &str, port: u16) -> IoResult<NetReaderWriterPair> {
        let socket = try!(TcpStream::connect(&format!("{}:{}", host, port)[..]));
        let ssl = try!(ssl_to_io(SslContext::new(SslMethod::Tlsv1)));
        let ssl_socket = try!(ssl_to_io(SslStream::new(&ssl, socket)));
        Ok((BufferedReader::new(NetStream::SslTcpStream(ssl_socket.clone())),
            BufferedWriter::new(NetStream::SslTcpStream(ssl_socket))))
    }

    /// Panics because SSL support is not compiled in.
    #[cfg(not(feature = "ssl"))]
    fn connect_ssl_internal(host: &str, port: u16) -> IoResult<NetReaderWriterPair> {
        panic!("Cannot connect to {}:{} over SSL without compiling with SSL support.", host, port)
    }

    /// Reconnects to the specified server, dropping the current connection.
    #[stable]
    pub fn reconnect(&self, host: &str, port: u16) -> IoResult<()> {
        let use_ssl = match self.reader.lock().unwrap().get_ref() {
            &NetStream::UnsecuredTcpStream(_) =>  false,
            #[cfg(feature = "ssl")]
            &NetStream::SslTcpStream(_) => true,
        };
        let (reader, writer) = if use_ssl {
            try!(Connection::connect_ssl_internal(host, port))
        } else {
            try!(Connection::connect_internal(host, port))
        };
        *self.reader.lock().unwrap() = reader;
        *self.writer.lock().unwrap() = writer;
        Ok(())
    }

    /// Sets the keepalive for the network stream.
    #[unstable = "Rust IO has not stabilized."]
    pub fn set_keepalive(&self, delay_in_seconds: Option<usize>) -> IoResult<()> {
        self.mod_stream(|tcp| tcp.set_keepalive(delay_in_seconds))
    }

    /// Sets the timeout for the network stream.
    #[unstable = "Rust IO has not stabilized."]
    pub fn set_timeout(&self, timeout_ms: Option<u64>) {
        self.mod_stream(|tcp| Ok(tcp.set_timeout(timeout_ms))).unwrap(); // this cannot fail.
    }

    /// Modifies the internal TcpStream using a function.
    fn mod_stream<F>(&self, f: F) -> IoResult<()> where F: FnOnce(&mut TcpStream) -> IoResult<()> {
        match self.reader.lock().unwrap().get_mut() {
            &mut NetStream::UnsecuredTcpStream(ref mut tcp) => f(tcp),
            #[cfg(feature = "ssl")]
            &mut NetStream::SslTcpStream(ref mut ssl) => f(ssl.get_mut()),
        }
    }
}

#[stable]
impl<T: IrcReader, U: IrcWriter> Connection<T, U> {
    /// Creates a new connection from an IrcReader and an IrcWriter.
    #[stable]
    pub fn new(reader: T, writer: U) -> Connection<T, U> {
        Connection {
            reader: Mutex::new(reader),
            writer: Mutex::new(writer),
        }
    }

    /// Sends a Message over this connection.
    #[stable]
    #[cfg(feature = "encode")]
    pub fn send<M: ToMessage>(&self, to_msg: M, encoding: &str) -> IoResult<()> {
        let encoding = match encoding_from_whatwg_label(encoding) {
            Some(enc) => enc,
            None => return Err(IoError {
                kind: IoErrorKind::InvalidInput,
                desc: "Failed to find decoder.",
                detail: Some(format!("Invalid decoder: {}", encoding))
            })
        };
        let msg = to_msg.to_message();
        let data = match encoding.encode(&msg.into_string(), EncoderTrap::Replace) {
            Ok(data) => data,
            Err(data) => return Err(IoError {
                kind: IoErrorKind::InvalidInput,
                desc: "Failed to decode message.",
                detail: Some(format!("Failed to decode {} as {}.", data, encoding.name())),
            })
        };
        let mut writer = self.writer.lock().unwrap();
        try!(writer.write_all(&data));
        writer.flush()
    }

    /// Sends a message over this connection.
    #[stable]
    #[cfg(not(feature = "encode"))]
    pub fn send<M: ToMessage>(&self, to_msg: M) -> IoResult<()> {
        let mut writer = self.writer.lock().unwrap();
        try!(writer.write_str(&to_msg.to_message().into_string()[]));
        writer.flush()
    }

    /// Receives a single line from this connection.
    #[stable]
    #[cfg(feature = "encoding")]
    pub fn recv(&self, encoding: &str) -> IoResult<String> {
        let encoding = match encoding_from_whatwg_label(encoding) {
            Some(enc) => enc,
            None => return Err(IoError {
                kind: IoErrorKind::InvalidInput,
                desc: "Failed to find decoder.",
                detail: Some(format!("Invalid decoder: {}", encoding))
            })
        };
        self.reader.lock().unwrap().read_until(b'\n').and_then(|line|
            match encoding.decode(&line, DecoderTrap::Replace) {
                Ok(data) => Ok(data),
                Err(data) => Err(IoError {
                    kind: IoErrorKind::InvalidInput,
                    desc: "Failed to decode message.",
                    detail: Some(format!("Failed to decode {} as {}.", data, encoding.name())),
                })
            }
        )
    }

    /// Receives a single line from this connection.
    #[stable]
    #[cfg(not(feature = "encoding"))]
    pub fn recv(&self) -> IoResult<String> {
        self.reader.lock().unwrap().read_line()
    }

    /// Acquires the Reader lock.
    #[stable]
    pub fn reader<'a>(&'a self) -> MutexGuard<'a, T> {
        self.reader.lock().unwrap()
    }

    /// Acquires the Writer lock.
    #[stable]
    pub fn writer<'a>(&'a self) -> MutexGuard<'a, U> {
        self.writer.lock().unwrap()
    }
}

/// Converts a Result<T, SslError> into an IoResult<T>.
#[cfg(feature = "ssl")]
fn ssl_to_io<T>(res: Result<T, SslError>) -> IoResult<T> {
    match res {
        Ok(x) => Ok(x),
        Err(e) => Err(IoError {
            kind: IoErrorKind::OtherIoError,
            desc: "An SSL error occurred.",
            detail: Some(e.description().to_owned()),
        }),
    }
}

/// An abstraction over different networked streams.
#[stable]
pub enum NetStream {
    /// An unsecured TcpStream.
    #[stable]
    UnsecuredTcpStream(TcpStream),
    /// An SSL-secured TcpStream.
    /// This is only available when compiled with SSL support.
    #[cfg(feature = "ssl")]
    #[stable]
    SslTcpStream(SslStream<TcpStream>),
}

impl Reader for NetStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        match self {
            &mut NetStream::UnsecuredTcpStream(ref mut stream) => stream.read(buf),
            #[cfg(feature = "ssl")]
            &mut NetStream::SslTcpStream(ref mut stream) => stream.read(buf),
        }
    }
}

impl Writer for NetStream {
    fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
        match self {
            &mut NetStream::UnsecuredTcpStream(ref mut stream) => stream.write_all(buf),
            #[cfg(feature = "ssl")]
            &mut NetStream::SslTcpStream(ref mut stream) => stream.write_all(buf),
        }
    }
}

#[cfg(test)]
mod test {
    use super::Connection;
    use std::old_io::{MemReader, MemWriter};
    use std::old_io::util::{NullReader, NullWriter};
    use client::data::message::Message;
    #[cfg(feature = "encode")] use encoding::{DecoderTrap, Encoding};
    #[cfg(feature = "encode")] use encoding::all::{ISO_8859_15, UTF_8};

    #[test]
    #[cfg(not(feature = "encode"))]
    fn send() {
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(
            Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("Testing!"))
        ).is_ok());
        let data = String::from_utf8(conn.writer().get_ref().to_vec()).unwrap();
        assert_eq!(&data[..], "PRIVMSG test :Testing!\r\n");
    }

    #[test]
    #[cfg(not(feature = "encode"))]
    fn send_str() {
        let exp = "PRIVMSG test :Testing!\r\n";
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(exp).is_ok());
        let data = String::from_utf8(conn.writer().get_ref().to_vec()).unwrap();
        assert_eq!(&data[..], exp);
    }

    #[test]
    #[cfg(feature = "encode")]
    fn send_utf8() {
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(
            Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("€ŠšŽžŒœŸ")), "UTF-8"
        ).is_ok());
        let data = UTF_8.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
        assert_eq!(&data[..], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
    }

    #[test]
    #[cfg(feature = "encode")]
    fn send_utf8_str() {
        let exp = "PRIVMSG test :€ŠšŽžŒœŸ\r\n";
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(exp, "UTF-8").is_ok());
        let data = UTF_8.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
        assert_eq!(&data[..], exp);
    }

    #[test]
    #[cfg(feature = "encode")]
    fn send_iso885915() {
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(
            Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("€ŠšŽžŒœŸ")), "l9"
        ).is_ok());
        let data = ISO_8859_15.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
        assert_eq!(&data[..], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
    }

    #[test]
    #[cfg(feature = "encode")]
    fn send_iso885915_str() {
        let exp = "PRIVMSG test :€ŠšŽžŒœŸ\r\n";
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(exp, "l9").is_ok());
        let data = ISO_8859_15.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
        assert_eq!(&data[..], exp);
    }

    #[test]
    #[cfg(not(feature = "encode"))]
    fn recv() {
        let conn = Connection::new(
            MemReader::new("PRIVMSG test :Testing!\r\n".as_bytes().to_vec()), NullWriter
        );
        assert_eq!(&conn.recv().unwrap()[..], "PRIVMSG test :Testing!\r\n");
    }

    #[test]
    #[cfg(feature = "encode")]
    fn recv_utf8() {
        let conn = Connection::new(
            MemReader::new(b"PRIVMSG test :Testing!\r\n".to_vec()), NullWriter
        );
        assert_eq!(&conn.recv("UTF-8").unwrap()[..], "PRIVMSG test :Testing!\r\n");
    }

    #[test]
    #[cfg(feature = "encode")]
    fn recv_iso885915() {
        let conn = Connection::new(
            MemReader::new({
                let mut vec = Vec::new();
                vec.push_all(b"PRIVMSG test :");
                vec.push_all(&[0xA4, 0xA6, 0xA8, 0xB4, 0xB8, 0xBC, 0xBD, 0xBE]);
                vec.push_all(b"\r\n");
                vec
            }), NullWriter
        );
        assert_eq!(&conn.recv("l9").unwrap()[..], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
    }
}
<commit_msg>Removed warning when no-default-features is used.<commit_after>//! Thread-safe connections on IrcStreams.
#![stable]
#[cfg(feature = "ssl")] use std::borrow::ToOwned;
#[cfg(feature = "ssl")] use std::error::Error;
use std::old_io::{BufferedReader, BufferedWriter, IoResult, TcpStream};
#[cfg(any(feature = "encode", feature = "ssl"))] use std::old_io::{IoError, IoErrorKind};
use std::sync::{Mutex, MutexGuard};
#[cfg(feature = "encode")] use encoding::{DecoderTrap, EncoderTrap, Encoding};
#[cfg(feature = "encode")] use encoding::label::encoding_from_whatwg_label;
use client::data::kinds::{IrcReader, IrcWriter};
use client::data::message::ToMessage;
#[cfg(feature = "ssl")] use openssl::ssl::{SslContext, SslMethod, SslStream};
#[cfg(feature = "ssl")] use openssl::ssl::error::SslError;

/// A thread-safe connection.
#[stable]
pub struct Connection<T: IrcReader, U: IrcWriter> {
    reader: Mutex<T>,
    writer: Mutex<U>,
}

/// A Connection over a buffered NetStream.
#[stable]
pub type NetConnection = Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>>;
/// An internal type
type NetReaderWriterPair = (BufferedReader<NetStream>, BufferedWriter<NetStream>);

#[stable]
impl Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>> {
    /// Creates a thread-safe TCP connection to the specified server.
    #[stable]
    pub fn connect(host: &str, port: u16) -> IoResult<NetConnection> {
        let (reader, writer) = try!(Connection::connect_internal(host, port));
        Ok(Connection::new(reader, writer))
    }

    /// connects to the specified server and returns a reader-writer pair.
    fn connect_internal(host: &str, port: u16) -> IoResult<NetReaderWriterPair> {
        let socket = try!(TcpStream::connect(&format!("{}:{}", host, port)[..]));
        Ok((BufferedReader::new(NetStream::UnsecuredTcpStream(socket.clone())),
            BufferedWriter::new(NetStream::UnsecuredTcpStream(socket))))
    }

    /// Creates a thread-safe TCP connection to the specified server over SSL.
    /// If the library is compiled without SSL support, this method panics.
    #[stable]
    pub fn connect_ssl(host: &str, port: u16) -> IoResult<NetConnection> {
        let (reader, writer) = try!(Connection::connect_ssl_internal(host, port));
        Ok(Connection::new(reader, writer))
    }

    /// Connects over SSL to the specified server and returns a reader-writer pair.
    #[cfg(feature = "ssl")]
    fn connect_ssl_internal(host: &str, port: u16) -> IoResult<NetReaderWriterPair> {
        let socket = try!(TcpStream::connect(&format!("{}:{}", host, port)[..]));
        let ssl = try!(ssl_to_io(SslContext::new(SslMethod::Tlsv1)));
        let ssl_socket = try!(ssl_to_io(SslStream::new(&ssl, socket)));
        Ok((BufferedReader::new(NetStream::SslTcpStream(ssl_socket.clone())),
            BufferedWriter::new(NetStream::SslTcpStream(ssl_socket))))
    }

    /// Panics because SSL support is not compiled in.
    #[cfg(not(feature = "ssl"))]
    fn connect_ssl_internal(host: &str, port: u16) -> IoResult<NetReaderWriterPair> {
        panic!("Cannot connect to {}:{} over SSL without compiling with SSL support.", host, port)
    }

    /// Reconnects to the specified server, dropping the current connection.
    #[stable]
    pub fn reconnect(&self, host: &str, port: u16) -> IoResult<()> {
        let use_ssl = match self.reader.lock().unwrap().get_ref() {
            &NetStream::UnsecuredTcpStream(_) =>  false,
            #[cfg(feature = "ssl")]
            &NetStream::SslTcpStream(_) => true,
        };
        let (reader, writer) = if use_ssl {
            try!(Connection::connect_ssl_internal(host, port))
        } else {
            try!(Connection::connect_internal(host, port))
        };
        *self.reader.lock().unwrap() = reader;
        *self.writer.lock().unwrap() = writer;
        Ok(())
    }

    /// Sets the keepalive for the network stream.
    #[unstable = "Rust IO has not stabilized."]
    pub fn set_keepalive(&self, delay_in_seconds: Option<usize>) -> IoResult<()> {
        self.mod_stream(|tcp| tcp.set_keepalive(delay_in_seconds))
    }

    /// Sets the timeout for the network stream.
    #[unstable = "Rust IO has not stabilized."]
    pub fn set_timeout(&self, timeout_ms: Option<u64>) {
        self.mod_stream(|tcp| Ok(tcp.set_timeout(timeout_ms))).unwrap(); // this cannot fail.
    }

    /// Modifies the internal TcpStream using a function.
    fn mod_stream<F>(&self, f: F) -> IoResult<()> where F: FnOnce(&mut TcpStream) -> IoResult<()> {
        match self.reader.lock().unwrap().get_mut() {
            &mut NetStream::UnsecuredTcpStream(ref mut tcp) => f(tcp),
            #[cfg(feature = "ssl")]
            &mut NetStream::SslTcpStream(ref mut ssl) => f(ssl.get_mut()),
        }
    }
}

#[stable]
impl<T: IrcReader, U: IrcWriter> Connection<T, U> {
    /// Creates a new connection from an IrcReader and an IrcWriter.
    #[stable]
    pub fn new(reader: T, writer: U) -> Connection<T, U> {
        Connection {
            reader: Mutex::new(reader),
            writer: Mutex::new(writer),
        }
    }

    /// Sends a Message over this connection.
    #[stable]
    #[cfg(feature = "encode")]
    pub fn send<M: ToMessage>(&self, to_msg: M, encoding: &str) -> IoResult<()> {
        let encoding = match encoding_from_whatwg_label(encoding) {
            Some(enc) => enc,
            None => return Err(IoError {
                kind: IoErrorKind::InvalidInput,
                desc: "Failed to find decoder.",
                detail: Some(format!("Invalid decoder: {}", encoding))
            })
        };
        let msg = to_msg.to_message();
        let data = match encoding.encode(&msg.into_string(), EncoderTrap::Replace) {
            Ok(data) => data,
            Err(data) => return Err(IoError {
                kind: IoErrorKind::InvalidInput,
                desc: "Failed to decode message.",
                detail: Some(format!("Failed to decode {} as {}.", data, encoding.name())),
            })
        };
        let mut writer = self.writer.lock().unwrap();
        try!(writer.write_all(&data));
        writer.flush()
    }

    /// Sends a message over this connection.
    #[stable]
    #[cfg(not(feature = "encode"))]
    pub fn send<M: ToMessage>(&self, to_msg: M) -> IoResult<()> {
        let mut writer = self.writer.lock().unwrap();
        try!(writer.write_str(&to_msg.to_message().into_string()));
        writer.flush()
    }

    /// Receives a single line from this connection.
    #[stable]
    #[cfg(feature = "encoding")]
    pub fn recv(&self, encoding: &str) -> IoResult<String> {
        let encoding = match encoding_from_whatwg_label(encoding) {
            Some(enc) => enc,
            None => return Err(IoError {
                kind: IoErrorKind::InvalidInput,
                desc: "Failed to find decoder.",
                detail: Some(format!("Invalid decoder: {}", encoding))
            })
        };
        self.reader.lock().unwrap().read_until(b'\n').and_then(|line|
            match encoding.decode(&line, DecoderTrap::Replace) {
                Ok(data) => Ok(data),
                Err(data) => Err(IoError {
                    kind: IoErrorKind::InvalidInput,
                    desc: "Failed to decode message.",
                    detail: Some(format!("Failed to decode {} as {}.", data, encoding.name())),
                })
            }
        )
    }

    /// Receives a single line from this connection.
    #[stable]
    #[cfg(not(feature = "encoding"))]
    pub fn recv(&self) -> IoResult<String> {
        self.reader.lock().unwrap().read_line()
    }

    /// Acquires the Reader lock.
    #[stable]
    pub fn reader<'a>(&'a self) -> MutexGuard<'a, T> {
        self.reader.lock().unwrap()
    }

    /// Acquires the Writer lock.
    #[stable]
    pub fn writer<'a>(&'a self) -> MutexGuard<'a, U> {
        self.writer.lock().unwrap()
    }
}

/// Converts a Result<T, SslError> into an IoResult<T>.
#[cfg(feature = "ssl")]
fn ssl_to_io<T>(res: Result<T, SslError>) -> IoResult<T> {
    match res {
        Ok(x) => Ok(x),
        Err(e) => Err(IoError {
            kind: IoErrorKind::OtherIoError,
            desc: "An SSL error occurred.",
            detail: Some(e.description().to_owned()),
        }),
    }
}

/// An abstraction over different networked streams.
#[stable]
pub enum NetStream {
    /// An unsecured TcpStream.
    #[stable]
    UnsecuredTcpStream(TcpStream),
    /// An SSL-secured TcpStream.
    /// This is only available when compiled with SSL support.
    #[cfg(feature = "ssl")]
    #[stable]
    SslTcpStream(SslStream<TcpStream>),
}

impl Reader for NetStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        match self {
            &mut NetStream::UnsecuredTcpStream(ref mut stream) => stream.read(buf),
            #[cfg(feature = "ssl")]
            &mut NetStream::SslTcpStream(ref mut stream) => stream.read(buf),
        }
    }
}

impl Writer for NetStream {
    fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
        match self {
            &mut NetStream::UnsecuredTcpStream(ref mut stream) => stream.write_all(buf),
            #[cfg(feature = "ssl")]
            &mut NetStream::SslTcpStream(ref mut stream) => stream.write_all(buf),
        }
    }
}

#[cfg(test)]
mod test {
    use super::Connection;
    use std::old_io::{MemReader, MemWriter};
    use std::old_io::util::{NullReader, NullWriter};
    use client::data::message::Message;
    #[cfg(feature = "encode")] use encoding::{DecoderTrap, Encoding};
    #[cfg(feature = "encode")] use encoding::all::{ISO_8859_15, UTF_8};

    #[test]
    #[cfg(not(feature = "encode"))]
    fn send() {
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(
            Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("Testing!"))
        ).is_ok());
        let data = String::from_utf8(conn.writer().get_ref().to_vec()).unwrap();
        assert_eq!(&data[..], "PRIVMSG test :Testing!\r\n");
    }

    #[test]
    #[cfg(not(feature = "encode"))]
    fn send_str() {
        let exp = "PRIVMSG test :Testing!\r\n";
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(exp).is_ok());
        let data = String::from_utf8(conn.writer().get_ref().to_vec()).unwrap();
        assert_eq!(&data[..], exp);
    }

    #[test]
    #[cfg(feature = "encode")]
    fn send_utf8() {
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(
            Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("€ŠšŽžŒœŸ")), "UTF-8"
        ).is_ok());
        let data = UTF_8.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
        assert_eq!(&data[..], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
    }

    #[test]
    #[cfg(feature = "encode")]
    fn send_utf8_str() {
        let exp = "PRIVMSG test :€ŠšŽžŒœŸ\r\n";
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(exp, "UTF-8").is_ok());
        let data = UTF_8.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
        assert_eq!(&data[..], exp);
    }

    #[test]
    #[cfg(feature = "encode")]
    fn send_iso885915() {
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(
            Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("€ŠšŽžŒœŸ")), "l9"
        ).is_ok());
        let data = ISO_8859_15.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
        assert_eq!(&data[..], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
    }

    #[test]
    #[cfg(feature = "encode")]
    fn send_iso885915_str() {
        let exp = "PRIVMSG test :€ŠšŽžŒœŸ\r\n";
        let conn = Connection::new(NullReader, MemWriter::new());
        assert!(conn.send(exp, "l9").is_ok());
        let data = ISO_8859_15.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
        assert_eq!(&data[..], exp);
    }

    #[test]
    #[cfg(not(feature = "encode"))]
    fn recv() {
        let conn = Connection::new(
            MemReader::new("PRIVMSG test :Testing!\r\n".as_bytes().to_vec()), NullWriter
        );
        assert_eq!(&conn.recv().unwrap()[..], "PRIVMSG test :Testing!\r\n");
    }

    #[test]
    #[cfg(feature = "encode")]
    fn recv_utf8() {
        let conn = Connection::new(
            MemReader::new(b"PRIVMSG test :Testing!\r\n".to_vec()), NullWriter
        );
        assert_eq!(&conn.recv("UTF-8").unwrap()[..], "PRIVMSG test :Testing!\r\n");
    }

    #[test]
    #[cfg(feature = "encode")]
    fn recv_iso885915() {
        let conn = Connection::new(
            MemReader::new({
                let mut vec = Vec::new();
                vec.push_all(b"PRIVMSG test :");
                vec.push_all(&[0xA4, 0xA6, 0xA8, 0xB4, 0xB8, 0xBC, 0xBD, 0xBE]);
                vec.push_all(b"\r\n");
                vec
            }), NullWriter
        );
        assert_eq!(&conn.recv("l9").unwrap()[..], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
    }
}
<|endoftext|>


<commit_before>#![cfg(target_os = "linux")]

mod common;

use std::fs;
use std::mem::size_of;
use std::path::Path;
use std::thread;
use std::time::Duration;

use rand::Rng;

use sled::Config;

const N_TESTS: usize = 100;
const CYCLE: usize = 256;
const BATCH_SIZE: u32 = 8;

/// Verifies that the keys in the tree are correctly recovered.
/// Panics if they are incorrect.
/// Returns the key that should be resumed at, and the current cycle value.
fn verify(tree: &sled::Tree) -> (u32, u32) {
    // key 0 should always be the highest value, as that's where we increment
    // at some point, it might go down by one
    // it should never return, or go down again after that
    let mut iter = tree.iter();
    let highest = match iter.next() {
        Some(Ok((_k, v))) => slice_to_u32(&*v),
        Some(Err(e)) => panic!("{:?}", e),
        None => return (0, 0),
    };

    let highest_vec = u32_to_vec(highest);

    // find how far we got
    let mut contiguous: u32 = 0;
    let mut lowest = 0;
    for res in iter {
        let (_k, v) = res.unwrap();
        if &v[..4] == &highest_vec[..4] {
            contiguous += 1;
        } else {
            let expected = if highest == 0 {
                CYCLE as u32 - 1
            } else {
                (highest - 1) % CYCLE as u32
            };
            let actual = slice_to_u32(&*v);
            assert_eq!(expected, actual);
            lowest = actual;
            break;
        }
    }

    // ensure nothing changes after this point
    let low_beginning = u32_to_vec(contiguous + 1);

    for res in tree.range(&*low_beginning..) {
        let (k, v): (sled::IVec, _) = res.unwrap();
        assert_eq!(
            slice_to_u32(&*v),
            lowest,
            "expected key {} to have value {}, instead it had value {} in db: {:?}",
            slice_to_u32(&*k),
            lowest,
            slice_to_u32(&*v),
            tree
        );
    }

    (contiguous, highest)
}

/// Verifies that the keys in the tree are correctly recovered (i.e., equal).
/// Panics if they are incorrect.
fn verify_batches(tree: &sled::Tree) -> u32 {
    let mut iter = tree.iter();
    let first_value = match iter.next() {
        Some(Ok((_k, v))) => slice_to_u32(&*v),
        Some(Err(e)) => panic!("{:?}", e),
        None => return 0,
    };
    for key in 0..BATCH_SIZE {
        let res = tree.get(u32_to_vec(key));
        let option = res.unwrap();
        let v = match option {
            Some(v) => v,
            None => panic!(
                "expected key {} to have a value, instead it was missing in db: {:?}",
                key,
                tree
            ),
        };
        let value = slice_to_u32(&*v);
        assert_eq!(
            first_value,
            value,
            "expected key {} to have value {}, instead it had value {} in db: {:?}",
            key,
            first_value,
            value,
            tree
        );
    }

    first_value
}

fn u32_to_vec(u: u32) -> Vec<u8> {
    let buf: [u8; size_of::<u32>()] = u.to_be_bytes();
    buf.to_vec()
}

fn slice_to_u32(b: &[u8]) -> u32 {
    let mut buf = [0u8; size_of::<u32>()];
    buf.copy_from_slice(&b[..size_of::<u32>()]);

    u32::from_be_bytes(buf)
}

fn spawn_killah() {
    thread::spawn(|| {
        let runtime = rand::thread_rng().gen_range(0, 200);
        thread::sleep(Duration::from_millis(runtime));
        unsafe {
            libc::raise(9);
        }
    });
}

fn run(config: Config) {
    common::setup_logger();

    let crash_during_initialization = rand::thread_rng().gen_bool(0.1);

    if crash_during_initialization {
        spawn_killah();
    }

    let tree = config.open().unwrap();

    if !crash_during_initialization {
        spawn_killah();
    }

    let (key, highest) = verify(&tree);

    let mut hu = ((highest as usize) * CYCLE) + key as usize;
    assert_eq!(hu % CYCLE, key as usize);
    assert_eq!(hu / CYCLE, highest as usize);

    loop {
        hu += 1;

        if hu / CYCLE >= CYCLE {
            hu = 0;
        }

        let key = u32_to_vec((hu % CYCLE) as u32);

        let mut value = u32_to_vec((hu / CYCLE) as u32);
        let additional_len = rand::thread_rng().gen_range(0, 1000);
        value.append(&mut vec![0u8; additional_len]);

        tree.insert(&key, value).unwrap();
    }
}

fn run_batches(config: Config) {
    fn do_batch(i: u32, tree: &sled::Tree) {
        let mut rng = rand::thread_rng();
        let base_value = u32_to_vec(i);

        let mut batch = sled::Batch::default();
        if rng.gen_bool(0.1) {
            for key in 0..BATCH_SIZE {
                batch.remove(u32_to_vec(key));
            }
        } else {
            for key in 0..BATCH_SIZE {
                let mut value = base_value.clone();
                let additional_len = rng.gen_range(0, 1000);
                value.append(&mut vec![0u8; additional_len]);

                batch.insert(u32_to_vec(key), value);
            }
        }
        tree.apply_batch(batch).unwrap();
    }

    common::setup_logger();
    let crash_during_initialization = rand::thread_rng().gen_bool(0.1);

    if crash_during_initialization {
        spawn_killah();
    }

    let tree = config.open().unwrap();

    let mut i = verify_batches(&tree);
    i += 1;
    do_batch(i, &tree);

    if !crash_during_initialization {
        spawn_killah();
    }

    loop {
        i += 1;
        do_batch(i, &tree);
    }
}

fn run_without_snapshot(dir: &str) {
    let config = Config::new()
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .path(dir.to_string())
        .snapshot_after_ops(1 << 56)
        .segment_size(1024);

    match thread::spawn(|| run(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

fn run_with_snapshot(dir: &str) {
    let config = Config::new()
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .path(dir.to_string())
        .snapshot_after_ops(5000)
        .segment_size(1024);

    match thread::spawn(|| run(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

fn run_batches_without_snapshot(dir: &str) {
    let config = Config::new()
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .path(dir.to_string())
        .snapshot_after_ops(1 << 56)
        .segment_size(1024);

    match thread::spawn(|| run_batches(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

fn run_batches_with_snapshot(dir: &str) {
    let config = Config::new()
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .path(dir.to_string())
        .snapshot_after_ops(5000)
        .segment_size(1024);

    match thread::spawn(|| run_batches(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

#[test]
fn test_crash_recovery_with_runtime_snapshot() {
    let dir = "test_crashes_with_snapshot";
    cleanup(dir);
    for _ in 0..N_TESTS {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_with_snapshot(dir)
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup(dir);
                panic!("child exited abnormally");
            }
        }
    }
    cleanup(dir);
}

#[test]
fn test_crash_recovery_no_runtime_snapshot() {
    let dir = "test_crashes";
    cleanup(dir);
    for _ in 0..N_TESTS {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_without_snapshot(dir)
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup(dir);
                panic!("child exited abnormally");
            }
        }
    }
    cleanup(dir);
}

#[test]
fn test_crash_batches_with_runtime_snapshot() {
    let dir = "test_batches_with_snapshot";
    cleanup(dir);
    for _ in 0..N_TESTS {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_batches_with_snapshot(dir)
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup(dir);
                panic!("child exited abnormally");
            }
        }
    }
    cleanup(dir);
}

#[test]
fn test_crash_batches_no_runtime_snapshot() {
    let dir = "test_batches";
    cleanup(dir);
    for _ in 0..N_TESTS {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_batches_without_snapshot(dir)
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup(dir);
                panic!("child exited abnormally");
            }
        }
    }
    cleanup(dir);
}

fn cleanup(dir: &str) {
    let dir = Path::new(dir);
    if dir.exists() {
        fs::remove_dir_all(dir).unwrap();
    }
}
<commit_msg>Re-ignore the batch tests that still fail sometimes<commit_after>#![cfg(target_os = "linux")]

mod common;

use std::fs;
use std::mem::size_of;
use std::path::Path;
use std::thread;
use std::time::Duration;

use rand::Rng;

use sled::Config;

const N_TESTS: usize = 100;
const CYCLE: usize = 256;
const BATCH_SIZE: u32 = 8;

/// Verifies that the keys in the tree are correctly recovered.
/// Panics if they are incorrect.
/// Returns the key that should be resumed at, and the current cycle value.
fn verify(tree: &sled::Tree) -> (u32, u32) {
    // key 0 should always be the highest value, as that's where we increment
    // at some point, it might go down by one
    // it should never return, or go down again after that
    let mut iter = tree.iter();
    let highest = match iter.next() {
        Some(Ok((_k, v))) => slice_to_u32(&*v),
        Some(Err(e)) => panic!("{:?}", e),
        None => return (0, 0),
    };

    let highest_vec = u32_to_vec(highest);

    // find how far we got
    let mut contiguous: u32 = 0;
    let mut lowest = 0;
    for res in iter {
        let (_k, v) = res.unwrap();
        if &v[..4] == &highest_vec[..4] {
            contiguous += 1;
        } else {
            let expected = if highest == 0 {
                CYCLE as u32 - 1
            } else {
                (highest - 1) % CYCLE as u32
            };
            let actual = slice_to_u32(&*v);
            assert_eq!(expected, actual);
            lowest = actual;
            break;
        }
    }

    // ensure nothing changes after this point
    let low_beginning = u32_to_vec(contiguous + 1);

    for res in tree.range(&*low_beginning..) {
        let (k, v): (sled::IVec, _) = res.unwrap();
        assert_eq!(
            slice_to_u32(&*v),
            lowest,
            "expected key {} to have value {}, instead it had value {} in db: {:?}",
            slice_to_u32(&*k),
            lowest,
            slice_to_u32(&*v),
            tree
        );
    }

    (contiguous, highest)
}

/// Verifies that the keys in the tree are correctly recovered (i.e., equal).
/// Panics if they are incorrect.
fn verify_batches(tree: &sled::Tree) -> u32 {
    let mut iter = tree.iter();
    let first_value = match iter.next() {
        Some(Ok((_k, v))) => slice_to_u32(&*v),
        Some(Err(e)) => panic!("{:?}", e),
        None => return 0,
    };
    for key in 0..BATCH_SIZE {
        let res = tree.get(u32_to_vec(key));
        let option = res.unwrap();
        let v = match option {
            Some(v) => v,
            None => panic!(
                "expected key {} to have a value, instead it was missing in db: {:?}",
                key,
                tree
            ),
        };
        let value = slice_to_u32(&*v);
        assert_eq!(
            first_value,
            value,
            "expected key {} to have value {}, instead it had value {} in db: {:?}",
            key,
            first_value,
            value,
            tree
        );
    }

    first_value
}

fn u32_to_vec(u: u32) -> Vec<u8> {
    let buf: [u8; size_of::<u32>()] = u.to_be_bytes();
    buf.to_vec()
}

fn slice_to_u32(b: &[u8]) -> u32 {
    let mut buf = [0u8; size_of::<u32>()];
    buf.copy_from_slice(&b[..size_of::<u32>()]);

    u32::from_be_bytes(buf)
}

fn spawn_killah() {
    thread::spawn(|| {
        let runtime = rand::thread_rng().gen_range(0, 200);
        thread::sleep(Duration::from_millis(runtime));
        unsafe {
            libc::raise(9);
        }
    });
}

fn run(config: Config) {
    common::setup_logger();

    let crash_during_initialization = rand::thread_rng().gen_bool(0.1);

    if crash_during_initialization {
        spawn_killah();
    }

    let tree = config.open().unwrap();

    if !crash_during_initialization {
        spawn_killah();
    }

    let (key, highest) = verify(&tree);

    let mut hu = ((highest as usize) * CYCLE) + key as usize;
    assert_eq!(hu % CYCLE, key as usize);
    assert_eq!(hu / CYCLE, highest as usize);

    loop {
        hu += 1;

        if hu / CYCLE >= CYCLE {
            hu = 0;
        }

        let key = u32_to_vec((hu % CYCLE) as u32);

        let mut value = u32_to_vec((hu / CYCLE) as u32);
        let additional_len = rand::thread_rng().gen_range(0, 1000);
        value.append(&mut vec![0u8; additional_len]);

        tree.insert(&key, value).unwrap();
    }
}

fn run_batches(config: Config) {
    fn do_batch(i: u32, tree: &sled::Tree) {
        let mut rng = rand::thread_rng();
        let base_value = u32_to_vec(i);

        let mut batch = sled::Batch::default();
        if rng.gen_bool(0.1) {
            for key in 0..BATCH_SIZE {
                batch.remove(u32_to_vec(key));
            }
        } else {
            for key in 0..BATCH_SIZE {
                let mut value = base_value.clone();
                let additional_len = rng.gen_range(0, 1000);
                value.append(&mut vec![0u8; additional_len]);

                batch.insert(u32_to_vec(key), value);
            }
        }
        tree.apply_batch(batch).unwrap();
    }

    common::setup_logger();
    let crash_during_initialization = rand::thread_rng().gen_bool(0.1);

    if crash_during_initialization {
        spawn_killah();
    }

    let tree = config.open().unwrap();

    let mut i = verify_batches(&tree);
    i += 1;
    do_batch(i, &tree);

    if !crash_during_initialization {
        spawn_killah();
    }

    loop {
        i += 1;
        do_batch(i, &tree);
    }
}

fn run_without_snapshot(dir: &str) {
    let config = Config::new()
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .path(dir.to_string())
        .snapshot_after_ops(1 << 56)
        .segment_size(1024);

    match thread::spawn(|| run(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

fn run_with_snapshot(dir: &str) {
    let config = Config::new()
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .path(dir.to_string())
        .snapshot_after_ops(5000)
        .segment_size(1024);

    match thread::spawn(|| run(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

fn run_batches_without_snapshot(dir: &str) {
    let config = Config::new()
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .path(dir.to_string())
        .snapshot_after_ops(1 << 56)
        .segment_size(1024);

    match thread::spawn(|| run_batches(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

fn run_batches_with_snapshot(dir: &str) {
    let config = Config::new()
        .cache_capacity(128 * 1024 * 1024)
        .flush_every_ms(Some(100))
        .path(dir.to_string())
        .snapshot_after_ops(5000)
        .segment_size(1024);

    match thread::spawn(|| run_batches(config)).join() {
        Err(e) => {
            println!("worker thread failed: {:?}", e);
            std::process::exit(15);
        }
        _ => {}
    }
}

#[test]
fn test_crash_recovery_with_runtime_snapshot() {
    let dir = "test_crashes_with_snapshot";
    cleanup(dir);
    for _ in 0..N_TESTS {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_with_snapshot(dir)
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup(dir);
                panic!("child exited abnormally");
            }
        }
    }
    cleanup(dir);
}

#[test]
fn test_crash_recovery_no_runtime_snapshot() {
    let dir = "test_crashes";
    cleanup(dir);
    for _ in 0..N_TESTS {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_without_snapshot(dir)
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup(dir);
                panic!("child exited abnormally");
            }
        }
    }
    cleanup(dir);
}

#[test]
#[ignore]
fn test_crash_batches_with_runtime_snapshot() {
    let dir = "test_batches_with_snapshot";
    cleanup(dir);
    for _ in 0..N_TESTS {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_batches_with_snapshot(dir)
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup(dir);
                panic!("child exited abnormally");
            }
        }
    }
    cleanup(dir);
}

#[test]
#[ignore]
fn test_crash_batches_no_runtime_snapshot() {
    let dir = "test_batches";
    cleanup(dir);
    for _ in 0..N_TESTS {
        let child = unsafe { libc::fork() };
        if child == 0 {
            run_batches_without_snapshot(dir)
        } else {
            let mut status = 0;
            unsafe {
                libc::waitpid(child, &mut status as *mut libc::c_int, 0);
            }
            if status != 9 {
                cleanup(dir);
                panic!("child exited abnormally");
            }
        }
    }
    cleanup(dir);
}

fn cleanup(dir: &str) {
    let dir = Path::new(dir);
    if dir.exists() {
        fs::remove_dir_all(dir).unwrap();
    }
}
<|endoftext|>


<commit_before>use serde::Deserialize;

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box {
        #[serde(with = "urdf_vec3")]
        size: [f64; 3],
    },
    Cylinder {
        radius: f64,
        length: f64,
    },
    Capsule {
        radius: f64,
        length: f64,
    },
    Sphere {
        radius: f64,
    },
    Mesh {
        filename: String,
        #[serde(with = "urdf_option_vec3")]
        scale: Option<[f64; 3]>,
    },
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box {
            size: [0.0f64, 0.0, 0.0],
        }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Color {
    #[serde(with = "urdf_vec4")]
    pub rgba: [f64; 4],
}

#[derive(Debug, Deserialize, Clone)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture {
            filename: "".to_string(),
        }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Material {
    pub name: String,
    pub color: Option<Color>,
    pub texture: Option<Texture>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Visual {
    pub name: Option<String>,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    pub material: Option<Material>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Collision {
    pub name: Option<String>,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
}

/// Urdf Link element
/// See <http://wiki.ros.org/urdf/XML/link> for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Vec<Visual>,
    #[serde(default)]
    pub collision: Vec<Collision>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Vec3 {
    #[serde(with = "urdf_vec3")]
    pub data: [f64; 3],
}

mod urdf_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<[f64; 3], D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 3 {
            return Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )));
        }
        let mut arr = [0.0f64; 3];
        arr.copy_from_slice(&vec);
        Ok(arr)
    }
}

mod urdf_option_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<[f64; 3]>, D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.is_empty() {
            Ok(None)
        } else if vec.len() == 3 {
            let mut arr = [0.0; 3];
            arr.copy_from_slice(&vec);
            Ok(Some(arr))
        } else {
            Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )))
        }
    }
}

mod urdf_vec4 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<[f64; 4], D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 4 {
            return Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )));
        }
        let mut arr = [0.0f64; 4];
        arr.copy_from_slice(&vec);
        Ok(arr)
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Axis {
    #[serde(with = "urdf_vec3")]
    pub xyz: [f64; 3],
}

impl Default for Axis {
    fn default() -> Axis {
        Axis {
            xyz: [1.0f64, 0.0, 0.0],
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Pose {
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub xyz: [f64; 3],
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub rpy: [f64; 3],
}

fn default_zero3() -> [f64; 3] {
    [0.0f64, 0.0, 0.0]
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: default_zero3(),
            rpy: default_zero3(),
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
    Spherical,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    pub effort: f64,
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mimic {
    pub joint: String,
    pub multiplier: Option<f64>,
    pub offset: Option<f64>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct SafetyController {
    #[serde(default)]
    pub soft_lower_limit: f64,
    #[serde(default)]
    pub soft_upper_limit: f64,
    #[serde(default)]
    pub k_position: f64,
    pub k_velocity: f64,
}

/// Urdf Joint element
/// See <http://wiki.ros.org/urdf/XML/joint> for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: JointType,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    #[serde(default)]
    pub limit: JointLimit,
    pub dynamics: Option<Dynamics>,
    pub mimic: Option<Mimic>,
    pub safety_controller: Option<SafetyController>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Dynamics {
    #[serde(default)]
    pub damping: f64,
    #[serde(default)]
    pub friction: f64,
}

/// Top level struct to access urdf.
#[derive(Debug, Deserialize, Clone)]
pub struct Robot {
    #[serde(default)]
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,

    #[serde(rename = "material", default)]
    pub materials: Vec<Material>,
}
<commit_msg>Fix mesh without scale problem by adding #[serde(default)]<commit_after>use serde::Deserialize;

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box {
        #[serde(with = "urdf_vec3")]
        size: [f64; 3],
    },
    Cylinder {
        radius: f64,
        length: f64,
    },
    Capsule {
        radius: f64,
        length: f64,
    },
    Sphere {
        radius: f64,
    },
    Mesh {
        filename: String,
        #[serde(with = "urdf_option_vec3", default)]
        scale: Option<[f64; 3]>,
    },
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box {
            size: [0.0f64, 0.0, 0.0],
        }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Color {
    #[serde(with = "urdf_vec4")]
    pub rgba: [f64; 4],
}

#[derive(Debug, Deserialize, Clone)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture {
            filename: "".to_string(),
        }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Material {
    pub name: String,
    pub color: Option<Color>,
    pub texture: Option<Texture>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Visual {
    pub name: Option<String>,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    pub material: Option<Material>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Collision {
    pub name: Option<String>,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
}

/// Urdf Link element
/// See <http://wiki.ros.org/urdf/XML/link> for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Vec<Visual>,
    #[serde(default)]
    pub collision: Vec<Collision>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Vec3 {
    #[serde(with = "urdf_vec3")]
    pub data: [f64; 3],
}

mod urdf_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<[f64; 3], D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 3 {
            return Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )));
        }
        let mut arr = [0.0f64; 3];
        arr.copy_from_slice(&vec);
        Ok(arr)
    }
}

mod urdf_option_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<[f64; 3]>, D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.is_empty() {
            Ok(None)
        } else if vec.len() == 3 {
            let mut arr = [0.0; 3];
            arr.copy_from_slice(&vec);
            Ok(Some(arr))
        } else {
            Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )))
        }
    }
}

mod urdf_vec4 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<[f64; 4], D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 4 {
            return Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )));
        }
        let mut arr = [0.0f64; 4];
        arr.copy_from_slice(&vec);
        Ok(arr)
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Axis {
    #[serde(with = "urdf_vec3")]
    pub xyz: [f64; 3],
}

impl Default for Axis {
    fn default() -> Axis {
        Axis {
            xyz: [1.0f64, 0.0, 0.0],
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Pose {
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub xyz: [f64; 3],
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub rpy: [f64; 3],
}

fn default_zero3() -> [f64; 3] {
    [0.0f64, 0.0, 0.0]
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: default_zero3(),
            rpy: default_zero3(),
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
    Spherical,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    pub effort: f64,
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mimic {
    pub joint: String,
    pub multiplier: Option<f64>,
    pub offset: Option<f64>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct SafetyController {
    #[serde(default)]
    pub soft_lower_limit: f64,
    #[serde(default)]
    pub soft_upper_limit: f64,
    #[serde(default)]
    pub k_position: f64,
    pub k_velocity: f64,
}

/// Urdf Joint element
/// See <http://wiki.ros.org/urdf/XML/joint> for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: JointType,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    #[serde(default)]
    pub limit: JointLimit,
    pub dynamics: Option<Dynamics>,
    pub mimic: Option<Mimic>,
    pub safety_controller: Option<SafetyController>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Dynamics {
    #[serde(default)]
    pub damping: f64,
    #[serde(default)]
    pub friction: f64,
}

/// Top level struct to access urdf.
#[derive(Debug, Deserialize, Clone)]
pub struct Robot {
    #[serde(default)]
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,

    #[serde(rename = "material", default)]
    pub materials: Vec<Material>,
}
<|endoftext|>


<commit_before>use std::{convert};
use std::io::{Cursor, Read};

use byteorder;
use byteorder::{ReadBytesExt};

#[derive(Debug, PartialEq, Eq)]
pub enum DeserializationError {
    UnexpectedTag,
    ShortData,
    ExtraData,
    IntegerOverflow,
}

impl convert::From<byteorder::Error> for DeserializationError {
    fn from(e: byteorder::Error) -> DeserializationError {
        return match e {
            byteorder::Error::UnexpectedEOF => DeserializationError::ShortData,
            _ => panic!("Unexpected error!"),
        }
    }
}

pub struct Deserializer {
    reader: Cursor<Vec<u8>>,
}

impl Deserializer {
    pub fn new(data: Vec<u8>) -> Deserializer {
        return Deserializer{
            reader: Cursor::new(data),
        }
    }

    fn _read_length(&mut self) -> Result<usize, DeserializationError> {
        let b = try!(self.reader.read_u8());
        // TODO: handle lengths greater than 128
        assert!(b & 0x80 == 0);
        return Ok((b & 0x7f) as usize);
    }

    fn _read_with_tag<T, F>(&mut self, expected_tag: u8, body: F) -> Result<T, DeserializationError>
            where F: Fn(Vec<u8>) -> Result<T, DeserializationError> {
        // TODO: only some of the bits in the first byte are for the tag
        let tag = try!(self.reader.read_u8());
        if tag != expected_tag {
            return Err(DeserializationError::UnexpectedTag);
        }
        let length = try!(self._read_length());
        let mut data = vec![0; length];
        let n = self.reader.read(&mut data).unwrap();
        if n != length {
            return Err(DeserializationError::ShortData);
        }
        return body(data);
    }

    pub fn finish(self) -> Result<(), DeserializationError> {
        if self.reader.position() as usize != self.reader.get_ref().len() {
            return Err(DeserializationError::ExtraData);
        }
        return Ok(());
    }

    pub fn read_int(&mut self) -> Result<i64, DeserializationError> {
        return self._read_with_tag(2, |data| {
            if data.len() > 8 {
                return Err(DeserializationError::IntegerOverflow);
            }
            let mut ret = 0;
            for b in data.iter() {
                ret <<= 8;
                ret |= *b as i64;
            }
            // Shift up and down in order to sign extend the result.
            ret <<= 64 - data.len() * 8;
            ret >>= 64 - data.len() * 8;
            return Ok(ret);
        });
    }
}

pub fn from_vec<F, T>(data: Vec<u8>, f: F) -> Result<T, DeserializationError>
        where F: Fn(&mut Deserializer) -> Result<T, DeserializationError> {
    let mut deserializer = Deserializer::new(data);
    let result = try!(f(&mut deserializer));
    try!(deserializer.finish());
    return Ok(result);
}

#[cfg(test)]
mod tests {
    use std::{fmt};

    use super::{Deserializer, DeserializationError, from_vec};

    fn assert_deserializes<T, F>(values: Vec<(Result<T, DeserializationError>, Vec<u8>)>, f: F)
            where T: Eq + fmt::Debug, F: Fn(&mut Deserializer) -> Result<T, DeserializationError> {
        for (expected, value) in values {
            let result = from_vec(value, &f);
            assert_eq!(result, expected);
        }
    }
    #[test]
    fn test_read_extra_data() {
        assert_deserializes(vec![
            (Err(DeserializationError::ExtraData), b"\x00".to_vec()),
        ], |_| {
            return Ok(());
        });
    }

    #[test]
    fn test_read_int() {
        assert_deserializes(vec![
            (Ok(0), b"\x02\x01\x00".to_vec()),
            (Ok(127), b"\x02\x01\x7f".to_vec()),
            (Ok(128), b"\x02\x02\x00\x80".to_vec()),
            (Ok(256), b"\x02\x02\x01\x00".to_vec()),
            (Ok(-128), b"\x02\x01\x80".to_vec()),
            (Ok(-129), b"\x02\x02\xff\x7f".to_vec()),
            (Err(DeserializationError::UnexpectedTag), b"\x03".to_vec()),
            (Err(DeserializationError::ShortData), b"\x02\x02\x00".to_vec()),
            (Err(DeserializationError::ShortData), b"".to_vec()),
            (Err(DeserializationError::ShortData), b"\x02".to_vec()),
            (
                Err(DeserializationError::IntegerOverflow),
                b"\x02\x09\x02\x00\x00\x00\x00\x00\x00\x00\x00".to_vec()
            ),
        ], |deserializer| {
            return deserializer.read_int();
        });
    }
}
<commit_msg>too many newlines<commit_after>use std::{convert};
use std::io::{Cursor, Read};

use byteorder;
use byteorder::{ReadBytesExt};

#[derive(Debug, PartialEq, Eq)]
pub enum DeserializationError {
    UnexpectedTag,
    ShortData,
    ExtraData,
    IntegerOverflow,
}

impl convert::From<byteorder::Error> for DeserializationError {
    fn from(e: byteorder::Error) -> DeserializationError {
        return match e {
            byteorder::Error::UnexpectedEOF => DeserializationError::ShortData,
            _ => panic!("Unexpected error!"),
        }
    }
}

pub struct Deserializer {
    reader: Cursor<Vec<u8>>,
}

impl Deserializer {
    pub fn new(data: Vec<u8>) -> Deserializer {
        return Deserializer{
            reader: Cursor::new(data),
        }
    }

    fn _read_length(&mut self) -> Result<usize, DeserializationError> {
        let b = try!(self.reader.read_u8());
        // TODO: handle lengths greater than 128
        assert!(b & 0x80 == 0);
        return Ok((b & 0x7f) as usize);
    }

    fn _read_with_tag<T, F>(&mut self, expected_tag: u8, body: F) -> Result<T, DeserializationError>
            where F: Fn(Vec<u8>) -> Result<T, DeserializationError> {
        // TODO: only some of the bits in the first byte are for the tag
        let tag = try!(self.reader.read_u8());
        if tag != expected_tag {
            return Err(DeserializationError::UnexpectedTag);
        }
        let length = try!(self._read_length());
        let mut data = vec![0; length];
        let n = self.reader.read(&mut data).unwrap();
        if n != length {
            return Err(DeserializationError::ShortData);
        }
        return body(data);
    }

    pub fn finish(self) -> Result<(), DeserializationError> {
        if self.reader.position() as usize != self.reader.get_ref().len() {
            return Err(DeserializationError::ExtraData);
        }
        return Ok(());
    }

    pub fn read_int(&mut self) -> Result<i64, DeserializationError> {
        return self._read_with_tag(2, |data| {
            if data.len() > 8 {
                return Err(DeserializationError::IntegerOverflow);
            }
            let mut ret = 0;
            for b in data.iter() {
                ret <<= 8;
                ret |= *b as i64;
            }
            // Shift up and down in order to sign extend the result.
            ret <<= 64 - data.len() * 8;
            ret >>= 64 - data.len() * 8;
            return Ok(ret);
        });
    }
}

pub fn from_vec<F, T>(data: Vec<u8>, f: F) -> Result<T, DeserializationError>
        where F: Fn(&mut Deserializer) -> Result<T, DeserializationError> {
    let mut deserializer = Deserializer::new(data);
    let result = try!(f(&mut deserializer));
    try!(deserializer.finish());
    return Ok(result);
}

#[cfg(test)]
mod tests {
    use std::{fmt};

    use super::{Deserializer, DeserializationError, from_vec};

    fn assert_deserializes<T, F>(values: Vec<(Result<T, DeserializationError>, Vec<u8>)>, f: F)
            where T: Eq + fmt::Debug, F: Fn(&mut Deserializer) -> Result<T, DeserializationError> {
        for (expected, value) in values {
            let result = from_vec(value, &f);
            assert_eq!(result, expected);
        }
    }
    #[test]
    fn test_read_extra_data() {
        assert_deserializes(vec![
            (Err(DeserializationError::ExtraData), b"\x00".to_vec()),
        ], |_| {
            return Ok(());
        });
    }

    #[test]
    fn test_read_int() {
        assert_deserializes(vec![
            (Ok(0), b"\x02\x01\x00".to_vec()),
            (Ok(127), b"\x02\x01\x7f".to_vec()),
            (Ok(128), b"\x02\x02\x00\x80".to_vec()),
            (Ok(256), b"\x02\x02\x01\x00".to_vec()),
            (Ok(-128), b"\x02\x01\x80".to_vec()),
            (Ok(-129), b"\x02\x02\xff\x7f".to_vec()),
            (Err(DeserializationError::UnexpectedTag), b"\x03".to_vec()),
            (Err(DeserializationError::ShortData), b"\x02\x02\x00".to_vec()),
            (Err(DeserializationError::ShortData), b"".to_vec()),
            (Err(DeserializationError::ShortData), b"\x02".to_vec()),
            (
                Err(DeserializationError::IntegerOverflow),
                b"\x02\x09\x02\x00\x00\x00\x00\x00\x00\x00\x00".to_vec()
            ),
        ], |deserializer| {
            return deserializer.read_int();
        });
    }
}
<|endoftext|>