use std::any::{Any, TypeId};
pub use cset_derive::Track;
#[derive(Debug)]
pub struct ChangeSet {
pub target_type: TypeId,
pub changes: Vec<Change>,
}
impl ChangeSet {
pub fn new<T: 'static>(changes: Vec<Change>) -> Self {
ChangeSet {
target_type: TypeId::of::<T>(),
changes,
}
}
pub fn for_type<T: 'static>(&self) -> bool {
self.target_type == TypeId::of::<T>()
}
}
#[derive(Debug)]
pub enum ChangeValue {
Value(Box<dyn Any>),
ChangeSet(ChangeSet),
}
#[derive(Debug)]
pub struct Change {
pub field_id: FieldId,
pub value: ChangeValue,
}
#[derive(Debug)]
pub struct DraftField<'b, T: 'static> {
pub original: &'b mut T,
pub draft: Option<T>,
}
impl<'b, T> DraftField<'b, T> {
pub fn new(original: &'b mut T) -> Self {
Self {
original,
draft: None,
}
}
pub fn apply(self, field_idx: FieldId) -> Option<Change> {
self.draft.map(|new_value| {
let old_value = std::mem::replace(self.original, new_value);
let boxed: Box<dyn Any> = Box::new(old_value);
Change {
field_id: field_idx,
value: ChangeValue::Value(boxed),
}
})
}
}
#[derive(Debug, Clone, Default)]
pub struct FieldId(Vec<usize>);
impl FieldId {
pub fn push_field(&self, child_field: usize) -> Self {
let mut new = self.clone();
new.0.push(child_field);
new
}
pub fn field_index(&self, depth: usize) -> usize {
self.0[depth]
}
}