public void BoxedTest() { Assert.True(RuntimeProperties.IsBoxed((object)1)); }
public static string Dump <T>(ref T value, DumpOptions options, InspectorOptions options2) { switch (options) { case DumpOptions.Info: // var addrTable = new ConsoleTable("Addresses", ""); var addr = Mem.AddressOf(ref value); addrTable.AddRow("Address", addr); if (Mem.TryGetAddressOfHeap(value, out var heap)) { addrTable.AddRow("Address (heap)", heap); } addrTable.Write(ConsoleTableFormat.Minimal); // var infoTable = new ConsoleTable("Sizes", ""); infoTable.AddRow("Intrinsic", Mem.SizeOf <T>()); infoTable.AddRow("Auto", Mem.SizeOf(value, SizeOfOptions.Auto)); infoTable.Write(ConsoleTableFormat.Minimal); // var propTable = new ConsoleTable("Runtime info", ""); propTable.AddRow("Pinnable", RuntimeProperties.IsPinnable(value)); propTable.AddRow("Blittable", RuntimeProperties.IsBlittable(value)); propTable.AddRow("Boxed", RuntimeProperties.IsBoxed(value)); propTable.AddRow("Nil", RuntimeProperties.IsDefault(value)); propTable.AddRow("Uninitialized", RuntimeProperties.IsNullMemory(value)); propTable.AddRow("In GC heap", GCHeap.IsHeapPointer(Mem.AddressOfData(ref value))); return(propTable.ToMinimalString()); case DumpOptions.Sizes: var layoutTable = new ConsoleTable("Size Type", "Value"); var options1 = Enum.GetValues <SizeOfOptions>().ToList(); options1.Remove(SizeOfOptions.Heap); foreach (var option in options1) { var sizeOf = Mem.SizeOf(value, option); if (sizeOf == Native.INVALID) { continue; } layoutTable.AddRow(Enum.GetName(option), sizeOf); } var mt = value.GetMetaType(); if (!mt.RuntimeType.IsValueType) { layoutTable.AddRow(nameof(SizeOfOptions.Heap), Mem.SizeOf(value, SizeOfOptions.Heap)); } return(layoutTable.ToString()); case DumpOptions.Layout: var layoutTable1 = new ConsoleTable(); var flags = EnumHelper.GetSetFlags(options2); if (options2 == InspectorOptions.All) { flags.Remove(InspectorOptions.All); } layoutTable1.AddColumn(flags.Select(Enum.GetName)); // Rewrite options options2 = default; foreach (var flag in flags) { options2 |= flag; } var mt1 = value.GetMetaType(); var fields = mt1.Fields.Where(x => !x.IsStatic); int s = Mem.SizeOf(value, SizeOfOptions.Auto); var p = Mem.AddressOf(ref value); foreach (var metaField in fields) { var rowValues = new List <object>(); if (options2.HasFlag(InspectorOptions.Offset)) { rowValues.Add($"{metaField.Offset:X}"); } if (options2.HasFlag(InspectorOptions.Size)) { rowValues.Add(metaField.Size); } if (options2.HasFlag(InspectorOptions.Type)) { rowValues.Add(metaField.FieldType.Name); } if (options2.HasFlag(InspectorOptions.Name)) { rowValues.Add(metaField.Name); } if (options2.HasFlag(InspectorOptions.Address)) { var addr1 = Mem.AddressOfData(ref value) + metaField.Offset; rowValues.Add(addr1.ToString()); } if (options2.HasFlag(InspectorOptions.Value)) { object fieldVal; if (!mt1.RuntimeType.IsConstructedGenericType) { fieldVal = metaField.Info.GetValue(value); } else { fieldVal = "?"; } rowValues.Add($"{fieldVal}"); } layoutTable1.AddRow(rowValues.ToArray()); } if (value is string str) { for (int i = 1; i < str.Length; i++) { char c = str[i]; var rowValues = new List <object>(); int offsetBase = (i * sizeof(char)); if (options2.HasFlag(InspectorOptions.Offset)) { rowValues.Add($"{offsetBase + RuntimeProperties.StringOverhead - sizeof(char):X}"); } if (options2.HasFlag(InspectorOptions.Size)) { rowValues.Add(sizeof(char)); } if (options2.HasFlag(InspectorOptions.Type)) { rowValues.Add(nameof(Char)); } if (options2.HasFlag(InspectorOptions.Name)) { rowValues.Add($"Char #{i + 1}"); } if (options2.HasFlag(InspectorOptions.Address)) { if (Mem.TryGetAddressOfHeap(value, OffsetOptions.StringData, out var addr2)) { addr2 += offsetBase; rowValues.Add(addr2.ToString()); } } if (options2.HasFlag(InspectorOptions.Value)) { rowValues.Add($"{c}"); } layoutTable1.AddRow(rowValues.ToArray()); } } return(layoutTable1.ToString()); default: throw new ArgumentOutOfRangeException(nameof(options)); } }