Skip to content

Commit 5ef5c52

Browse files
committed
Convert MemoryBufferProtocolWrapper to generic
1 parent 1586538 commit 5ef5c52

File tree

2 files changed

+48
-48
lines changed

2 files changed

+48
-48
lines changed

src/core/IronPython/Runtime/Binding/ConversionBinder.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,9 @@ private DynamicMetaObject ConvertFromMemoryToBufferProtocol(DynamicMetaObject se
734734
return new DynamicMetaObject(
735735
AstUtils.Convert(
736736
Ast.New(
737-
typeof(MemoryBufferProtocolWrapper).GetConstructor(new Type[] { fromType }),
738-
AstUtils.Convert(self.Expression, fromType)
737+
typeof(MemoryBufferProtocolWrapper<byte>).GetConstructor([fromType, typeof(string)]),
738+
AstUtils.Convert(self.Expression, fromType),
739+
AstUtils.Constant(null, typeof(string))
739740
),
740741
typeof(IBufferProtocol)
741742
),

src/core/IronPython/Runtime/ConversionWrappers.cs

Lines changed: 45 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Collections.Generic;
1111
using System.Diagnostics.CodeAnalysis;
1212
using System.Numerics;
13+
using System.Runtime.InteropServices;
1314

1415
namespace IronPython.Runtime {
1516

@@ -376,79 +377,77 @@ IEnumerator IEnumerable.GetEnumerator() {
376377
#endregion
377378
}
378379

379-
public sealed class MemoryBufferWrapper : IPythonBuffer {
380-
private readonly ReadOnlyMemory<byte> _rom;
381-
private readonly Memory<byte>? _memory;
382-
private readonly BufferFlags _flags;
380+
public sealed class MemoryBufferProtocolWrapper<T> : IBufferProtocol where T : unmanaged {
381+
private readonly ReadOnlyMemory<T> _rom;
382+
private readonly Memory<T>? _memory;
383+
private readonly string? _format;
383384

384-
public MemoryBufferWrapper(ReadOnlyMemory<byte> memory, BufferFlags flags) {
385+
public MemoryBufferProtocolWrapper(ReadOnlyMemory<T> memory, string? format = null) {
385386
_rom = memory;
386387
_memory = null;
387-
_flags = flags;
388+
_format = format;
388389
}
389390

390-
public MemoryBufferWrapper(Memory<byte> memory, BufferFlags flags) {
391+
public MemoryBufferProtocolWrapper(Memory<T> memory, string? format = null) {
391392
_rom = memory;
392393
_memory = memory;
393-
_flags = flags;
394+
_format = format;
394395
}
395396

396-
public void Dispose() { }
397-
398-
public object Object => _memory ?? _rom;
397+
public IPythonBuffer? GetBuffer(BufferFlags flags, bool throwOnError) {
398+
if (_memory.HasValue) {
399+
return new MemoryBufferWrapper(this, flags);
400+
}
399401

400-
public bool IsReadOnly => !_memory.HasValue;
402+
if (flags.HasFlag(BufferFlags.Writable)) {
403+
if (throwOnError) {
404+
throw Operations.PythonOps.BufferError("ReadOnlyMemory is not writable.");
405+
}
406+
return null;
407+
}
401408

402-
public ReadOnlySpan<byte> AsReadOnlySpan() => _rom.Span;
409+
return new MemoryBufferWrapper(this, flags);
410+
}
403411

404-
public Span<byte> AsSpan() => _memory.HasValue ? _memory.Value.Span : throw new InvalidOperationException("ReadOnlyMemory is not writable");
412+
private sealed unsafe class MemoryBufferWrapper : IPythonBuffer {
413+
private readonly MemoryBufferProtocolWrapper<T> _wrapper;
414+
private readonly BufferFlags _flags;
405415

406-
public MemoryHandle Pin() => _rom.Pin();
416+
public MemoryBufferWrapper(MemoryBufferProtocolWrapper<T> wrapper, BufferFlags flags) {
417+
_wrapper = wrapper;
418+
_flags = flags;
419+
}
407420

408-
public int Offset => 0;
421+
public void Dispose() { }
409422

410-
public string? Format => _flags.HasFlag(BufferFlags.Format) ? "B" : null;
423+
public object Object => _wrapper._memory ?? _wrapper._rom;
411424

412-
public int ItemCount => _rom.Length;
425+
public bool IsReadOnly => !_wrapper._memory.HasValue;
413426

414-
public int ItemSize => 1;
427+
public ReadOnlySpan<byte> AsReadOnlySpan() => MemoryMarshal.Cast<T, byte>(_wrapper._rom.Span);
415428

416-
public int NumOfDims => 1;
429+
public Span<byte> AsSpan()
430+
=> _wrapper._memory.HasValue
431+
? MemoryMarshal.Cast<T, byte>(_wrapper._memory.Value.Span)
432+
: throw new InvalidOperationException("ReadOnlyMemory is not writable");
417433

418-
public IReadOnlyList<int>? Shape => null;
434+
public MemoryHandle Pin() => _wrapper._rom.Pin();
419435

420-
public IReadOnlyList<int>? Strides => null;
436+
public int Offset => 0;
421437

422-
public IReadOnlyList<int>? SubOffsets => null;
423-
}
438+
public string? Format => _flags.HasFlag(BufferFlags.Format) ? _wrapper._format : null;
424439

425-
public class MemoryBufferProtocolWrapper : IBufferProtocol {
426-
private readonly ReadOnlyMemory<byte> _rom;
427-
private readonly Memory<byte>? _memory;
440+
public int ItemCount => _wrapper._rom.Length;
428441

429-
public MemoryBufferProtocolWrapper(ReadOnlyMemory<byte> memory) {
430-
_rom = memory;
431-
_memory = null;
432-
}
442+
public int ItemSize => sizeof(T);
433443

434-
public MemoryBufferProtocolWrapper(Memory<byte> memory) {
435-
_rom = memory;
436-
_memory = memory;
437-
}
444+
public int NumOfDims => 1;
438445

439-
public IPythonBuffer? GetBuffer(BufferFlags flags, bool throwOnError) {
440-
if (_memory.HasValue) {
441-
return new MemoryBufferWrapper(_memory.Value, flags);
442-
}
446+
public IReadOnlyList<int>? Shape => null;
443447

444-
if (flags.HasFlag(BufferFlags.Writable)) {
445-
if (throwOnError) {
446-
throw Operations.PythonOps.BufferError("ReadOnlyMemory is not writable.");
447-
}
448-
return null;
449-
}
448+
public IReadOnlyList<int>? Strides => null;
450449

451-
return new MemoryBufferWrapper(_rom, flags);
450+
public IReadOnlyList<int>? SubOffsets => null;
452451
}
453452
}
454453
}

0 commit comments

Comments
 (0)