@@ -262,8 +262,70 @@ pyarray_typestrdescr_to_type(ts::String, descr::Py) = begin
262
262
return Utils. StaticString{UInt32,sz}
263
263
elseif etc == ' O'
264
264
return UnsafePyObject
265
+ elseif etc == ' V'
266
+ pyisnull (descr) && error (" not supported: void dtype with null descr" )
267
+ sz = parse (Int, ts[3 : end ])
268
+ T = pyarray_descr_to_type (descr)
269
+ sizeof (T) == sz || error (" size mismatch: itemsize=$sz but sizeof(descr)=$(sizeof (T)) " )
270
+ return T
271
+ else
272
+ error (" not supported: dtype of kind: $(repr (etc)) " )
273
+ end
274
+ end
275
+
276
+ function pyarray_descr_to_type (descr:: Py )
277
+ fnames = Symbol[]
278
+ foffsets = Int[]
279
+ ftypes = DataType[]
280
+ curoffset = 0
281
+ for item in descr
282
+ # get the name
283
+ name = item[0 ]
284
+ if pyistuple (name)
285
+ name = name[0 ]
286
+ end
287
+ fname = Symbol (pyconvert (String, name))
288
+ # get the shape
289
+ if length (item) > 2
290
+ shape = pyconvert (Vector{Int}, item[2 ])
291
+ else
292
+ shape = Int[]
293
+ end
294
+ # get the type
295
+ descr2 = item[1 ]
296
+ if pyisstr (descr2)
297
+ typestr = pyconvert (String, descr2)
298
+ # void entries are just padding to ignore
299
+ if typestr[2 ] == ' V'
300
+ curoffset += parse (Int, typestr[3 : end ]) * prod (shape)
301
+ continue
302
+ end
303
+ ftype = pyarray_typestrdescr_to_type (typestr, PyNULL)
304
+ else
305
+ ftype = pyarray_descr_to_type (descr2)
306
+ end
307
+ # apply the shape
308
+ for n in reverse (shape)
309
+ ftype = NTuple{n,ftype}
310
+ end
311
+ # save the field
312
+ push! (fnames, fname)
313
+ push! (foffsets, curoffset)
314
+ push! (ftypes, ftype)
315
+ curoffset += sizeof (ftype)
316
+ end
317
+ # construct the tuple type and check its offsets and size
318
+ # TODO : support non-aligned dtypes by packing them into a custom type and reinterpreting
319
+ T = Tuple{ftypes... }
320
+ for (i, o) in pairs (foffsets)
321
+ fieldoffset (T, i) == o || error (" not supported: dtype that is not aligned: $descr " )
322
+ end
323
+ sizeof (T) == curoffset || error (" not supported: dtype with end padding: $descr " )
324
+ # return the tuple type if the field names are f0, f1, ..., else return a named tuple
325
+ if fnames == [Symbol (:f , i- 1 ) for i in 1 : length (fnames)]
326
+ return T
265
327
else
266
- error ( " type not supported: $ts " )
328
+ return NamedTuple{ Tuple (fnames), T}
267
329
end
268
330
end
269
331
@@ -380,9 +442,13 @@ function pyarray_get_R(src::PyArraySource_ArrayStruct)
380
442
mod (size, 4 ) == 0 || error (" unicode size must be a multiple of 4: $size " )
381
443
return Utils. StaticString{UInt32,div (size, 4 )}
382
444
elseif kind == 86 # V = void (should have descr)
383
- error (" dtype not supported" )
445
+ hasdescr || error (" not supported: void dtype with no descr" )
446
+ descr = pynew (incref (src. info. descr))
447
+ T = pyarray_descr_to_type (descr)
448
+ sizeof (T) == size || error (" size mismatch: itemsize=$size but sizeof(descr)=$(sizeof (T)) " )
449
+ return T
384
450
else
385
- error (" unexpected kind ( $(Char (kind) ) )" )
451
+ error (" not supported: dtype of kind: $(Char (kind)) " )
386
452
end
387
453
@assert false
388
454
end
0 commit comments