@@ -308,23 +308,56 @@ public static void CopyTo(this IPythonBuffer buffer, Span<byte> dest) {
308308 }
309309 }
310310
311+ /// <summary>
312+ /// Obtain the underlying array, if possible.
313+ /// The returned array is unsafe because it should not be written to.
314+ /// </summary>
311315 internal static byte [ ] ? AsUnsafeArray ( this IPythonBuffer buffer ) {
312316 if ( ! buffer . IsCContiguous ( ) )
313317 return null ;
314318
315- if ( buffer . Object is Bytes b )
316- return b . UnsafeByteArray ;
317-
318- if ( buffer . Object is Memory < byte > mem ) {
319- if ( MemoryMarshal . TryGetArray ( mem , out ArraySegment < byte > seg ) && seg . Array != null && seg . Offset == 0 && seg . Count == seg . Array . Length )
319+ ReadOnlySpan < byte > bufdata = buffer . AsReadOnlySpan ( ) ;
320+ if ( buffer . Object is Bytes b ) {
321+ if ( b . UnsafeByteArray . AsSpan ( ) == bufdata )
322+ return b . UnsafeByteArray ;
323+ } else if ( buffer . Object is ByteArray ba ) {
324+ byte [ ] arrdata = ba . UnsafeByteList . Data ;
325+ if ( arrdata . AsSpan ( ) == bufdata )
326+ return arrdata ;
327+ } else if ( buffer . Object is Memory < byte > mem ) {
328+ if ( MemoryMarshal . TryGetArray ( mem , out ArraySegment < byte > seg ) && seg . Array is not null && seg . Array . AsSpan ( ) == bufdata )
320329 return seg . Array ;
321330 } else if ( buffer . Object is ReadOnlyMemory < byte > rom ) {
322- if ( MemoryMarshal . TryGetArray ( rom , out ArraySegment < byte > seg ) && seg . Array != null && seg . Offset == 0 && seg . Count == seg . Array . Length )
331+ if ( MemoryMarshal . TryGetArray ( rom , out ArraySegment < byte > seg ) && seg . Array is not null && seg . Array . AsSpan ( ) == bufdata )
332+ return seg . Array ;
333+ }
334+
335+ return null ;
336+ }
337+
338+ /// <summary>
339+ /// Obtain the underlying writable array, if possible.
340+ /// The returned array is unsafe because it can be longer than the buffer.
341+ /// </summary>
342+ internal static byte [ ] ? AsUnsafeWritableArray ( this IPythonBuffer buffer ) {
343+ if ( ! buffer . IsCContiguous ( ) || buffer . IsReadOnly )
344+ return null ;
345+
346+ Span < byte > bufdata = buffer . AsSpan ( ) ;
347+ if ( buffer . Object is ByteArray ba ) {
348+ byte [ ] arrdata = ba . UnsafeByteList . Data ;
349+ if ( UseSameMemory ( arrdata , bufdata ) )
350+ return arrdata ;
351+ } else if ( buffer . Object is Memory < byte > mem ) {
352+ if ( MemoryMarshal . TryGetArray ( mem , out ArraySegment < byte > seg ) && seg . Array is not null && UseSameMemory ( seg . Array , bufdata ) )
323353 return seg . Array ;
324354 }
325355
326356 return null ;
327357 }
358+
359+ private static bool UseSameMemory ( byte [ ] arr , ReadOnlySpan < byte > span )
360+ => arr . Length >= span . Length && arr . AsSpan ( 0 , span . Length ) == span ;
328361 }
329362
330363 public ref struct BufferBytesEnumerator {
0 commit comments