use core::fmt::{Debug};
use curve25519_dalek::ristretto::{CompressedRistretto,RistrettoPoint};
use crate::errors::{SignatureError,SignatureResult};
pub const RISTRETTO_POINT_LENGTH: usize = 32;
#[derive(Copy, Clone, Default, Eq)] pub struct RistrettoBoth {
compressed: CompressedRistretto,
point: RistrettoPoint,
}
impl Debug for RistrettoBoth {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
write!(f, "RistrettoPoint( {:?} )", self.compressed)
}
}
impl RistrettoBoth {
const DESCRIPTION : &'static str = "A ristretto point represented as a 32-byte compressed point";
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) -> SignatureResult<RistrettoBoth> {
Ok(RistrettoBoth {
point: compressed.decompress().ok_or(SignatureError::PointDecompressionError) ?,
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 from_bytes(bytes: &[u8]) -> SignatureResult<RistrettoBoth> {
RistrettoBoth::from_bytes_ser("RistrettoPoint",RistrettoBoth::DESCRIPTION,bytes)
}
#[inline]
pub fn from_bytes_ser(name: &'static str, description: &'static str, bytes: &[u8]) -> SignatureResult<RistrettoBoth> {
if bytes.len() != RISTRETTO_POINT_LENGTH {
return Err(SignatureError::BytesLengthError{
name, description, length: RISTRETTO_POINT_LENGTH,
});
}
let mut compressed = CompressedRistretto([0u8; RISTRETTO_POINT_LENGTH]);
compressed.0.copy_from_slice(&bytes[..32]);
RistrettoBoth::from_compressed(compressed)
}
}
serde_boilerplate!(RistrettoBoth);
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);
}
}