| using System.Collections.Generic; | 
| using System.Linq; | 
| using UnityEditor.MemoryProfiler; | 
| using System; | 
| using UnityEngine; | 
|   | 
| namespace MemoryProfilerWindow | 
| { | 
|     class CrawlDataUnpacker | 
|     { | 
|         public static CrawledMemorySnapshot Unpack(PackedCrawlerData packedCrawlerData) | 
|         { | 
|             var packedSnapshot = packedCrawlerData.packedMemorySnapshot; | 
|   | 
|             var result = new CrawledMemorySnapshot | 
|             { | 
|                 nativeObjects = packedSnapshot.nativeObjects.Select(packedNativeUnityEngineObject => UnpackNativeUnityEngineObject(packedSnapshot, packedNativeUnityEngineObject)).ToArray(), | 
|                 managedObjects = packedCrawlerData.managedObjects.Select(pm => UnpackManagedObject(packedSnapshot, pm)).ToArray(), | 
|                 gcHandles = packedSnapshot.gcHandles.Select(pgc => UnpackGCHandle(packedSnapshot)).ToArray(), | 
|                 staticFields = packedSnapshot.typeDescriptions.Where(t => t.staticFieldBytes != null & t.staticFieldBytes.Length > 0).Select(t => UnpackStaticFields(t)).ToArray(), | 
|                 typeDescriptions = packedSnapshot.typeDescriptions, | 
|                 managedHeap = packedSnapshot.managedHeapSections, | 
|                 nativeTypes = packedSnapshot.nativeTypes, | 
|                 virtualMachineInformation = packedSnapshot.virtualMachineInformation | 
|             }; | 
|   | 
|             result.FinishSnapshot(); | 
|   | 
|             var referencesLists = MakeTempLists(result.allObjects); | 
|             var referencedByLists = MakeTempLists(result.allObjects); | 
|   | 
|             foreach (var connection in packedCrawlerData.connections) | 
|             { | 
|                 referencesLists[connection.@from].Add(result.allObjects[connection.to]); | 
|                 referencedByLists[connection.to].Add(result.allObjects[connection.@from]); | 
|             } | 
|   | 
|             for (var i = 0; i != result.allObjects.Length; i++) | 
|             { | 
|                 result.allObjects[i].references = referencesLists[i].ToArray(); | 
|                 result.allObjects[i].referencedBy = referencedByLists[i].ToArray(); | 
|             } | 
|   | 
|             return result; | 
|         } | 
|   | 
|         static List<ThingInMemory>[] MakeTempLists(ThingInMemory[] combined) | 
|         { | 
|             var referencesLists = new List<ThingInMemory>[combined.Length]; | 
|             for (int i = 0; i != referencesLists.Length; i++) | 
|                 referencesLists[i] = new List<ThingInMemory>(4); | 
|             return referencesLists; | 
|         } | 
|   | 
|         static StaticFields UnpackStaticFields(TypeDescription typeDescription) | 
|         { | 
|             return new StaticFields() | 
|                    { | 
|                        typeDescription = typeDescription, | 
|                        caption = "static fields of " + typeDescription.name, | 
|                        size = typeDescription.staticFieldBytes.Length | 
|                    }; | 
|         } | 
|   | 
|         static GCHandle UnpackGCHandle(PackedMemorySnapshot packedSnapshot) | 
|         { | 
|             return new GCHandle() { size = packedSnapshot.virtualMachineInformation.pointerSize, caption = "gchandle" }; | 
|         } | 
|   | 
|         static ManagedObject UnpackManagedObject(PackedMemorySnapshot packedSnapshot, PackedManagedObject pm) | 
|         { | 
|             var typeDescription = packedSnapshot.typeDescriptions[pm.typeIndex]; | 
|             return new ManagedObject() { address = pm.address, size = pm.size, typeDescription = typeDescription, caption = typeDescription.name }; | 
|         } | 
|   | 
|         static NativeUnityEngineObject UnpackNativeUnityEngineObject(PackedMemorySnapshot packedSnapshot, PackedNativeUnityEngineObject packedNativeUnityEngineObject) | 
|         { | 
| #if UNITY_5_6_OR_NEWER | 
|             var classId = packedNativeUnityEngineObject.nativeTypeArrayIndex; | 
| #else | 
|             var classId = packedNativeUnityEngineObject.classId; | 
| #endif | 
|             var className = packedSnapshot.nativeTypes[classId].name; | 
|   | 
|             return new NativeUnityEngineObject() | 
|                    { | 
|                        instanceID = packedNativeUnityEngineObject.instanceId, | 
|                        classID = classId, | 
|                        className = className, | 
|                        name = packedNativeUnityEngineObject.name, | 
|                        caption = packedNativeUnityEngineObject.name + "(" + className + ")", | 
|                        size = packedNativeUnityEngineObject.size, | 
|                        isPersistent = packedNativeUnityEngineObject.isPersistent, | 
|                        isDontDestroyOnLoad = packedNativeUnityEngineObject.isDontDestroyOnLoad, | 
|                        isManager = packedNativeUnityEngineObject.isManager, | 
|                        hideFlags = packedNativeUnityEngineObject.hideFlags | 
|                    }; | 
|         } | 
|     } | 
|   | 
|     [System.Serializable] | 
|     internal class PackedCrawlerData | 
|     { | 
|         public bool valid; | 
|         public PackedMemorySnapshot packedMemorySnapshot; | 
|         public StartIndices startIndices; | 
|         public PackedManagedObject[] managedObjects; | 
|         public TypeDescription[] typesWithStaticFields; | 
|         public Connection[] connections; | 
|   | 
|         public PackedCrawlerData(PackedMemorySnapshot packedMemorySnapshot) | 
|         { | 
|             this.packedMemorySnapshot = packedMemorySnapshot; | 
|             typesWithStaticFields = packedMemorySnapshot.typeDescriptions.Where(t => t.staticFieldBytes != null && t.staticFieldBytes.Length > 0).ToArray(); | 
|             startIndices = new StartIndices(this.packedMemorySnapshot.gcHandles.Length, this.packedMemorySnapshot.nativeObjects.Length, typesWithStaticFields.Length); | 
|             valid = true; | 
|         } | 
|     } | 
|   | 
|     [System.Serializable] | 
|     internal class StartIndices | 
|     { | 
|         [SerializeField] | 
|         private int _gcHandleCount; | 
|         [SerializeField] | 
|         private int _nativeObjectCount; | 
|         [SerializeField] | 
|         private int _staticFieldsCount; | 
|   | 
|         public StartIndices(int gcHandleCount, int nativeObjectCount, int staticFieldsCount) | 
|         { | 
|             _gcHandleCount = gcHandleCount; | 
|             _nativeObjectCount = nativeObjectCount; | 
|             _staticFieldsCount = staticFieldsCount; | 
|         } | 
|   | 
|         public int OfFirstGCHandle { get { return 0; } } | 
|         public int OfFirstNativeObject { get { return OfFirstGCHandle + _gcHandleCount; } } | 
|         public int OfFirstStaticFields { get { return OfFirstNativeObject + _nativeObjectCount; } } | 
|         public int OfFirstManagedObject { get { return OfFirstStaticFields + _staticFieldsCount; } } | 
|     } | 
| } |