BsManagedSerializableDiff.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #pragma once
  2. #include "BsScriptEnginePrerequisites.h"
  3. #include "BsIReflectable.h"
  4. namespace BansheeEngine
  5. {
  6. /**
  7. * @brief Handles creation and applying of managed diffs. A diff contains differences
  8. * between two objects of identical types. If the initial state of an object
  9. * is known the recorded differences can be saved and applied to the original
  10. * state to restore the modified object.
  11. *
  12. * Differences are recorded per primitive field in an object.
  13. * Complex objects are recursed. Special handling is implemented
  14. * to properly generate diffs for arrays, lists and dictionaries.
  15. *
  16. * All primitive types supported by managed serialization are supported.
  17. * (see ScriptPrimitiveType)
  18. */
  19. class BS_SCR_BE_EXPORT ManagedSerializableDiff : public IReflectable
  20. {
  21. public:
  22. /**
  23. * @brief A base class for all modifications recorded in a diff.
  24. */
  25. struct BS_SCR_BE_EXPORT Modification : public IReflectable
  26. {
  27. virtual ~Modification();
  28. /************************************************************************/
  29. /* RTTI */
  30. /************************************************************************/
  31. public:
  32. friend class ModificationRTTI;
  33. static RTTITypeBase* getRTTIStatic();
  34. virtual RTTITypeBase* getRTTI() const override;
  35. };
  36. /**
  37. * @brief Contains a modification of a specific field in an object along
  38. * with information about the field and its parent object.
  39. */
  40. struct BS_SCR_BE_EXPORT ModifiedField : public IReflectable
  41. {
  42. ModifiedField() { }
  43. ModifiedField(const ManagedSerializableTypeInfoPtr& parentType,
  44. const ManagedSerializableFieldInfoPtr& fieldType, const SPtr<Modification>& modification);
  45. ManagedSerializableTypeInfoPtr parentType; /**< Type of the parent object the field belongs to. */
  46. ManagedSerializableFieldInfoPtr fieldType; /**< Data type of the field. */
  47. SPtr<Modification> modification; /**< Recorded modification(s) on the field. */
  48. /************************************************************************/
  49. /* RTTI */
  50. /************************************************************************/
  51. public:
  52. friend class ModifiedFieldRTTI;
  53. static RTTITypeBase* getRTTIStatic();
  54. virtual RTTITypeBase* getRTTI() const override;
  55. };
  56. /**
  57. * @brief Represents a single modified array or list entry.
  58. */
  59. struct BS_SCR_BE_EXPORT ModifiedArrayEntry : public IReflectable
  60. {
  61. ModifiedArrayEntry() { }
  62. ModifiedArrayEntry(UINT32 idx, const SPtr<Modification>& modification);
  63. UINT32 idx; /**< Index of the array/list entry that is modified. */
  64. SPtr<Modification> modification; /**< Recorded modification(s) on the entry. */
  65. /************************************************************************/
  66. /* RTTI */
  67. /************************************************************************/
  68. public:
  69. friend class ModifiedArrayEntryRTTI;
  70. static RTTITypeBase* getRTTIStatic();
  71. virtual RTTITypeBase* getRTTI() const override;
  72. };
  73. /**
  74. * @brief Represents a single modified dictionary entry.
  75. */
  76. struct BS_SCR_BE_EXPORT ModifiedDictionaryEntry : public IReflectable
  77. {
  78. ModifiedDictionaryEntry() { }
  79. ModifiedDictionaryEntry(const ManagedSerializableFieldDataPtr& key, const SPtr<Modification>& modification);
  80. ManagedSerializableFieldDataPtr key; /**< Serialized value of the key for the modified entry. */
  81. SPtr<Modification> modification; /**< Recorded modification(s) on the dictionary entry value. */
  82. /************************************************************************/
  83. /* RTTI */
  84. /************************************************************************/
  85. public:
  86. friend class ModifiedArrayEntryRTTI;
  87. static RTTITypeBase* getRTTIStatic();
  88. virtual RTTITypeBase* getRTTI() const override;
  89. };
  90. /**
  91. * @brief Contains data about all modifications in a single complex object.
  92. * (aside from arrays, list, dictionaries which are handled specially).
  93. */
  94. struct BS_SCR_BE_EXPORT ModifiedObject : Modification
  95. {
  96. static SPtr<ModifiedObject> create();
  97. Vector<ModifiedField> entries; /**< A list of entries containing each modified field in the object. */
  98. /************************************************************************/
  99. /* RTTI */
  100. /************************************************************************/
  101. public:
  102. friend class ModifiedObjectRTTI;
  103. static RTTITypeBase* getRTTIStatic();
  104. virtual RTTITypeBase* getRTTI() const override;
  105. };
  106. /**
  107. * @brief Contains data about all modifications in an array or a list.
  108. */
  109. struct BS_SCR_BE_EXPORT ModifiedArray : Modification
  110. {
  111. static SPtr<ModifiedArray> create();
  112. Vector<ModifiedArrayEntry> entries; /**< A list of all modified array/list entries along with their indices. */
  113. Vector<UINT32> origSizes; /**< Original size of the array/list (one size per dimension). */
  114. Vector<UINT32> newSizes; /**< New size of the array/list (one size per dimension). */
  115. /************************************************************************/
  116. /* RTTI */
  117. /************************************************************************/
  118. public:
  119. friend class ModifiedArrayRTTI;
  120. static RTTITypeBase* getRTTIStatic();
  121. virtual RTTITypeBase* getRTTI() const override;
  122. };
  123. /**
  124. * @brief Contains data about all modifications in a dictionary.
  125. */
  126. struct BS_SCR_BE_EXPORT ModifiedDictionary : Modification
  127. {
  128. static SPtr<ModifiedDictionary> create();
  129. Vector<ModifiedDictionaryEntry> entries; /**< A list of modified entries in the dictionary. */
  130. Vector<ManagedSerializableFieldDataPtr> removed; /**< A list of keys for entries that were removed from the dictionary. */
  131. /************************************************************************/
  132. /* RTTI */
  133. /************************************************************************/
  134. public:
  135. friend class ModifiedDictionaryRTTI;
  136. static RTTITypeBase* getRTTIStatic();
  137. virtual RTTITypeBase* getRTTI() const override;
  138. };
  139. /**
  140. * @brief Contains data about modification of a primitive field.
  141. * (i.e. fields new value)
  142. */
  143. struct BS_SCR_BE_EXPORT ModifiedEntry : Modification
  144. {
  145. ModifiedEntry() { }
  146. ModifiedEntry(const ManagedSerializableFieldDataPtr& value);
  147. static SPtr<ModifiedEntry> create(const ManagedSerializableFieldDataPtr& value);
  148. ManagedSerializableFieldDataPtr value;
  149. /************************************************************************/
  150. /* RTTI */
  151. /************************************************************************/
  152. public:
  153. friend class ModifiedEntryRTTI;
  154. static RTTITypeBase* getRTTIStatic();
  155. virtual RTTITypeBase* getRTTI() const override;
  156. };
  157. public:
  158. ManagedSerializableDiff();
  159. ~ManagedSerializableDiff();
  160. /**
  161. * @brief Generates a new managed diff object by comparing two objects of the same type. Callers must
  162. * ensure both objects are not null and of identical types.
  163. *
  164. * @param oldObj Original object. This is the object you can apply the diff to to convert it to \p newObj.
  165. * @param newObj New modified object. Any values in this object that differ from the original object will be
  166. * recorded in the diff.
  167. *
  168. * @return Returns null if objects are identical.
  169. */
  170. static ManagedSerializableDiffPtr create(const ManagedSerializableObjectPtr& oldObj, const ManagedSerializableObjectPtr& newObj);
  171. /**
  172. * @brief Applies the diff data stored in this object to the specified object, modifying all
  173. * fields in the object to correspond to the stored diff data.
  174. */
  175. void apply(const ManagedSerializableObjectPtr& obj);
  176. private:
  177. /**
  178. * @brief Recursively generates a diff between all fields of the specified objects. Returns null if objects are identical.
  179. */
  180. SPtr<ModifiedObject> generateDiff(const ManagedSerializableObjectPtr& oldObj, const ManagedSerializableObjectPtr& newObj);
  181. /**
  182. * @brief Generates a diff between two fields. Fields can be of any type and the system will generate the diff appropriately.
  183. * Diff is generated recursively on all complex objects as well. Returns null if fields contain identical data.
  184. */
  185. SPtr<Modification> generateDiff(const ManagedSerializableFieldDataPtr& oldData, const ManagedSerializableFieldDataPtr& newData,
  186. UINT32 fieldTypeId);
  187. /**
  188. * @brief Applies an object modification to a managed object. Modifications are applied recursively.
  189. *
  190. * @param mod Object modification to apply.
  191. * @param obj Object to apply the modification to.
  192. *
  193. * @return New field data in the case modification needed the object to be re-created instead of just modified.
  194. */
  195. ManagedSerializableFieldDataPtr applyDiff(const SPtr<ModifiedObject>& mod, const ManagedSerializableObjectPtr& obj);
  196. /**
  197. * @brief Applies an array modification to a managed array. Modifications are applied recursively.
  198. *
  199. * @param mod Array modification to apply.
  200. * @param obj Array to apply the modification to.
  201. *
  202. * @return New field data in the case modification needed the array to be re-created instead of just modified.
  203. */
  204. ManagedSerializableFieldDataPtr applyDiff(const SPtr<ModifiedArray>& mod, const ManagedSerializableArrayPtr& obj);
  205. /**
  206. * @brief Applies an list modification to a managed list. Modifications are applied recursively.
  207. *
  208. * @param mod List modification to apply.
  209. * @param obj List to apply the modification to.
  210. *
  211. * @return New field data in the case modification needed the list to be re-created instead of just modified.
  212. */
  213. ManagedSerializableFieldDataPtr applyDiff(const SPtr<ModifiedArray>& mod, const ManagedSerializableListPtr& obj);
  214. /**
  215. * @brief Applies an dictionary modification to a managed dictionary. Modifications are applied recursively.
  216. *
  217. * @param mod Dictionary modification to apply.
  218. * @param obj Dictionary to apply the modification to.
  219. *
  220. * @return New field data in the case modification needed the dictionary to be re-created instead of just modified.
  221. */
  222. ManagedSerializableFieldDataPtr applyDiff(const SPtr<ModifiedDictionary>& mod, const ManagedSerializableDictionaryPtr& obj);
  223. /**
  224. * @brief Applies a modification to a single field. Field type is determined and the modification is applied
  225. * to the specific field type as needed. Modifications are applied recursively.
  226. *
  227. * @param mod Modification to apply.
  228. * @param fieldType Type of the field we're applying the modification to.
  229. * @param origData Original data of the field.
  230. *
  231. * @return New field data in the case modification needed the field data to be re-created instead of just modified.
  232. */
  233. ManagedSerializableFieldDataPtr applyDiff(const SPtr<Modification>& mod, const ManagedSerializableTypeInfoPtr& fieldType,
  234. const ManagedSerializableFieldDataPtr& origData);
  235. SPtr<ModifiedObject> mModificationRoot;
  236. /************************************************************************/
  237. /* RTTI */
  238. /************************************************************************/
  239. public:
  240. friend class ManagedSerializableDiffRTTI;
  241. static RTTITypeBase* getRTTIStatic();
  242. virtual RTTITypeBase* getRTTI() const override;
  243. };
  244. }