observable-property 0.4.3

A thread-safe observable property implementation for Rust
Documentation
# Batched Updates Feature - Summary


## Overview

Added a new `update_batch` method to `ObservableProperty` that allows updating a property through multiple intermediate states and notifying observers for each transition.

## Method Signature

```rust
pub fn update_batch<F>(&self, f: F) -> Result<(), PropertyError>
where
    F: FnOnce(&mut T) -> Vec<T>
```

## Key Features


### Behavior

1. Captures the initial value
2. Calls the provided function with `&mut T` to get intermediate states
3. Updates the property's value to the final state (last element in returned vector)
4. Notifies observers for each state transition sequentially
5. If empty vector is returned, value remains unchanged and no notifications occur

### Use Cases

- **Animations**: Smooth transitions through intermediate visual states
- **Progressive calculations**: Show progress through multi-step computations
- **State machines**: Record transitions through multiple states
- **Debugging**: Track how a value transforms through complex operations
- **History tracking**: Maintain a record of transformation steps

## Examples


### Basic Animation

```rust
let position = ObservableProperty::new(0);
position.update_batch(|_| vec![25, 50, 75, 100])?;
// Observers notified: 0→25, 25→50, 50→75, 75→100
// Final value: 100
```

### Multi-Step Transformation
```rust
let text = ObservableProperty::new(String::from("hello"));
text.update_batch(|current| {
    let step1 = current.to_uppercase();  // "HELLO"
    let step2 = format!("{}!", step1);   // "HELLO!"
    let step3 = format!("{} WORLD", step2); // "HELLO! WORLD"
    vec![step1, step2, step3]
})?;
```

### Empty Batch (No Changes)
```rust
let value = ObservableProperty::new(42);
value.update_batch(|current| {
    *current = 100; // This is ignored
    Vec::new() // No notifications, value stays 42
})?;
```

## Implementation Details


### Thread Safety

- Lock is held during function execution and state collection
- Observers are notified sequentially after lock is released
- Fully thread-safe, can be called from multiple threads

### Error Handling

- Observer panics are isolated and logged
- Dead weak observers are automatically cleaned up
- Gracefully handles poisoned locks

### Performance

- Lock acquired once for state collection
- All intermediate states stored in memory before notification
- Observers notified outside of lock to prevent blocking

## Testing


### Added 8 Comprehensive Tests

1. `test_update_batch_basic` - Basic functionality with multiple states
2. `test_update_batch_empty_vec` - Empty vector behavior
3. `test_update_batch_single_state` - Single state transition
4. `test_update_batch_string_transformation` - Complex string transformations
5. `test_update_batch_multiple_observers` - Multiple observers receive all notifications
6. `test_update_batch_with_panicking_observer` - Panic isolation
7. `test_update_batch_thread_safety` - Concurrent usage from multiple threads
8. `test_update_batch_with_weak_observers` - Automatic cleanup of dead weak observers

All tests pass successfully ✓

## Example File

Created `examples/update_batch.rs` demonstrating:
- Animation with intermediate positions
- Multi-step string transformation
- Counter with intermediate values
- Temperature gradual increase
- Empty batch behavior
- Fibonacci sequence generation

Run with: `cargo run --example update_batch`

## Documentation

- Comprehensive doc comments with examples
- Follows the same documentation style as existing methods
- All doctests pass ✓
- No documentation warnings ✓

## Compatibility

- Follows existing API patterns
- Consistent error handling with other methods
- Compatible with all observer types (strong, weak, filtered, etc.)
- Works with RAII subscriptions
- No breaking changes to existing API