ore_encoding_rs/
encode.rs

1use std::{ops::{Sub, Add}};
2
3use num::{Bounded, One};
4
5/// Convenience alias for all of the traits that must be implemented by the type
6/// held by an [OrePlaintext]
7pub trait OrePlaintextOps: Ord + Bounded + One + Copy + Sub<Output=Self> + Add<Output=Self> {}
8
9/// Blanket implementation of `OrePlaintextOps`
10impl<T: Ord + Sized + Bounded + One + Copy + Sub<Output=T> + Add<Output=T>> OrePlaintextOps for T {}
11
12/// An `OrePlainText` is a wrapper around an unsigned integer which represents a
13/// plaintext value before it is encrypted with an ORE encryption scheme.
14#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone)]
15pub struct OrePlaintext<T>(pub T) where T: OrePlaintextOps;
16
17impl From<f32> for OrePlaintext<u64> {
18    fn from(term: f32) -> OrePlaintext<u64> {
19        OrePlaintext::from(f64::from(term))
20    }
21}
22
23impl From<f64> for OrePlaintext<u64> {
24    fn from(term: f64) -> OrePlaintext<u64> {
25        use core::mem::transmute;
26        let num: u64 = term.to_bits();
27        let signed: i64 = -(unsafe { transmute(num >> 63) });
28        let mut mask: u64 = unsafe { transmute(signed) };
29        mask |= 0x8000000000000000;
30        OrePlaintext(num ^ mask)
31    }
32}
33
34/// This is useful for debugging purposes only
35impl From<OrePlaintext<u64>> for f64 {
36    fn from(plaintext: OrePlaintext<u64>) -> f64 {
37        let OrePlaintext(term) = plaintext;
38        let i = (((term >> 63) as i64) - 1) as u64;
39        let mask: u64 = i | 0x8000000000000000;
40        f64::from_bits(term ^ mask)
41    }
42}
43
44impl From<bool> for OrePlaintext<u64> {
45    fn from(term: bool) -> OrePlaintext<u64> {
46        OrePlaintext(term.into())
47    }
48}
49
50impl From<u8> for OrePlaintext<u64> {
51    fn from(term: u8) -> OrePlaintext<u64> {
52        OrePlaintext(term.into())
53    }
54}
55
56impl From<u16> for OrePlaintext<u64> {
57    fn from(term: u16) -> OrePlaintext<u64> {
58        OrePlaintext(term.into())
59    }
60}
61
62impl From<u32> for OrePlaintext<u64> {
63    fn from(term: u32) -> OrePlaintext<u64> {
64        OrePlaintext(term.into())
65    }
66}
67
68impl From<u64> for OrePlaintext<u64> {
69    fn from(term: u64) -> OrePlaintext<u64> {
70        OrePlaintext(term)
71    }
72}
73
74
75#[cfg(test)]
76mod tests {
77    use std::cmp::Ordering;
78
79    use super::*;
80    use quickcheck::TestResult;
81
82    #[test]
83    // -0.0 and 0.0 compare as equal in f64's PartialOrd implementation.  This
84    // test demonstrates that fact and why we need to filter out -0.0 from the
85    // sort_order_is_preserved_for_vec_of_f64_after_converting_to_vec_of_ordered_integer
86    // quickcheck test because the sort order will be nondeterministic for
87    // vectors containing both 0.0 and -0.0.
88    fn zero_and_negative_zero() -> () {
89        assert_eq!(0.0f64.partial_cmp(&-0.0f64), Some(Ordering::Equal))
90    }
91
92    quickcheck! {
93        fn roundtrip_one_f64(x: f64) -> TestResult {
94            if !x.is_nan() && x.is_finite() {
95                TestResult::from_bool(x == f64::from(OrePlaintext::<u64>::from(x)))
96            } else {
97                TestResult::discard()
98            }
99        }
100
101        fn sort_order_is_preserved_for_vec_of_f64_after_converting_to_vec_of_ore_plaintext(numbers: Vec<f64>) -> TestResult {
102            let mut filtered: Vec<f64> = numbers.into_iter().filter(|n| !n.is_nan() && n.is_finite() && *n != -0.0f64).collect();
103            filtered.sort_by(|a, b| a.partial_cmp(b).unwrap());
104            if filtered.len() == 0 {
105                TestResult::discard()
106            } else {
107                let mut sorted_by_f64 = filtered.clone().into_iter().collect::<Vec<f64>>();
108                sorted_by_f64.sort_by(|a, b| a.partial_cmp(b).unwrap());
109
110                let mut sorted_by_u64 = filtered.clone().into_iter().collect::<Vec<f64>>();
111                sorted_by_u64.sort_by(|a, b| OrePlaintext::from(*a).cmp(&OrePlaintext::from(*b)));
112
113                TestResult::from_bool(sorted_by_f64 == sorted_by_u64)
114            }
115        }
116    }
117}