From 902280ce8544fbefd7a62fe4c11c35b3705464b7 Mon Sep 17 00:00:00 2001
From: Marius Gavrilescu <marius@ieval.ro>
Date: Sat, 23 Jun 2018 20:44:32 +0300
Subject: [PATCH] Export cat (stream) interface too

---
 HighwayHash.xs         | 67 ++++++++++++++++++++++++++++++++++++++----
 t/Digest-HighwayHash.t | 18 +++++++++++-
 typemap                | 16 ++++------
 3 files changed, 83 insertions(+), 18 deletions(-)

diff --git a/HighwayHash.xs b/HighwayHash.xs
index f806845..e04c57c 100644
--- a/HighwayHash.xs
+++ b/HighwayHash.xs
@@ -9,6 +9,8 @@
 
 #include "highwayhash.c"
 
+typedef HighwayHashCat* Digest__HighwayHash;
+
 void process_key(pTHX_ AV *key_av, uint64_t *key) {
 	int i;
 	SV *elt;
@@ -24,14 +26,14 @@ void process_key(pTHX_ AV *key_av, uint64_t *key) {
 	}
 }
 
-uint64_t highway_hash64(AV *key_av, unsigned char *bytes, uint64_t size) {
+uint64_t highway_hash64(AV *key_av, unsigned char *bytes, size_t size) {
 	dTHX;
 	uint64_t key[4];
 	process_key(aTHX_ key_av, key);
 	return HighwayHash64(bytes, size, key);
 }
 
-AV* highway_hash128(AV *key_av, unsigned char *bytes, uint64_t size) {
+AV* highway_hash128(AV *key_av, unsigned char *bytes, size_t size) {
 	dTHX;
 	AV* result;
 	uint64_t key[4];
@@ -44,7 +46,7 @@ AV* highway_hash128(AV *key_av, unsigned char *bytes, uint64_t size) {
 	return result;
 }
 
-AV* highway_hash256(AV *key_av, unsigned char *bytes, uint64_t size) {
+AV* highway_hash256(AV *key_av, unsigned char *bytes, size_t size) {
 	dTHX;
 	AV* result;
 	uint64_t key[4];
@@ -59,13 +61,66 @@ AV* highway_hash256(AV *key_av, unsigned char *bytes, uint64_t size) {
 	return result;
 }
 
+Digest__HighwayHash new(AV *key_av) {
+	dTHX;
+	uint64_t key[4];
+	Digest__HighwayHash state;
+	Newx(state, 1, HighwayHashCat);
+	process_key(aTHX_ key_av, key);
+	HighwayHashCatStart(key, state);
+	return state;
+}
+
+void append(Digest__HighwayHash state, unsigned char *bytes, size_t size) {
+	HighwayHashCatAppend(bytes, size, state);
+}
+
+uint64_t finish64(Digest__HighwayHash state) {
+	return HighwayHashCatFinish64(state);
+}
+
+AV* finish128(Digest__HighwayHash state) {
+	dTHX;
+	AV* result;
+	uint64_t hash[2];
+	HighwayHashCatFinish128(state, hash);
+	result = newAV();
+	av_push(result, sv_2mortal(newSVu64(hash[0])));
+	av_push(result, sv_2mortal(newSVu64(hash[1])));
+	return result;
+}
+
+AV* finish256(Digest__HighwayHash state) {
+	dTHX;
+	AV* result;
+	uint64_t hash[4];
+	HighwayHashCatFinish256(state, hash);
+	result = newAV();
+	av_push(result, sv_2mortal(newSVu64(hash[0])));
+	av_push(result, sv_2mortal(newSVu64(hash[1])));
+	av_push(result, sv_2mortal(newSVu64(hash[2])));
+	av_push(result, sv_2mortal(newSVu64(hash[3])));
+	return result;
+}
+
 MODULE = Digest::HighwayHash		PACKAGE = Digest::HighwayHash
 PROTOTYPES: DISABLE
 BOOT:
      PERL_MATH_INT64_LOAD_OR_CROAK;
 
-uint64_t highway_hash64(AV *key_av, unsigned char *bytes, uint64_t length(bytes))
+uint64_t highway_hash64(AV *key_av, unsigned char *bytes, size_t length(bytes))
+
+AV* highway_hash128(AV *key_av, unsigned char *bytes, size_t length(bytes))
+
+AV* highway_hash256(AV *key_av, unsigned char *bytes, size_t length(bytes))
+
+Digest::HighwayHash new(SV *class, AV *key_av)
+C_ARGS: key_av
+
+void append(Digest::HighwayHash state, unsigned char *bytes, size_t length(bytes))
+
+uint64_t finish64(Digest::HighwayHash state)
 
-AV* highway_hash128(AV *key_av, unsigned char *bytes, uint64_t length(bytes))
+AV* finish128(Digest::HighwayHash state)
 
-AV* highway_hash256(AV *key_av, unsigned char *bytes, uint64_t length(bytes))
+AV* finish256(Digest::HighwayHash state)
diff --git a/t/Digest-HighwayHash.t b/t/Digest-HighwayHash.t
index 594b4da..9fcd195 100644
--- a/t/Digest-HighwayHash.t
+++ b/t/Digest-HighwayHash.t
@@ -2,7 +2,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 7;
+use Test::More tests => 10;
 use Test::Exception;
 
 BEGIN { use_ok('Digest::HighwayHash') };
@@ -11,6 +11,22 @@ is highway_hash64([1, 2, 3, 4], 'hello'), '11956820856122239241', 'highway_hash6
 is_deeply highway_hash128([1, 2, 3, 4], 'hello'), ['3048112761216189476', '13900443277579286659'], 'highway_hash128';
 is_deeply highway_hash256([1, 2, 3, 4], 'hello'), ['8099666330974151427', '17027479935588128037', '4015249936799013189', '10027181291351549853'], 'highway_hash256';
 
+my $state64  = Digest::HighwayHash->new([1, 2, 3, 4]);
+my $state128 = Digest::HighwayHash->new([1, 2, 3, 4]);
+my $state256 = Digest::HighwayHash->new([1, 2, 3, 4]);
+
+$state64->append('hello');
+$state64->append('');
+$state128->append('h');
+$state128->append('ell');
+$state128->append('o');
+$state256->append('hell');
+$state256->append('o');
+
+is $state64->finish64, '11956820856122239241', 'finish64';
+is_deeply $state128->finish128, ['3048112761216189476', '13900443277579286659'], 'finish128';
+is_deeply $state256->finish256, ['8099666330974151427', '17027479935588128037', '4015249936799013189', '10027181291351549853'], 'finish256';
+
 throws_ok { highway_hash64 1, 'hello' }                qr/not an ARRAY reference/, 'bad key 1';
 throws_ok { highway_hash128 [1, 2], 'hello' }          qr/Key for highway_hash must be a 4-element array/, 'bad key 2';
 throws_ok { highway_hash256 [1, 2, 3, 4, 5], 'hello' } qr/Key for highway_hash must be a 4-element array/, 'bad key 3';
diff --git a/typemap b/typemap
index 082062c..90e6044 100644
--- a/typemap
+++ b/typemap
@@ -1,14 +1,7 @@
-#
-# typemap - This file is in the public domain
-#
-# Author: Salvador Fandino <sfandino@yahoo.com>
-# Version: 1.0
-#
-
-
 TYPEMAP
-int64_t         T_INT64
-uint64_t        T_UINT64
+int64_t                T_INT64
+uint64_t               T_UINT64
+Digest::HighwayHash    T_PTROBJ
 
 INPUT
 T_INT64
@@ -22,4 +15,5 @@ T_INT64
         $arg = newSVi64($var);
 
 T_UINT64
-        $arg = newSVu64($var);
\ No newline at end of file
+        $arg = newSVu64($var);
+
-- 
2.39.5