# System.Runtime.InteropServices.Marshalling

``` diff
 namespace System.Runtime.InteropServices.Marshalling {
-    [CLSCompliantAttribute(false)]
-    [CustomTypeMarshallerAttribute(typeof(string), CustomTypeMarshallerKind.Value, BufferSize=256, Features=CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.UnmanagedResources)]
-    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
-    public ref struct AnsiStringMarshaller {
+    [CLSCompliantAttribute(false)]
+    [CustomMarshallerAttribute(typeof(string), MarshalMode.Default, typeof(AnsiStringMarshaller))]
+    [CustomMarshallerAttribute(typeof(string), MarshalMode.ManagedToUnmanagedIn, typeof(AnsiStringMarshaller.ManagedToUnmanagedIn))]
+    public static class AnsiStringMarshaller {
-        [NullableContextAttribute((byte)2)]
-        public AnsiStringMarshaller(string? str);
-        public AnsiStringMarshaller([NullableAttribute((byte)2)] string? str, Span<byte> buffer);
+        [return: NullableAttribute((byte)2)]
+        public unsafe static string? ConvertToManaged(byte* unmanaged);
+        public unsafe static byte* ConvertToUnmanaged([NullableAttribute((byte)2)] string? managed);
+        public unsafe static void Free(byte* unmanaged);
-        public void FreeNative();
-        public unsafe void FromNativeValue(byte* value);
-        [NullableContextAttribute((byte)2)]
-        public string? ToManaged();
-        public unsafe byte* ToNativeValue();
+        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
+        public ref struct ManagedToUnmanagedIn {
+            public static int BufferSize { get; }
+            public void Free();
+            public void FromManaged([NullableAttribute((byte)2)] string? managed, Span<byte> buffer);
+            public unsafe byte* ToUnmanaged();
+        }
     }
-    [CLSCompliantAttribute(false)]
-    [CustomTypeMarshallerAttribute(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder[]), CustomTypeMarshallerKind.LinearCollection, BufferSize=512, Features=CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.UnmanagedResources)]
-    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
-    public ref struct ArrayMarshaller<T> {
-        public ArrayMarshaller(int sizeOfNativeElement);
-        public ArrayMarshaller([NullableAttribute(new byte[]{ (byte)2, (byte)1})] T[]? array, int sizeOfNativeElement);
-        public ArrayMarshaller([NullableAttribute(new byte[]{ (byte)2, (byte)1})] T[]? array, Span<byte> buffer, int sizeOfNativeElement);
-        public void FreeNative();
-        public unsafe void FromNativeValue(byte* value);
-        [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
-        public Span<T> GetManagedValuesDestination(int length);
-        [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
-        public ReadOnlySpan<T> GetManagedValuesSource();
-        public Span<byte> GetNativeValuesDestination();
-        public ReadOnlySpan<byte> GetNativeValuesSource(int length);
-        public ref byte GetPinnableReference();
-        [return: NullableAttribute(new byte[]{ (byte)2, (byte)1})]
-        public T[]? ToManaged();
-        public unsafe byte* ToNativeValue();
-    }
+    [CLSCompliantAttribute(false)]
+    [ContiguousCollectionMarshallerAttribute]
+    [CustomMarshallerAttribute(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.Default, typeof(ArrayMarshaller<,>))]
+    [CustomMarshallerAttribute(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ManagedToUnmanagedIn, typeof(ArrayMarshaller<,>.ManagedToUnmanagedIn))]
+    public static class ArrayMarshaller<T, TUnmanagedElement> where TUnmanagedElement : struct {
+        [return: NullableAttribute(new byte[]{ (byte)2, (byte)1})]
+        public unsafe static T[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements);
+        public unsafe static TUnmanagedElement* AllocateContainerForUnmanagedElements([NullableAttribute(new byte[]{ (byte)2, (byte)1})] T[]? managed, out int numElements);
+        public unsafe static void Free(TUnmanagedElement* unmanaged);
+        [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
+        public static Span<T> GetManagedValuesDestination([NullableAttribute(new byte[]{ (byte)2, (byte)1})] T[]? managed);
+        [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
+        public static ReadOnlySpan<T> GetManagedValuesSource([NullableAttribute(new byte[]{ (byte)2, (byte)1})] T[]? managed);
+        public unsafe static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements);
+        public unsafe static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements);
+        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+        public ref struct ManagedToUnmanagedIn {
+            public static int BufferSize { get; }
+            public void Free();
+            public void FromManaged([NullableAttribute(new byte[]{ (byte)2, (byte)1})] T[]? array, Span<TUnmanagedElement> buffer);
+            [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
+            public ReadOnlySpan<T> GetManagedValuesSource();
+            public ref TUnmanagedElement GetPinnableReference();
+            [NullableContextAttribute((byte)1)]
+            public static ref T GetPinnableReference([NullableAttribute(new byte[]{ (byte)2, (byte)1})] T[]? array);
+            public Span<TUnmanagedElement> GetUnmanagedValuesDestination();
+            public unsafe TUnmanagedElement* ToUnmanaged();
+        }
+    }
-    [CLSCompliantAttribute(false)]
-    [CustomTypeMarshallerAttribute(typeof(string), CustomTypeMarshallerKind.Value, BufferSize=256, Features=CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.UnmanagedResources)]
-    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
-    public ref struct BStrStringMarshaller {
+    [CLSCompliantAttribute(false)]
+    [CustomMarshallerAttribute(typeof(string), MarshalMode.Default, typeof(BStrStringMarshaller))]
+    [CustomMarshallerAttribute(typeof(string), MarshalMode.ManagedToUnmanagedIn, typeof(BStrStringMarshaller.ManagedToUnmanagedIn))]
+    public static class BStrStringMarshaller {
-        [NullableContextAttribute((byte)2)]
-        public BStrStringMarshaller(string? str);
-        public BStrStringMarshaller([NullableAttribute((byte)2)] string? str, Span<ushort> buffer);
+        [return: NullableAttribute((byte)2)]
+        public unsafe static string? ConvertToManaged(ushort* unmanaged);
+        public unsafe static ushort* ConvertToUnmanaged([NullableAttribute((byte)2)] string? managed);
+        public unsafe static void Free(ushort* unmanaged);
-        public void FreeNative();
-        public unsafe void FromNativeValue(void* value);
-        [NullableContextAttribute((byte)2)]
-        public string? ToManaged();
-        public unsafe void* ToNativeValue();
+        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
+        public ref struct ManagedToUnmanagedIn {
+            public static int BufferSize { get; }
+            public void Free();
+            public void FromManaged([NullableAttribute((byte)2)] string? managed, Span<byte> buffer);
+            public unsafe ushort* ToUnmanaged();
+        }
     }
+    [AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Struct)]
+    public sealed class ContiguousCollectionMarshallerAttribute : Attribute {
+        public ContiguousCollectionMarshallerAttribute();
+    }
+    [AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple=true)]
+    [NullableAttribute((byte)0)]
+    [NullableContextAttribute((byte)1)]
+    public sealed class CustomMarshallerAttribute : Attribute {
+        public CustomMarshallerAttribute(Type managedType, MarshalMode marshalMode, Type marshallerType);
+        public Type ManagedType { get; }
+        public Type MarshallerType { get; }
+        public MarshalMode MarshalMode { get; }
+        [NullableContextAttribute((byte)0)]
+        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
+        public struct GenericPlaceholder
+    }
-    [AttributeUsageAttribute(AttributeTargets.Struct)]
-    [NullableAttribute((byte)0)]
-    [NullableContextAttribute((byte)1)]
-    public sealed class CustomTypeMarshallerAttribute : Attribute {
-        public CustomTypeMarshallerAttribute(Type managedType, CustomTypeMarshallerKind marshallerKind = CustomTypeMarshallerKind.Value);
-        public int BufferSize { get; set; }
-        public CustomTypeMarshallerDirection Direction { get; set; }
-        public CustomTypeMarshallerFeatures Features { get; set; }
-        public Type ManagedType { get; }
-        public CustomTypeMarshallerKind MarshallerKind { get; }
-        [NullableContextAttribute((byte)0)]
-        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
-        public struct GenericPlaceholder
-    }
-    [FlagsAttribute]
-    public enum CustomTypeMarshallerDirection {
-        In = 1,
-        [EditorBrowsableAttribute(EditorBrowsableState.Never)]
-        None = 0,
-        Out = 2,
-        Ref = 3,
-    }
-    [FlagsAttribute]
-    public enum CustomTypeMarshallerFeatures {
-        CallerAllocatedBuffer = 2,
-        None = 0,
-        TwoStageMarshalling = 4,
-        UnmanagedResources = 1,
-    }
-    public enum CustomTypeMarshallerKind {
-        LinearCollection = 1,
-        Value = 0,
-    }
+    public enum MarshalMode {
+        Default = 0,
+        ElementIn = 7,
+        ElementOut = 9,
+        ElementRef = 8,
+        ManagedToUnmanagedIn = 1,
+        ManagedToUnmanagedOut = 3,
+        ManagedToUnmanagedRef = 2,
+        UnmanagedToManagedIn = 4,
+        UnmanagedToManagedOut = 6,
+        UnmanagedToManagedRef = 5,
+    }
-    [CLSCompliantAttribute(false)]
-    [CustomTypeMarshallerAttribute(typeof(CustomTypeMarshallerAttribute.GenericPlaceholder*[]), CustomTypeMarshallerKind.LinearCollection, BufferSize=512, Features=CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.UnmanagedResources)]
-    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
-    public ref struct PointerArrayMarshaller<T> where T : struct {
-        public PointerArrayMarshaller(int sizeOfNativeElement);
-        public PointerArrayMarshaller([NullableAttribute(new byte[]{ (byte)2, (byte)0, (byte)0})] T*[]? array, int sizeOfNativeElement);
-        public PointerArrayMarshaller([NullableAttribute(new byte[]{ (byte)2, (byte)0, (byte)0})] T*[]? array, Span<byte> buffer, int sizeOfNativeElement);
-        public void FreeNative();
-        public unsafe void FromNativeValue(byte* value);
-        public Span<IntPtr> GetManagedValuesDestination(int length);
-        public ReadOnlySpan<IntPtr> GetManagedValuesSource();
-        public Span<byte> GetNativeValuesDestination();
-        public ReadOnlySpan<byte> GetNativeValuesSource(int length);
-        public ref byte GetPinnableReference();
-        [return: NullableAttribute(new byte[]{ (byte)2, (byte)0, (byte)0})]
-        public T*[]? ToManaged();
-        public unsafe byte* ToNativeValue();
-    }
+    [CLSCompliantAttribute(false)]
+    [ContiguousCollectionMarshallerAttribute]
+    [CustomMarshallerAttribute(typeof(CustomMarshallerAttribute.GenericPlaceholder*[]), MarshalMode.Default, typeof(PointerArrayMarshaller<,>))]
+    [CustomMarshallerAttribute(typeof(CustomMarshallerAttribute.GenericPlaceholder*[]), MarshalMode.ManagedToUnmanagedIn, typeof(PointerArrayMarshaller<,>.ManagedToUnmanagedIn))]
+    public static class PointerArrayMarshaller<T, TUnmanagedElement> where T : struct where TUnmanagedElement : struct {
+        [return: NullableAttribute(new byte[]{ (byte)2, (byte)0, (byte)0})]
+        public unsafe static T*[]? AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements);
+        public unsafe static TUnmanagedElement* AllocateContainerForUnmanagedElements([NullableAttribute(new byte[]{ (byte)2, (byte)0, (byte)0})] T*[]? managed, out int numElements);
+        public unsafe static void Free(TUnmanagedElement* unmanaged);
+        public static Span<IntPtr> GetManagedValuesDestination([NullableAttribute(new byte[]{ (byte)2, (byte)0, (byte)0})] T*[]? managed);
+        public static ReadOnlySpan<IntPtr> GetManagedValuesSource([NullableAttribute(new byte[]{ (byte)2, (byte)0, (byte)0})] T*[]? managed);
+        public unsafe static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements);
+        public unsafe static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements);
+        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+        public ref struct ManagedToUnmanagedIn {
+            public static int BufferSize { get; }
+            public void Free();
+            public void FromManaged([NullableAttribute(new byte[]{ (byte)2, (byte)0, (byte)0})] T*[]? array, Span<TUnmanagedElement> buffer);
+            public ReadOnlySpan<IntPtr> GetManagedValuesSource();
+            public ref TUnmanagedElement GetPinnableReference();
+            public static ref byte GetPinnableReference([NullableAttribute(new byte[]{ (byte)2, (byte)0, (byte)0})] T*[]? array);
+            public Span<TUnmanagedElement> GetUnmanagedValuesDestination();
+            public unsafe TUnmanagedElement* ToUnmanaged();
+        }
+    }
+    [CLSCompliantAttribute(false)]
+    [ContiguousCollectionMarshallerAttribute]
+    [CustomMarshallerAttribute(typeof(ReadOnlySpan<>), MarshalMode.ManagedToUnmanagedIn, typeof(ReadOnlySpanMarshaller<,>.ManagedToUnmanagedIn))]
+    [CustomMarshallerAttribute(typeof(ReadOnlySpan<>), MarshalMode.UnmanagedToManagedOut, typeof(ReadOnlySpanMarshaller<,>.UnmanagedToManagedOut))]
+    public static class ReadOnlySpanMarshaller<T, TUnmanagedElement> where TUnmanagedElement : struct {
+        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+        public ref struct ManagedToUnmanagedIn {
+            public static int BufferSize { get; }
+            public void Free();
+            public void FromManaged([NullableAttribute(new byte[]{ (byte)0, (byte)1})] ReadOnlySpan<T> managed, Span<TUnmanagedElement> buffer);
+            [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
+            public ReadOnlySpan<T> GetManagedValuesSource();
+            public ref TUnmanagedElement GetPinnableReference();
+            [NullableContextAttribute((byte)1)]
+            public static ref T GetPinnableReference([NullableAttribute(new byte[]{ (byte)0, (byte)1})] ReadOnlySpan<T> managed);
+            public Span<TUnmanagedElement> GetUnmanagedValuesDestination();
+            public unsafe TUnmanagedElement* ToUnmanaged();
+        }
+        public static class UnmanagedToManagedOut {
+            public unsafe static TUnmanagedElement* AllocateContainerForUnmanagedElements([NullableAttribute(new byte[]{ (byte)0, (byte)1})] ReadOnlySpan<T> managed, out int numElements);
+            [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
+            public static ReadOnlySpan<T> GetManagedValuesSource([NullableAttribute(new byte[]{ (byte)0, (byte)1})] ReadOnlySpan<T> managed);
+            public unsafe static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements);
+        }
+    }
+    [CLSCompliantAttribute(false)]
+    [ContiguousCollectionMarshallerAttribute]
+    [CustomMarshallerAttribute(typeof(Span<>), MarshalMode.Default, typeof(SpanMarshaller<,>))]
+    [CustomMarshallerAttribute(typeof(Span<>), MarshalMode.ManagedToUnmanagedIn, typeof(SpanMarshaller<,>.ManagedToUnmanagedIn))]
+    public static class SpanMarshaller<T, TUnmanagedElement> where TUnmanagedElement : struct {
+        [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
+        public unsafe static Span<T> AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements);
+        public unsafe static TUnmanagedElement* AllocateContainerForUnmanagedElements([NullableAttribute(new byte[]{ (byte)0, (byte)1})] Span<T> managed, out int numElements);
+        public unsafe static void Free(TUnmanagedElement* unmanaged);
+        [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
+        public static Span<T> GetManagedValuesDestination([NullableAttribute(new byte[]{ (byte)0, (byte)1})] Span<T> managed);
+        [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
+        public static ReadOnlySpan<T> GetManagedValuesSource([NullableAttribute(new byte[]{ (byte)0, (byte)1})] Span<T> managed);
+        public unsafe static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements);
+        public unsafe static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TUnmanagedElement* unmanaged, int numElements);
+        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+        public ref struct ManagedToUnmanagedIn {
+            public static int BufferSize { get; }
+            public void Free();
+            public void FromManaged([NullableAttribute(new byte[]{ (byte)0, (byte)1})] Span<T> managed, Span<TUnmanagedElement> buffer);
+            [return: NullableAttribute(new byte[]{ (byte)0, (byte)1})]
+            public ReadOnlySpan<T> GetManagedValuesSource();
+            public ref TUnmanagedElement GetPinnableReference();
+            [NullableContextAttribute((byte)1)]
+            public static ref T GetPinnableReference([NullableAttribute(new byte[]{ (byte)0, (byte)1})] Span<T> managed);
+            public Span<TUnmanagedElement> GetUnmanagedValuesDestination();
+            public unsafe TUnmanagedElement* ToUnmanaged();
+        }
+    }
-    [CLSCompliantAttribute(false)]
-    [CustomTypeMarshallerAttribute(typeof(string), CustomTypeMarshallerKind.Value, Features=CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.UnmanagedResources)]
-    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
-    public ref struct Utf16StringMarshaller {
+    [CLSCompliantAttribute(false)]
+    [CustomMarshallerAttribute(typeof(string), MarshalMode.Default, typeof(Utf16StringMarshaller))]
+    public static class Utf16StringMarshaller {
-        [NullableContextAttribute((byte)2)]
-        public Utf16StringMarshaller(string? str);
+        [return: NullableAttribute((byte)2)]
+        public unsafe static string? ConvertToManaged(ushort* unmanaged);
+        public unsafe static ushort* ConvertToUnmanaged([NullableAttribute((byte)2)] string? managed);
+        public unsafe static void Free(ushort* unmanaged);
-        public void FreeNative();
-        public unsafe void FromNativeValue(void* value);
+        [NullableContextAttribute((byte)2)]
+        public static ref readonly char GetPinnableReference(string? str);
-        [NullableContextAttribute((byte)2)]
-        public string? ToManaged();
-        public unsafe void* ToNativeValue();
     }
-    [CLSCompliantAttribute(false)]
-    [CustomTypeMarshallerAttribute(typeof(string), CustomTypeMarshallerKind.Value, BufferSize=256, Features=CustomTypeMarshallerFeatures.CallerAllocatedBuffer | CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.UnmanagedResources)]
-    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
-    public ref struct Utf8StringMarshaller {
+    [CLSCompliantAttribute(false)]
+    [CustomMarshallerAttribute(typeof(string), MarshalMode.Default, typeof(Utf8StringMarshaller))]
+    [CustomMarshallerAttribute(typeof(string), MarshalMode.ManagedToUnmanagedIn, typeof(Utf8StringMarshaller.ManagedToUnmanagedIn))]
+    public static class Utf8StringMarshaller {
-        [NullableContextAttribute((byte)2)]
-        public Utf8StringMarshaller(string? str);
-        public Utf8StringMarshaller([NullableAttribute((byte)2)] string? str, Span<byte> buffer);
+        [return: NullableAttribute((byte)2)]
+        public unsafe static string? ConvertToManaged(byte* unmanaged);
+        public unsafe static byte* ConvertToUnmanaged([NullableAttribute((byte)2)] string? managed);
+        public unsafe static void Free(byte* unmanaged);
-        public void FreeNative();
-        public unsafe void FromNativeValue(byte* value);
-        [NullableContextAttribute((byte)2)]
-        public string? ToManaged();
-        public unsafe byte* ToNativeValue();
+        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
+        public ref struct ManagedToUnmanagedIn {
+            public static int BufferSize { get; }
+            public void Free();
+            public void FromManaged([NullableAttribute((byte)2)] string? managed, Span<byte> buffer);
+            public unsafe byte* ToUnmanaged();
+        }
     }
 }
```

