morphix/observe/mod.rs
1use std::ops::DerefMut;
2
3use serde::{Serialize, Serializer};
4
5use crate::Change;
6use crate::adapter::Adapter;
7
8mod shallow;
9mod string;
10mod vec;
11
12pub use shallow::ShallowObserver;
13
14/// A trait for types that can be observed for changes.
15///
16/// Types implementing `Observe` can be wrapped in [Observers] that track mutations.
17/// The trait is typically derived using the `#[derive(Observe)]` macro.
18///
19/// ## Example
20///
21/// ```
22/// use morphix::Observe;
23/// use serde::Serialize;
24///
25/// #[derive(Serialize, Observe)]
26/// struct MyStruct {
27/// field: String,
28/// }
29///
30/// let mut data = MyStruct { field: "value".to_string() };
31/// let mut data_observer = data.observe();
32/// // Mutations through observer are tracked
33/// data_observer.field.push_str(" modified");
34/// ```
35///
36/// [`Observers`]: crate::Observer
37pub trait Observe: Serialize {
38 /// Associated observer type.
39 type Observer<'i>: Observer<'i, Self>
40 where
41 Self: 'i;
42
43 /// Creates an observer for this value.
44 ///
45 /// ## Returns
46 ///
47 /// An observer that wraps this value and tracks mutations.
48 #[inline]
49 fn observe<'i>(&'i mut self) -> Self::Observer<'i> {
50 Self::Observer::observe(self)
51 }
52
53 /// Serializes only the appended portion of the value.
54 ///
55 /// This method is used for optimizing append operations by only
56 /// serializing the new data rather than the entire value.
57 ///
58 /// ## Arguments
59 ///
60 /// - `serializer` - serializer to use
61 /// - `start_index` - index from which to start serialization
62 ///
63 /// ## Errors
64 ///
65 /// - Returns serialization errors from the underlying serializer.
66 ///
67 /// ## Panics
68 ///
69 /// - Panics if called on types that don't support append operations.
70 #[inline]
71 #[expect(unused_variables)]
72 fn serialize_append<S: Serializer>(&self, serializer: S, start_index: usize) -> Result<S::Ok, S::Error> {
73 unimplemented!()
74 }
75}
76
77/// A trait for observer types that wrap and track mutations to values.
78///
79/// Observers provide transparent access to the underlying value while
80/// recording any mutations that occur.
81pub trait Observer<'i, T: ?Sized>: DerefMut<Target = T> {
82 /// Creates a new observer for the given value.
83 ///
84 /// ## Arguments
85 ///
86 /// - `value` - value to observe
87 fn observe(value: &'i mut T) -> Self;
88
89 /// Collects all recorded changes using the specified adapter.
90 ///
91 /// ## Type Parameters
92 ///
93 /// - `A` - adapter to use for serialization
94 ///
95 /// ## Returns
96 ///
97 /// - `None` if no changes were recorded,
98 /// - otherwise a `Change` containing all mutations that occurred.
99 ///
100 /// ## Errors
101 ///
102 /// - Returns an error if serialization fails.
103 fn collect<A: Adapter>(this: Self) -> Result<Option<Change<A>>, A::Error>
104 where
105 T: Serialize;
106}
107
108#[doc(hidden)]
109#[derive(Clone, Copy)]
110pub enum Mutation {
111 Replace,
112 Append(usize),
113}
114
115#[doc(hidden)]
116pub trait MutationObserver<'i, T>: Observer<'i, T> {
117 fn mutation(this: &mut Self) -> &mut Option<Mutation>;
118
119 fn mark_replace(this: &mut Self) {
120 *Self::mutation(this) = Some(Mutation::Replace);
121 }
122
123 fn mark_append(this: &mut Self, start_index: usize) {
124 let mutation = Self::mutation(this);
125 if mutation.is_some() {
126 return;
127 }
128 *mutation = Some(Mutation::Append(start_index));
129 }
130}