use crate::dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use crate::ser;
use std::fmt::Debug;
pub const RISTRETTO_POINT_LENGTH: usize = 32;
#[derive(Copy, Clone, Default, Eq)] pub struct RistrettoBoth {
compressed: CompressedRistretto,
point: RistrettoPoint,
}
impl ::zeroize::Zeroize for RistrettoBoth {
fn zeroize(&mut self) {
crate::zeroize_hack(&mut self.compressed);
crate::zeroize_hack(&mut self.point);
}
}
impl Debug for RistrettoBoth {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
write!(f, "RistrettoPoint( {:?} )", self.compressed)
}
}
impl RistrettoBoth {
pub fn as_compressed(&self) -> &CompressedRistretto {
&self.compressed
}
pub fn into_compressed(self) -> CompressedRistretto {
self.compressed
}
pub fn as_point(&self) -> &RistrettoPoint {
&self.point
}
pub fn into_point(self) -> RistrettoPoint {
self.point
}
pub fn from_compressed(compressed: CompressedRistretto) -> Option<RistrettoBoth> {
match compressed.decompress() {
None => None,
Some(point) => Some(RistrettoBoth { point, compressed }),
}
}
pub fn from_point(point: RistrettoPoint) -> RistrettoBoth {
RistrettoBoth {
compressed: point.compress(),
point,
}
}
#[inline]
pub fn to_bytes(&self) -> [u8; RISTRETTO_POINT_LENGTH] {
self.compressed.to_bytes()
}
#[inline]
pub fn as_bytes<'a>(&'a self) -> &'a [u8; RISTRETTO_POINT_LENGTH] {
self.compressed.as_bytes()
}
#[inline]
pub fn from_bytes(bytes: &[u8]) -> Option<RistrettoBoth> {
if bytes.len() != RISTRETTO_POINT_LENGTH {
return None;
}
let mut compressed = CompressedRistretto([0u8; RISTRETTO_POINT_LENGTH]);
compressed.0.copy_from_slice(&bytes[..32]);
RistrettoBoth::from_compressed(compressed)
}
}
impl PartialEq<Self> for RistrettoBoth {
fn eq(&self, other: &Self) -> bool {
let r = self.compressed.eq(&other.compressed);
debug_assert_eq!(r, self.point.eq(&other.point));
r
}
}
impl PartialOrd<RistrettoBoth> for RistrettoBoth {
fn partial_cmp(&self, other: &RistrettoBoth) -> Option<::core::cmp::Ordering> {
self.compressed.0.partial_cmp(&other.compressed.0)
}
}
impl Ord for RistrettoBoth {
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
self.compressed.0.cmp(&other.compressed.0)
}
}
impl ::core::hash::Hash for RistrettoBoth {
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
self.compressed.0.hash(state);
}
}
impl ser::Writeable for RistrettoBoth {
fn write<W: ser::Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
self.compressed.write(writer)?;
Ok(())
}
}
impl ser::Readable for RistrettoBoth {
fn read(reader: &mut dyn ser::Reader) -> Result<RistrettoBoth, ser::Error> {
let raw = CompressedRistretto::read(reader)?;
match raw.decompress() {
Some(kosher) => Ok(RistrettoBoth {
compressed: raw,
point: kosher,
}),
None => Err(ser::Error::CorruptedData),
}
}
}