5

When I use std.algorithm.copy on std.digest objects, I get different results compared when I am using put byte by byte. Why?

import std.stdio;
import std.digest.digest;
import std.digest.md;
import std.algorithm;

void main() {
    string s = "Hello!\n";
    auto d1 = makeDigest!MD5;
    auto d2 = makeDigest!MD5;
    foreach (ubyte b; s) {
        d1.put(b);
    }
    s.copy(d2);
    writeln(digest!MD5(s).toHexString);
    writeln(d1.finish().toHexString);
    writeln(d2.finish().toHexString);
}

Output:

E134CED312B3511D88943D57CCD70C83
E134CED312B3511D88943D57CCD70C83
D41D8CD98F00B204E9800998ECF8427E
Tamas
  • 3,254
  • 4
  • 29
  • 51

1 Answers1

4

d2 is passed by value to copy. The data gets copied inside the function, but then when it returns, the d2 variable on the outside is unmodified!

I kinda think this might be a bug: the current behavior doesn't make a great deal of sense to me. When you are copying it, it makes sense to do it by reference. The unittests only test arrays which are half-reference (they are pointers) and it works for them.

Adam D. Ruppe
  • 25,382
  • 4
  • 41
  • 60
  • 1
    Here's the bug report: https://issues.dlang.org/show_bug.cgi?id=9102 I don't remember if there was any reason given why copy doesn't pass the range by ref. We just never specified whether value-type output ranges are legal (and it's not explicitly defined for InputRanges either). Something that should have been implemented for digests is a disabled this(this) to avoid silent copying. But I guess it's to late now as this would break valid code as well. – jpf Mar 16 '16 at 06:44
  • 2
    As a workaround you could use MD5Digest (which is a class) instead of MD5 (which is a struct). – Thayne Mar 21 '16 at 05:52