File-Raw-Hash

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for File-Raw-Hash

0.03    2026-05-17
        - Bumped File::Raw prereq to 0.13 to pick up the streaming
          O_BINARY fix on Windows.

0.02    2026-05-07
        - Bumped File::Raw prereq to 0.12

0.01    2026-05-07
        Initial release.
        - Single 'hash' plugin registered with File::Raw.
        - READ, WRITE, STREAM, RECORD phases (passthrough on the data
          path; the digest is delivered via a caller-supplied scalar /

t/05-stream.t  view on Meta::CPAN


# One-shot reference digest via the READ phase.
my $expected;
file_slurp($path, plugin => 'hash', algo => 'sha256', into => \$expected);
ok(defined $expected && length($expected) == 64,
   'reference one-shot digest computed');

# Streaming digest via each_line. The hash plugin consumes chunks and
# computes the digest; it doesn't emit records, so the user callback
# is never invoked. That's by design - "use each_line to trigger the
# streaming path; the digest lands in 'into' at EOF".
my $stream_digest;
my $line_count = 0;
File::Raw::each_line($path, sub { $line_count++ },
    plugin => 'hash',
    algo   => 'sha256',
    into   => \$stream_digest,
);

is($line_count, 0,
   'hash plugin does not emit records (callback intentionally not called)');
is($stream_digest, $expected,
   'STREAM digest matches one-shot READ digest across chunks');

# Multi-algo streaming.
{
    my %digests;
    File::Raw::each_line($path, sub {},
        plugin => 'hash',
        algos  => [qw(sha256 md5 crc32)],
        into   => \%digests);

    is_deeply([sort keys %digests], [qw(crc32 md5 sha256)],
              'multi-algo STREAM populates all entries');
    is($digests{sha256}, $expected,

t/07-large.t  view on Meta::CPAN

#!perl
use 5.008003;
use strict;
use warnings;
use Test::More;
use File::Temp qw(tempfile);
use File::Raw qw(import);
use File::Raw::Hash;

# 5 MB blob round-trip - confirms the streaming code path doesn't trip
# on multi-chunk inputs and that the digest matches the one-shot
# computation byte-for-byte. We deliberately stay below the plan's 50
# MB target so this passes on small CPAN-tester boxes; the 50 MB
# stress lives in xt/ for author-only runs.

my $size = 5 * 1024 * 1024;     # 5 MiB
my $blob = '';
{
    # Deterministic pseudorandom-ish content via a tiny LCG so the test
    # doesn't depend on the system PRNG. Same byte sequence every run.

t/12-hmac.t  view on Meta::CPAN

{
    my $path = spew_bytes('');
    my $d;
    file_slurp($path, plugin => 'hash', algo => 'sha256',
               hmac_key => 'k', into => \$d);
    like($d, qr/^[0-9a-f]{64}$/, 'HMAC of empty data is well-defined');
    isnt($d, 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
         'HMAC differs from plain hash of empty');
}

# HMAC streaming consistency.
{
    my $payload = ('xyzzy' x 20000) . "\n";
    my $path = spew_bytes($payload);
    my $oneshot;
    file_slurp($path, plugin => 'hash', algo => 'sha256',
               hmac_key => 'streamkey', into => \$oneshot);

    my $streamed;
    File::Raw::each_line($path, sub {},
        plugin => 'hash', algo => 'sha256',



( run in 1.049 second using v1.01-cache-2.11-cpan-140bd7fdf52 )