1+ using Rewrite . Core ;
2+ using Rewrite . RewriteCSharp ;
3+ using Rewrite . RewriteCSharp . Tree ;
4+ using Rewrite . RewriteJava . Tree ;
5+ using static Rewrite . Rpc . RpcObjectData . ObjectState ;
6+
7+ namespace Rewrite . Rpc ;
8+
9+ public class DeltaSerializer
10+ {
11+ public List < RpcObjectData > Serialize ( object ? before , object ? after )
12+ {
13+ return Serialize ( before , after , after ) ;
14+ }
15+ private List < RpcObjectData > Serialize ( object ? before , object ? after , object ? root )
16+ {
17+ var list = new List < RpcObjectData > ( ) ;
18+ bool shouldWriteEndOfObject = ReferenceEquals ( after , root ) ;
19+
20+ if ( after == null )
21+ {
22+ list . Add ( new ( ) { State = DELETE } ) ;
23+ if ( shouldWriteEndOfObject )
24+ list . Add ( new ( ) { State = END_OF_OBJECT } ) ;
25+ return list ;
26+ }
27+
28+ if ( before == null )
29+ {
30+ // ADD case — send type and value
31+ list . Add ( new ( )
32+ {
33+ State = ADD ,
34+ ValueType = after . GetType ( ) . AssemblyQualifiedName ,
35+ Value = after ,
36+ } ) ;
37+ if ( shouldWriteEndOfObject )
38+ list . Add ( new ( ) { State = END_OF_OBJECT } ) ;
39+ return list ;
40+ }
41+
42+ if ( ! Equals ( before , after ) )
43+ {
44+ list . Add ( new ( )
45+ {
46+ State = CHANGE ,
47+ ValueType = after . GetType ( ) . AssemblyQualifiedName ,
48+ Value = after ,
49+ } ) ;
50+ if ( shouldWriteEndOfObject )
51+ list . Add ( new ( ) { State = END_OF_OBJECT } ) ;
52+ return list ;
53+ }
54+
55+ // If no change:
56+ list . Add ( new ( ) { State = NO_CHANGE } ) ;
57+ if ( shouldWriteEndOfObject )
58+ list . Add ( new ( ) { State = END_OF_OBJECT } ) ;
59+ return list ;
60+ }
61+
62+ public T Deserialize < T > ( object before , List < RpcObjectData > changes )
63+ {
64+ return ( T ) Deserialize ( before , changes ) ;
65+ }
66+
67+ public object Deserialize ( object before , List < RpcObjectData > changes )
68+ {
69+ foreach ( var change in changes )
70+ {
71+ switch ( change . State )
72+ {
73+ case DELETE :
74+ return null ! ;
75+ case NO_CHANGE :
76+ return before ;
77+ case ADD :
78+ case CHANGE :
79+ return change . Value ! ;
80+ case END_OF_OBJECT :
81+ continue ;
82+ default :
83+ throw new InvalidOperationException ( $ "Unsupported state: { change . State } ") ;
84+ }
85+ }
86+
87+ return before ;
88+ }
89+
90+ public abstract class DiffContext
91+ {
92+ public DeltaSerializer Serializer { get ; }
93+ public List < RpcObjectData > Output { get ; }
94+
95+ protected DiffContext ( DeltaSerializer serializer , List < RpcObjectData > output )
96+ {
97+ Serializer = serializer ;
98+ Output = output ;
99+ }
100+
101+ public DiffContext < T > For < T > ( T ? after , T ? before = default )
102+ {
103+ return new DiffContext < T > ( before , after , Serializer , Output ) ;
104+ }
105+ }
106+ public class DiffContext < T > : DiffContext
107+ {
108+ public T ? Before { get ; }
109+ public T ? After { get ; }
110+
111+ public DiffContext ( T ? before , T ? after , DeltaSerializer serializer , List < RpcObjectData > output )
112+ : base ( serializer , output )
113+ {
114+ Before = before ;
115+ After = after ;
116+ }
117+
118+ public void SerializeProperty < TProp > (
119+ Func < T , TProp ? > selector ,
120+ Action < TProp , DiffContext > visitIfChanged )
121+ {
122+ var beforeValue = Before != null ? selector ( Before ) : default ;
123+ var afterValue = After != null ? selector ( After ) : default ;
124+
125+ if ( Equals ( beforeValue , afterValue ) )
126+ {
127+ Output . Add ( new ( ) { State = NO_CHANGE } ) ;
128+ }
129+ else
130+ {
131+ Output . Add ( new ( ) { State = CHANGE } ) ;
132+ var childContext = new DiffContext < TProp > ( beforeValue , afterValue , Serializer , Output ) ;
133+ visitIfChanged ( afterValue ! , childContext ) ;
134+ }
135+ }
136+
137+ public void SerializeLeaf < TProp > ( Func < T , TProp ? > selector )
138+ {
139+ var value = selector ( After ! ) ;
140+ var beforeValue = Before != null ? selector ( Before ) : default ;
141+
142+ if ( Equals ( value , beforeValue ) )
143+ {
144+ Output . Add ( new ( ) { State = NO_CHANGE } ) ;
145+ }
146+ else
147+ {
148+ Output . Add ( new ( )
149+ {
150+ State = CHANGE ,
151+ Value = value ,
152+ ValueType = value ? . GetType ( ) . AssemblyQualifiedName
153+ } ) ;
154+ }
155+ }
156+ }
157+
158+ }
159+
160+ public class CSharpDeltaSerializer : CSharpVisitor < DeltaSerializer . DiffContext >
161+ {
162+ public override J ? VisitClassDeclaration ( Cs . ClassDeclaration node , DeltaSerializer . DiffContext p )
163+ {
164+ var ctx = p . For ( node ) ;
165+ ctx . SerializeProperty ( x => x . Name , ( after , context ) => VisitIdentifier ( after , context ) ) ;
166+ return node ;
167+ }
168+ }
0 commit comments