Thread overview
std.mmfile + std.bitmanip.peek, void[] is not a forward range?
Nov 21
Ben Jones
Nov 22
Ben Jones
November 21

I'm trying to read integers out of a mmap'd file using std.bitmanip.peek and it's failing because

isForwardRange!(void[]) is false

That seems unexpected, am I missing something or is that a bug?

Am I doing something wrong here?

 scope mmFile = new MmFile(filename, MmFile.Mode.read, 0, null);

 void[] data = mmFile[]; //doesn't matter, same as slicing mmFile below
 int val = data[offset .. $].peek!int; //data[ offset .. offset + 4] has same issue

Partial error:

Error: none of the overloads of template `std.bitmanip.peek` are callable using argument types `!(int)(void[])`
/opt/homebrew/Cellar/ldc/1.39.0_1/include/dlang/ldc/std/bitmanip.d(3416,3):        Candidates are: `peek(T, Endian endianness = Endian.bigEndian, R)(R range)`
  with `T = int,
       endianness = Endian.bigEndian,
       R = void[]`
  must satisfy the following constraint:
`       isForwardRange!R`
November 21
On Thursday, November 21, 2024 2:51:33 PM MST Ben Jones via Digitalmars-d- learn wrote:
> I'm trying to read integers out of a mmap'd file using std.bitmanip.peek and it's failing because
>
> `isForwardRange!(void[])` is false
>
> That seems unexpected, am I missing something or is that a bug?
>
> Am I doing something wrong here?
>
> ```
>   scope mmFile = new MmFile(filename, MmFile.Mode.read, 0, null);
>
>   void[] data = mmFile[]; //doesn't matter, same as slicing mmFile
> below
>   int val = data[offset .. $].peek!int; //data[ offset .. offset +
> 4] has same issue
>
> ```
>
> Partial error:
>
> ```
> Error: none of the overloads of template `std.bitmanip.peek` are
> callable using argument types `!(int)(void[])`
> /opt/homebrew/Cellar/ldc/1.39.0_1/include/dlang/ldc/std/bitmanip.d(3416,3):
>       Candidates are: `peek(T, Endian endianness = Endian.bigEndian, R)(R
> range)` with `T = int,
>         endianness = Endian.bigEndian,
>         R = void[]`
>    must satisfy the following constraint:
> `       isForwardRange!R`
> ```

void[] is not a range, because you cannot index any of its elements. For instance, this code

    void[] arr = new ubyte[](42);
    auto e = arr[0];

results in this error

    q.d(4): Error: variable `q.main.e` - type `void` is inferred from
            initializer `arr[0]`, and variables cannot be of type `void`
    q.d(4): Error: expression `arr[0]` is `void` and has no value

void[] can refer to an array of anything, and it's not at all type-safe or memory-safe to access its elements. It would be like implicitly treating a void* like a pointer to any specific type.

If you want to access anything in a void[], it must be cast to something else. If you want to access the data as bytes, then typically, casting to ubyte[] would be the appropriate thing to do. Then you can use std.bitmanip's stuff on it to convert groups of bytes to int or short or some other integral type.

- Jonathan M Davis



November 22
On Thursday, 21 November 2024 at 22:09:45 UTC, Jonathan M Davis wrote:
>
> void[] can refer to an array of anything, and it's not at all type-safe or memory-safe to access its elements. It would be like implicitly treating a void* like a pointer to any specific type.
>
> If you want to access anything in a void[], it must be cast to something else. If you want to access the data as bytes, then typically, casting to ubyte[] would be the appropriate thing to do. Then you can use std.bitmanip's stuff on it to convert groups of bytes to int or short or some other integral type.
>
> - Jonathan M Davis

Makes sense although it seems reasonable for bitmanip.peek and friends to work on void[] since the underlying data is assumed to be untyped.