use arco::observation::Observation;
use arco::state::State;
use std::fmt;
use std::hash::{Hash, Hasher};
#[derive(Clone)]
struct Counter {
value: u8,
max_value: u8,
}
impl Counter {
fn new(value: u8, max_value: u8) -> Self {
assert!(value <= max_value);
Self { value, max_value }
}
#[allow(dead_code)]
fn increment(&self) -> Self {
if self.value >= self.max_value {
Self { value: 0, ..*self }
} else {
Self {
value: self.value + 1,
..*self
}
}
}
}
impl State for Counter {
type Encoding = Vec<u8>;
fn canonical_encoding(&self) -> Self::Encoding {
vec![self.value, self.max_value]
}
fn distance(&self, other: &Self) -> u32 {
let mut diff = 0u32;
if self.value != other.value {
diff += 1;
}
if self.max_value != other.max_value {
diff += 1;
}
diff
}
}
impl PartialEq for Counter {
fn eq(&self, other: &Self) -> bool {
self.value == other.value && self.max_value == other.max_value
}
}
impl Eq for Counter {}
impl Hash for Counter {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state);
self.max_value.hash(state);
}
}
impl fmt::Debug for Counter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Counter({}/{})", self.value, self.max_value)
}
}
impl fmt::Display for Counter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.value)
}
}
#[derive(Debug, Clone, Default)]
struct FullObserver;
impl Observation<Counter> for FullObserver {
type Output = Vec<u8>;
fn observe(&self, state: &Counter) -> Self::Output {
state.canonical_encoding()
}
}
#[derive(Debug, Clone, Default)]
struct ValueObserver;
impl Observation<Counter> for ValueObserver {
type Output = Vec<u8>;
fn observe(&self, state: &Counter) -> Self::Output {
vec![state.value]
}
}
#[derive(Debug, Clone, Default)]
struct NonZeroObserver;
impl Observation<Counter> for NonZeroObserver {
type Output = Vec<u8>;
fn observe(&self, state: &Counter) -> Self::Output {
vec![if state.value == 0 { 0 } else { 1 }]
}
}
fn main() {
println!("=== Example 03: Custom Observers ===\n");
let s1 = Counter::new(0, 5);
let s2 = Counter::new(3, 5);
let s3 = Counter::new(3, 10); let s4 = Counter::new(5, 5);
let full = FullObserver;
let value = ValueObserver;
let zero = NonZeroObserver;
println!("Full observer:");
println!(" s1 (0/5): {:?}", full.observe(&s1));
println!(" s2 (3/5): {:?}", full.observe(&s2));
println!(" s3 (3/10): {:?}", full.observe(&s3));
println!(" s1 == s2? {}", full.observe(&s1) == full.observe(&s2));
println!("\nValue observer:");
println!(" s1 (0/5): {:?}", value.observe(&s1));
println!(" s2 (3/5): {:?}", value.observe(&s2));
println!(" s3 (3/10): {:?}", value.observe(&s3));
println!(" s2 == s3? {}", value.observe(&s2) == value.observe(&s3));
println!("\nZero observer:");
println!(" s1 (0/5): {:?}", zero.observe(&s1));
println!(" s2 (3/5): {:?}", zero.observe(&s2));
println!(" s4 (5/5): {:?}", zero.observe(&s4));
println!(" s2 == s4? {}", zero.observe(&s2) == zero.observe(&s4));
println!("\nDynamic sufficiency:");
println!(" Full observer: {} distinct values", 4);
println!(" Value observer: {} distinct values", 3); println!(" Zero observer: {} distinct values", 2); println!(" Coarser observers lose information.");
println!(" Whether this matters depends on the dynamics.");
println!("\n✓ Three observers at different granularities.");
}