use super::error::{Result, SidError};
use super::smartid::SmartId;
use serde::{Deserialize, Serialize};
pub const MAX_CONTRIBUTORS: u16 = 999;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Contributor {
cid: u16,
local_counter: u64,
}
impl Contributor {
pub fn new(cid: u16) -> Result<Self> {
if cid >= MAX_CONTRIBUTORS {
return Err(SidError::ContributorIdTooLarge(cid));
}
Ok(Self {
cid,
local_counter: 0,
})
}
pub fn with_counter(cid: u16, local_counter: u64) -> Result<Self> {
if cid >= MAX_CONTRIBUTORS {
return Err(SidError::ContributorIdTooLarge(cid));
}
Ok(Self { cid, local_counter })
}
pub fn cid(&self) -> u16 {
self.cid
}
pub fn local_counter(&self) -> u64 {
self.local_counter
}
pub fn mint(&mut self, num_contributors: u16, min_length: usize) -> Result<SmartId> {
let sid = SmartId::compute(self.local_counter, self.cid, num_contributors, min_length)?;
self.local_counter += 1;
Ok(sid)
}
pub fn peek_next(&self, num_contributors: u16, min_length: usize) -> Result<SmartId> {
SmartId::compute(self.local_counter, self.cid, num_contributors, min_length)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_contributor() {
let contrib = Contributor::new(0).unwrap();
assert_eq!(contrib.cid(), 0);
assert_eq!(contrib.local_counter(), 0);
let contrib = Contributor::new(998).unwrap();
assert_eq!(contrib.cid(), 998);
}
#[test]
fn test_contributor_id_too_large() {
let result = Contributor::new(999);
assert!(matches!(result, Err(SidError::ContributorIdTooLarge(999))));
let result = Contributor::new(1000);
assert!(matches!(result, Err(SidError::ContributorIdTooLarge(1000))));
}
#[test]
fn test_with_counter() {
let contrib = Contributor::with_counter(5, 100).unwrap();
assert_eq!(contrib.cid(), 5);
assert_eq!(contrib.local_counter(), 100);
}
#[test]
fn test_mint() {
let mut contrib = Contributor::new(0).unwrap();
let sid1 = contrib.mint(1, 4).unwrap();
assert_eq!(sid1.global_id(), 1); assert_eq!(contrib.local_counter(), 1);
let sid2 = contrib.mint(1, 4).unwrap();
assert_eq!(sid2.global_id(), 2); assert_eq!(contrib.local_counter(), 2);
}
#[test]
fn test_mint_multi_contributor() {
let mut contrib = Contributor::new(5).unwrap();
let sid = contrib.mint(10, 4).unwrap();
assert_eq!(sid.global_id(), 0 * 10 + 5 + 1);
let sid = contrib.mint(10, 4).unwrap();
assert_eq!(sid.global_id(), 1 * 10 + 5 + 1);
let sid = contrib.mint(10, 4).unwrap();
assert_eq!(sid.global_id(), 2 * 10 + 5 + 1); }
#[test]
fn test_peek_next() {
let contrib = Contributor::with_counter(3, 10).unwrap();
let sid = contrib.peek_next(100, 4).unwrap();
assert_eq!(sid.global_id(), 10 * 100 + 3 + 1); assert_eq!(contrib.local_counter(), 10); }
#[test]
fn test_serde() {
let contrib = Contributor::with_counter(42, 1000).unwrap();
let json = serde_json::to_string(&contrib).unwrap();
let parsed: Contributor = serde_json::from_str(&json).unwrap();
assert_eq!(parsed.cid(), 42);
assert_eq!(parsed.local_counter(), 1000);
}
}