5

How do I assign a TArray<Byte> to array of Byte and vice versa?

TEncoding.UTF8.GetBytes returns a TArray<Byte>. TIdHashMessageDigest5.HashBytes has a TIdBytes = array of Byte as parameter.

Can I assign these types to each other? Maybe with a copy? Or do I need to loop?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
r_j
  • 1,348
  • 15
  • 35
  • 2
    See also [Delphi XE4 Indy compatibility issue between TBytes and TidBytes](http://stackoverflow.com/a/16343080/576719). – LU RD Jan 04 '17 at 14:52

1 Answers1

8

These types are not assignment compatible. In an ideal world you would use TArray<T> exclusively, and it would be better if all libraries did so. I do not understand why Indy insists on using its own distinct type here.

If you cannot then you can make a copy. That's easy enough with a loop. If efficiency matters that you could copy using Move.

SetLength(Dest, Length(Source));
Move(Pointer(Source)^, Pointer(Dest)^, Length(Source));

I use Pointer(arr)^ here rather than arr[0] to avoid tripping range check exceptions in case of an empty array.

It is also possible to avoid a copy by using a typecast, since all dynamic arrays are implemented the same way. So you could write

Hash := HashBytes(TIdBytes(TEncoding.UTF8.GetBytes(...)));

Of course, this gives up type safety, but then so does the call to Move above.

Yet another approach, suggested by Remy's answer to another question, is to use TIdTextEncoding rather than TEncoding. That way you can work with TIdBytes exclusively.

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I imagine Indy does it like this for backwards compatibility with Delphi versions that do not have TArray? – penarthur66 Jan 04 '17 at 14:21
  • 2
    @penarthur66 `TIdBytes` could readily be conditionally defined to get around that. – David Heffernan Jan 04 '17 at 14:44
  • 3
    @penarthur66 actually, `TIdBytes` used to be an alias for `TBytes` when available (which is an alias for `TArray` when available), but doing so caused a lot of problems, especially in several event handlers across the Delphi/C++ boundary (Embarcadero RTTI bugs). So eventually I had no choice but to make `TIdBytes` go back to using `array of Byte` to maintain proper functionality. It was not to handle backwards compatibility, it was to handle Embarcadero bugs. – Remy Lebeau Jan 04 '17 at 15:52