Skip to content

Commit ddf53a1

Browse files
committed
add hashed streams
1 parent 33358dc commit ddf53a1

File tree

3 files changed

+102
-2
lines changed

3 files changed

+102
-2
lines changed

include/gf2/core/Streams.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <zlib.h>
1313

1414
#include "CoreApi.h"
15+
#include "SecureHash.h"
1516
#include "Stream.h"
1617

1718
namespace gf {
@@ -93,6 +94,22 @@ namespace gf {
9394
std::size_t m_offset = 0;
9495
};
9596

97+
class GF_CORE_API HashedInputStream : public InputStream {
98+
public:
99+
HashedInputStream(InputStream* stream);
100+
101+
SecureHash::Hash hash();
102+
103+
std::size_t read(Span<uint8_t> buffer) override;
104+
void seek(std::ptrdiff_t position) override;
105+
void skip(std::ptrdiff_t position) override;
106+
bool finished() override;
107+
108+
private:
109+
InputStream* m_stream = nullptr;
110+
SecureHash m_hash;
111+
};
112+
96113
class GF_CORE_API FileOutputStream : public OutputStream {
97114
public:
98115
enum class Mode : uint8_t {
@@ -163,6 +180,20 @@ namespace gf {
163180
std::vector<uint8_t>* m_bytes;
164181
};
165182

183+
class GF_CORE_API HashedOutputStream : public OutputStream {
184+
public:
185+
HashedOutputStream(OutputStream* stream);
186+
187+
SecureHash::Hash hash();
188+
189+
std::size_t write(Span<const uint8_t> buffer) override;
190+
std::size_t written_bytes() const override;
191+
192+
private:
193+
OutputStream* m_stream;
194+
SecureHash m_hash;
195+
};
196+
166197
} // namespace gf
167198

168199
#endif // GF_STREAMS_H

library/core/Streams.cc

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,42 @@ namespace gf {
296296
return m_offset == m_bytes->size();
297297
}
298298

299+
/*
300+
* HashedInputStream
301+
*/
302+
303+
HashedInputStream::HashedInputStream(InputStream* stream)
304+
: m_stream(stream)
305+
{
306+
}
307+
308+
SecureHash::Hash HashedInputStream::hash()
309+
{
310+
return m_hash.result();
311+
}
312+
313+
std::size_t HashedInputStream::read(Span<uint8_t> buffer)
314+
{
315+
auto result = m_stream->read(buffer);
316+
m_hash.input(buffer);
317+
return result;
318+
}
319+
320+
void HashedInputStream::seek([[maybe_unused]] std::ptrdiff_t position)
321+
{
322+
Log::fatal("Not supported");
323+
}
324+
325+
void HashedInputStream::skip([[maybe_unused]] std::ptrdiff_t position)
326+
{
327+
Log::fatal("Not supported");
328+
}
329+
330+
bool HashedInputStream::finished()
331+
{
332+
return m_stream->finished();
333+
}
334+
299335
/*
300336
* FileOutputStream
301337
*/
@@ -513,4 +549,29 @@ namespace gf {
513549
return m_bytes->size();
514550
}
515551

552+
/*
553+
* HashedOutputStream
554+
*/
555+
556+
HashedOutputStream::HashedOutputStream(OutputStream* stream)
557+
: m_stream(stream)
558+
{
559+
}
560+
561+
SecureHash::Hash HashedOutputStream::hash()
562+
{
563+
return m_hash.result();
564+
}
565+
566+
std::size_t HashedOutputStream::write(Span<const uint8_t> buffer)
567+
{
568+
m_hash.input(buffer);
569+
return m_stream->write(buffer);
570+
}
571+
572+
std::size_t HashedOutputStream::written_bytes() const
573+
{
574+
return m_stream->written_bytes();
575+
}
576+
516577
} // namespace gf

tests/tests_core_Serialization.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,26 @@ namespace {
2222
void save_and_load(const T& in, T& out)
2323
{
2424
std::vector<uint8_t> bytes;
25+
gf::SecureHash::Hash input_hash;
26+
gf::SecureHash::Hash output_hash;
2527

2628
{
2729
gf::BufferOutputStream ostream(&bytes);
28-
gf::Serializer serializer(&ostream);
30+
gf::HashedOutputStream hashed_ostream(&ostream);
31+
gf::Serializer serializer(&hashed_ostream);
2932
serializer | in;
33+
input_hash = hashed_ostream.hash();
3034
}
3135

3236
{
3337
gf::BufferInputStream istream(&bytes);
34-
gf::Deserializer deserializer(&istream);
38+
gf::HashedInputStream hashed_istream(&istream);
39+
gf::Deserializer deserializer(&hashed_istream);
3540
deserializer | out;
41+
output_hash = hashed_istream.hash();
3642
}
43+
44+
EXPECT_EQ(input_hash, output_hash);
3745
}
3846

3947
struct SizeWrapper {

0 commit comments

Comments
 (0)