using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using static Python.Runtime.Runtime;
namespace Python.Runtime
{
public static class RuntimeData
{
private static Type _formatterType;
public static Type FormatterType
{
get => _formatterType;
set
{
if (!typeof(IFormatter).IsAssignableFrom(value))
{
throw new ArgumentException("Not a type implemented IFormatter");
}
_formatterType = value;
}
}
public static ICLRObjectStorer WrappersStorer { get; set; }
///
/// Clears the old "clr_data" entry if a previous one is present.
///
static void ClearCLRData ()
{
BorrowedReference capsule = PySys_GetObject("clr_data");
if (!capsule.IsNull)
{
IntPtr oldData = PyCapsule_GetPointer(capsule, IntPtr.Zero);
PyMem_Free(oldData);
PyCapsule_SetPointer(capsule, IntPtr.Zero);
}
}
internal static void Stash()
{
var metaStorage = new RuntimeDataStorage();
MetaType.SaveRuntimeData(metaStorage);
var importStorage = new RuntimeDataStorage();
ImportHook.SaveRuntimeData(importStorage);
var typeStorage = new RuntimeDataStorage();
TypeManager.SaveRuntimeData(typeStorage);
var clsStorage = new RuntimeDataStorage();
ClassManager.SaveRuntimeData(clsStorage);
var moduleStorage = new RuntimeDataStorage();
SaveRuntimeDataModules(moduleStorage);
var objStorage = new RuntimeDataStorage();
SaveRuntimeDataObjects(objStorage);
var runtimeStorage = new RuntimeDataStorage();
runtimeStorage.AddValue("meta", metaStorage);
runtimeStorage.AddValue("import", importStorage);
runtimeStorage.AddValue("types", typeStorage);
runtimeStorage.AddValue("classes", clsStorage);
runtimeStorage.AddValue("modules", moduleStorage);
runtimeStorage.AddValue("objs", objStorage);
IFormatter formatter = CreateFormatter();
var ms = new MemoryStream();
formatter.Serialize(ms, runtimeStorage);
Debug.Assert(ms.Length _storage ?? (_storage = new RuntimeDataStorage());
///
/// Actions after loaded.
///
[NonSerialized]
private List _postActions;
public List PostActions => _postActions ?? (_postActions = new List());
public void AddPostAction(Action action)
{
PostActions.Add(action);
}
public void ExecutePostActions()
{
if (_postActions == null)
{
return;
}
foreach (var action in _postActions)
{
action();
}
}
}
public class CLRMappedItem
{
public object Instance { get; private set; }
public IList Handles { get; set; }
public bool Stored { get; set; }
public CLRMappedItem(object instance)
{
Instance = instance;
}
}
public interface ICLRObjectStorer
{
ICollection Store(CLRWrapperCollection wrappers, RuntimeDataStorage storage);
CLRWrapperCollection Restore(RuntimeDataStorage storage);
}
public class CLRWrapperCollection : KeyedCollection
{
public bool TryGetValue(object key, out CLRMappedItem value)
{
if (Dictionary == null)
{
value = null;
return false;
}
return Dictionary.TryGetValue(key, out value);
}
protected override object GetKeyForItem(CLRMappedItem item)
{
return item.Instance;
}
}
}