1<?php 2namespace Aws; 3 4use GuzzleHttp\Psr7\StreamDecoratorTrait; 5use Psr\Http\Message\StreamInterface; 6 7/** 8 * Stream decorator that calculates a rolling hash of the stream as it is read. 9 */ 10class HashingStream implements StreamInterface 11{ 12 use StreamDecoratorTrait; 13 14 /** @var HashInterface */ 15 private $hash; 16 17 /** @var callable|null */ 18 private $callback; 19 20 /** 21 * @param StreamInterface $stream Stream that is being read. 22 * @param HashInterface $hash Hash used to calculate checksum. 23 * @param callable $onComplete Optional function invoked when the 24 * hash calculation is completed. 25 */ 26 public function __construct( 27 StreamInterface $stream, 28 HashInterface $hash, 29 callable $onComplete = null 30 ) { 31 $this->stream = $stream; 32 $this->hash = $hash; 33 $this->callback = $onComplete; 34 } 35 36 public function read($length) 37 { 38 $data = $this->stream->read($length); 39 $this->hash->update($data); 40 if ($this->eof()) { 41 $result = $this->hash->complete(); 42 if ($this->callback) { 43 call_user_func($this->callback, $result); 44 } 45 } 46 47 return $data; 48 } 49 50 public function seek($offset, $whence = SEEK_SET) 51 { 52 if ($offset === 0) { 53 $this->hash->reset(); 54 return $this->stream->seek($offset); 55 } 56 57 // Seeking arbitrarily is not supported. 58 return false; 59 } 60} 61