rebterlai/crates/logtail/src/lib.rs

116 lines
3.0 KiB
Rust

use sha2::{Digest, Sha256};
use std::fmt;
/// This represents an instance that write logs.
/// Private IDs are only shared with the server when writing logs.
#[derive(Clone, PartialEq, Eq)]
pub struct PrivateID([u8; SHA256_SIZE]);
impl PrivateID {
/// Safely generate a new PrivateId for use in Config objects.
/// You should persist this across runs of an instance of your app, so that
/// it can append to the same log file on each run.
pub fn new() -> Self {
let mut id: [u8; 32] = rand::random();
id[0] &= 248;
id[31] = (id[31] & 127) | 64;
Self(id)
}
/// Parse a PrivateID from its base 16 representation.
pub fn from_hex(data: String) -> Result<Self, hex::FromHexError> {
let mut id: [u8; 32] = [0; 32];
hex::decode_to_slice(data, &mut id)?;
Ok(Self(id))
}
/// Show a private ID as its base 16 representation.
pub fn as_hex(&self) -> String {
hex::encode(self.0)
}
pub fn as_public(&self) -> PublicID {
let mut hasher = Sha256::new();
hasher.update(&self.0);
PublicID(hasher.finalize().into())
}
}
impl fmt::Display for PrivateID {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", self.as_hex())
}
}
impl fmt::Debug for PrivateID {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "PrivateID({})", self.as_hex())
}
}
const SHA256_SIZE: usize = 32;
#[derive(Clone, PartialEq, Eq)]
pub struct PublicID([u8; SHA256_SIZE]);
impl PublicID {
/// Parse a PublicID from its base 16 representation.
pub fn from_hex(data: String) -> Result<Self, hex::FromHexError> {
let mut id: [u8; 32] = [0; 32];
hex::decode_to_slice(data, &mut id)?;
Ok(Self(id))
}
/// Show a public ID as its base 16 representation.
pub fn as_hex(&self) -> String {
hex::encode(self.0)
}
}
impl fmt::Display for PublicID {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", self.as_hex())
}
}
impl fmt::Debug for PublicID {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "PublicID({})", self.as_hex())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn id() {
let id = PrivateID::new();
assert_ne!(id.as_hex(), "".to_string());
}
#[test]
fn encode_decode() {
let id = PrivateID::new();
let as_hex = id.as_hex();
let other_id = PrivateID::from_hex(as_hex).unwrap();
assert_eq!(id, other_id);
}
#[test]
fn to_public() {
let id = PrivateID::from_hex(
"6451f1641112c13e80daa7237d62391b028e638fef9cf91fd7ea347a5290a643".to_string(),
)
.unwrap();
let pub_id = id.as_public();
assert_eq!(
pub_id,
PublicID::from_hex(
"db3a35df70555653e5fcff5bbc06e1573ad67e00744b56691c15cde72d17c449".to_string()
)
.unwrap()
);
}
}