    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114

    //! Protocol Buffers representing the database.

    use protobuf::{CodedInputStream, CodedOutputStream, Message};
    use std::io::{Read, Write};
    use uuid::Uuid;

    // generated by protobuf_codegen
    include!(concat!(env!("OUT_DIR"), "/protos/mod.rs"));

    use crate::error::Error;

    /// Represents a type that can be serialized as a message.
    pub trait Serialize<M>
    where
        M: Message,
    {
        /// Serializes as a message.
        fn serialize(&self) -> Result<M, Error>;
    }

    impl Serialize<database::Uuid> for Uuid {
        fn serialize(&self) -> Result<database::Uuid, Error> {
            let mut uuid = database::Uuid::new();
            (uuid.upper, uuid.lower) = self.as_u64_pair();
            Ok(uuid)
        }
    }

    /// Represents a type that can be deserialized from a message.
    ///
    /// Supposed to be implemented for a specific message.
    pub trait Deserialize<T> {
        /// Deserializes the message.
        fn deserialize(self) -> Result<T, Error>;
    }

    impl Deserialize<Uuid> for database::Uuid {
        fn deserialize(self) -> Result<Uuid, Error> {
            let uuid = Uuid::from_u64_pair(self.upper, self.lower);
            Ok(uuid)
        }
    }

    /// Writes a given message to a given output stream.
    pub fn write_message<M, W>(message: &M, write: &mut W) -> Result<(), Error>
    where
        M: Message,
        W: Write,
    {
        let mut writer = CodedOutputStream::new(write);
        message.write_to(&mut writer)?;
        writer.flush()?;
        Ok(())
    }

    /// Reads a message from a given input stream.
    pub fn read_message<M, R>(read: &mut R) -> Result<M, Error>
    where
        M: Message,
        R: Read,
    {
        let mut reader = CodedInputStream::new(read);
        let message = M::parse_from(&mut reader)?;
        Ok(message)
    }

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

        #[test]
        fn database_can_be_newed() {
            let db = database::Database::new();
            assert_eq!(db.vector_size, 0);
            assert_eq!(db.num_partitions, 0);
            assert_eq!(db.num_divisions, 0);
            assert_eq!(db.num_codes, 0);
            assert!(db.partition_ids.is_empty());
            assert_eq!(db.partition_centroids_id, "");
            assert!(db.codebook_ids.is_empty());
            assert!(db.attributes_log_ids.is_empty());
        }

        #[test]
        fn partition_can_be_newed() {
            let partition = database::Partition::new();
            assert_eq!(partition.vector_size, 0);
            assert_eq!(partition.num_divisions, 0);
            assert!(partition.centroid.is_empty());
            assert!(partition.encoded_vectors.is_none());
            assert!(partition.vector_ids.is_empty());
        }

        #[test]
        fn uuid_can_be_serialized() {
            let upper: u64 = 0xa1a2a3a4b1b2c1c2;
            let lower: u64 = 0xd1d2d3d4d5d6d7d8;
            let uuid = Uuid::from_u64_pair(upper, lower);
            let serialized = uuid.serialize().unwrap();
            assert_eq!(serialized.upper, upper);
            assert_eq!(serialized.lower, lower);
        }

        #[test]
        fn uuid_can_be_deserialized() {
            let upper: u64 = 0xa1a2a3a4b1b2c1c2;
            let lower: u64 = 0xd1d2d3d4d5d6d7d8;
            let mut serialized = database::Uuid::new();
            serialized.upper = upper;
            serialized.lower = lower;
            let uuid = serialized.deserialize().unwrap();
            assert_eq!(uuid, Uuid::from_u64_pair(upper, lower));
        }
    }