use std::ops::Deref;
use reifydb_runtime::hash::{Hash128, xxh3_128};
use serde::{Deserialize, Serialize};
use super::walk::{FingerprintBuffer, fingerprint_ast_slice};
use crate::ast::ast::AstStatement;
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct StatementFingerprint(pub Hash128);
impl Deref for StatementFingerprint {
type Target = u128;
fn deref(&self) -> &Self::Target {
&self.0.0
}
}
impl StatementFingerprint {
#[inline]
pub const fn new(value: u128) -> Self {
Self(Hash128(value))
}
#[inline]
pub const fn as_u128(&self) -> u128 {
self.0.0
}
#[inline]
pub const fn to_le_bytes(&self) -> [u8; 16] {
self.0.0.to_le_bytes()
}
#[inline]
pub const fn from_le_bytes(bytes: [u8; 16]) -> Self {
Self(Hash128(u128::from_le_bytes(bytes)))
}
#[inline]
pub fn to_hex(&self) -> String {
format!("0x{:032x}", self.0.0)
}
}
impl From<Hash128> for StatementFingerprint {
fn from(hash: Hash128) -> Self {
Self(hash)
}
}
impl From<StatementFingerprint> for Hash128 {
fn from(fp: StatementFingerprint) -> Self {
fp.0
}
}
impl From<u128> for StatementFingerprint {
fn from(value: u128) -> Self {
Self(Hash128(value))
}
}
pub fn fingerprint_statement(statement: &AstStatement<'_>) -> StatementFingerprint {
let mut buf = FingerprintBuffer::new();
buf.write_u8(statement.has_pipes as u8);
buf.write_u8(statement.is_output as u8);
fingerprint_ast_slice(&mut buf, &statement.nodes);
StatementFingerprint(xxh3_128(buf.as_bytes()))
}