Reputation: 1769
I have a situation where I want to create a signature of a data structure:
my $signature = ds_to_sig(
{ foo => 'bar',
baz => 'bundy',
boing => undef,
number => 1_234_567,
}
);
The aim should be that if the data structure changes then so should the signature.
Is there an established way to do this?
Upvotes: 12
Views: 839
Reputation:
Digest::MD5->new->add(
Data::Dumper->new([$structure])
->Purity(0)
->Terse(1)
->Indent(0)
->Useqq(1)
->Sortkeys(1)
->Dump()
)->b64digest();
Upvotes: 5
Reputation: 67048
The best way to do this is to use a deep-structure serialization system like Storable. Two structures with the same data will produce the same blob of Storable output, so they can be compared.
#!/usr/bin/perl
use strict;
use warnings;
use Storable ('freeze');
$Storable::canonical = 1;
my $one = { foo => 42, bar => [ 1, 2, 3 ] };
my $two = { foo => 42, bar => [ 1, 2, 3 ] };
my $one_s = freeze $one;
my $two_s = freeze $two;
print "match\n" if $one_s eq $two_s;
...And to prove the inverse:
$one = [ 4, 5, 6 ];
$one_s = freeze $one;
print "no match" if $one_s ne $two_s;
Upvotes: 10
Reputation: 30235
I think what you're looking for is a hash function. I would recommend an approach like this:
use Storable;
$Storable::canonical = 1;
sub ds_to_sig {
my $structure = shift;
return hash(freeze $structure);
}
The function hash can be any hash function, for example the function md5 from Digest::MD5
Upvotes: 16
Reputation: 12852
Use Storable::nstore to turn it into a binary representation, and then calculate a checksum (for example with the Digest module).
Both modules are core modules.
Upvotes: 7
Reputation: 436
Can't you use an object instead of a struct? That way you could see if an object is an instance of a type without having to compare hashes, etc.
Upvotes: -5