use crate::account_address::AccountAddress;
use hex::FromHex;
#[cfg(any(test, feature = "fuzzing"))]
use rand::{rngs::OsRng, RngCore};
use serde::{de, ser, Deserialize, Serialize};
use std::{
convert::{TryFrom, TryInto},
fmt,
str::FromStr,
};
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct EventKey([u8; EventKey::LENGTH]);
#[cfg(any(test, feature = "fuzzing"))]
use proptest::prelude::*;
#[cfg(any(test, feature = "fuzzing"))]
impl proptest::arbitrary::Arbitrary for EventKey {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
any::<u8>().prop_map(|_seed| EventKey::random()).boxed()
}
}
impl EventKey {
pub const LENGTH: usize = AccountAddress::LENGTH + 8;
pub fn new(key: [u8; Self::LENGTH]) -> Self { EventKey(key) }
pub fn as_bytes(&self) -> &[u8] { &self.0 }
pub fn to_vec(&self) -> Vec<u8> { self.0.to_vec() }
pub fn get_creator_address(&self) -> AccountAddress {
AccountAddress::try_from(
&self.0[EventKey::LENGTH - AccountAddress::LENGTH..],
)
.expect("get_creator_address failed")
}
pub fn get_creation_number(&self) -> u64 {
u64::from_le_bytes(self.0[0..8].try_into().unwrap())
}
#[cfg(any(test, feature = "fuzzing"))]
pub fn random() -> Self {
let mut rng = OsRng;
let salt = rng.next_u64();
EventKey::new_from_address(&AccountAddress::random(), salt)
}
pub fn new_from_address(addr: &AccountAddress, salt: u64) -> Self {
let mut output_bytes = [0; Self::LENGTH];
let (lhs, rhs) = output_bytes.split_at_mut(8);
lhs.copy_from_slice(&salt.to_le_bytes());
rhs.copy_from_slice(addr.as_ref());
EventKey(output_bytes)
}
pub fn from_hex<T: AsRef<[u8]>>(
hex: T,
) -> Result<Self, EventKeyParseError> {
<[u8; Self::LENGTH]>::from_hex(hex)
.map_err(|_| EventKeyParseError)
.map(Self)
}
pub fn from_bytes<T: AsRef<[u8]>>(
bytes: T,
) -> Result<Self, EventKeyParseError> {
<[u8; Self::LENGTH]>::try_from(bytes.as_ref())
.map_err(|_| EventKeyParseError)
.map(Self)
}
}
impl FromStr for EventKey {
type Err = EventKeyParseError;
fn from_str(s: &str) -> Result<Self, EventKeyParseError> {
EventKey::from_hex(s)
}
}
impl From<EventKey> for [u8; EventKey::LENGTH] {
fn from(event_key: EventKey) -> Self { event_key.0 }
}
impl From<&EventKey> for [u8; EventKey::LENGTH] {
fn from(event_key: &EventKey) -> Self { event_key.0 }
}
impl ser::Serialize for EventKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer {
if serializer.is_human_readable() {
self.to_string().serialize(serializer)
} else {
serializer.serialize_newtype_struct(
"EventKey",
serde_bytes::Bytes::new(&self.0),
)
}
}
}
impl<'de> de::Deserialize<'de> for EventKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: de::Deserializer<'de> {
use serde::de::Error;
if deserializer.is_human_readable() {
let s = <String>::deserialize(deserializer)?;
EventKey::from_hex(s).map_err(D::Error::custom)
} else {
#[derive(::serde::Deserialize)]
#[serde(rename = "EventKey")]
struct Value<'a>(&'a [u8]);
let value = Value::deserialize(deserializer)?;
Self::try_from(value.0).map_err(D::Error::custom)
}
}
}
impl TryFrom<&[u8]> for EventKey {
type Error = EventKeyParseError;
fn try_from(bytes: &[u8]) -> Result<EventKey, EventKeyParseError> {
Self::from_bytes(bytes)
}
}
#[derive(Clone, Copy, Debug)]
pub struct EventKeyParseError;
impl fmt::Display for EventKeyParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
write!(f, "unable to parse EventKey")
}
}
impl std::error::Error for EventKeyParseError {}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EventHandle {
count: u64,
key: EventKey,
}
impl EventHandle {
pub fn new(key: EventKey, count: u64) -> Self { EventHandle { key, count } }
pub fn key(&self) -> &EventKey { &self.key }
pub fn count(&self) -> u64 { self.count }
#[cfg(any(test, feature = "fuzzing"))]
pub fn count_mut(&mut self) -> &mut u64 { &mut self.count }
#[cfg(any(test, feature = "fuzzing"))]
pub fn random_handle(count: u64) -> Self {
Self {
key: EventKey::random(),
count,
}
}
#[cfg(any(test, feature = "fuzzing"))]
pub fn new_from_address(addr: &AccountAddress, salt: u64) -> Self {
Self {
key: EventKey::new_from_address(addr, salt),
count: 0,
}
}
}
impl fmt::LowerHex for EventKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(f, "0x")?;
}
for byte in &self.0 {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
impl fmt::Display for EventKey {
fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
write!(f, "{:x}", self)
}
}
#[cfg(test)]
mod tests {
use super::EventKey;
#[test]
fn test_display_impls() {
let hex = "100000000000000000000000000000000000000000000000ca843279e3427144cead5e4d5999a3d0";
let key = EventKey::from_hex(hex).unwrap();
assert_eq!(format!("{}", key), hex);
assert_eq!(format!("{:x}", key), hex);
assert_eq!(format!("{:#x}", key), format!("0x{}", hex));
}
#[test]
fn test_invalid_length() {
let bytes = vec![1; 123];
EventKey::from_bytes(bytes).unwrap_err();
}
#[test]
fn test_deserialize_from_json_value() {
let key = EventKey::random();
let json_value = serde_json::to_value(key).unwrap();
let key2: EventKey = serde_json::from_value(json_value).unwrap();
assert_eq!(key, key2);
}
#[test]
fn test_serde_json() {
let hex = "100000000000000000000000000000000000000000000000ca843279e3427144cead5e4d5999a3d0";
let json_hex = "\"100000000000000000000000000000000000000000000000ca843279e3427144cead5e4d5999a3d0\"";
let key = EventKey::from_hex(hex).unwrap();
let json = serde_json::to_string(&key).unwrap();
let json_key: EventKey = serde_json::from_str(json_hex).unwrap();
assert_eq!(json, json_hex);
assert_eq!(key, json_key);
}
}