Passing a ubyte[] to a function taking a 'ref ubyte[16]'

Jonathan M Davis jmdavisProg at gmx.com
Sat Jun 23 16:51:14 PDT 2012


On Saturday, June 23, 2012 20:23:26 Johannes Pfau wrote:
> I'm working on the new design for std.hash and I hit an interesting
> problem:
> 
> The OOP interface has to take buffers as slices with unknown length, as
> the length differs between hashes and I have to put a common function
> declaration in a interface. So I have this:
> ------------
> interface Digest
> {
>     ubyte[] finish(ubyte[] buf);
> }
> ------------

I confess that I'm baffled as to why you'd even be using interfaces for this, 
given that Phobos always uses structs and templates for this sort of thing.

> Now the template API can and should use the correct type, so there
> finish is defined like this:
> ------------
> struct MD5
> {
>     void finish(ref ubyte[16] data);
> }
> ------------
> 
> And the interface implementation for MD5 has to call the MD5 structs
> finish function:
> ------------
> class MD5Digest : Digest
> {
>     private MD5 _digest;
> 
>     ubyte[] finish(ubyte[] buf)
>     {
>         enforce(buf.length >= 16);
>         _digest.finish(buf); //How to do this?
>     }
> }
> ------------
> 
> So how to pass a ubyte[] to a function expecting a ref ubyte[16]
> without allocating/using any extra memory (Not even stack)?
> 
> This seems to work, but it's very ugly:
> ------------
> _digest.finish(*cast(ubyte[16]*)buf.ptr);
> ------------
> 
> I thought this might create a temporary, but it passes all unittests,
> so it seems to work?

I believe that that will work, but it's definitely ugly. However, if you do 
that, you _need_ to put an assertion about the length of buf in there, 
otherwise, you could be using memory from past the end of buf.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list