/**
  * Update a command with the content and tree hash headers, as needed.
  *
  * @param PreparedEvent $event Event emitted.
  *
  * @throws \RuntimeException if the body is not seekable.
  */
 public function onPrepared(PreparedEvent $event)
 {
     $command = $event->getCommand();
     $name = $command->getName();
     // Determine if there is a need to calculate any hashes.
     $needsHashes = ($name === 'UploadArchive' || $name === 'UploadPart') && (!$command['checksum'] || !$command['ContentSHA256']);
     if ($needsHashes) {
         $body = $event->getRequest()->getBody();
         if (!$body->isSeekable()) {
             throw new CouldNotCreateChecksumException('sha256');
         }
         // Add a tree hash if not provided.
         if (!$command['checksum']) {
             $body = new HashingStream($body, new TreeHash(), function ($result) use($command, $event) {
                 $event->getRequest()->setHeader('x-amz-sha256-tree-hash', bin2hex($result));
             });
         }
         // Add a linear content hash if not provided.
         if (!$command['ContentSHA256']) {
             $body = new HashingStream($body, new PhpHash('sha256'), function ($result) use($command) {
                 $command['ContentSHA256'] = bin2hex($result);
             });
         }
         // Read the stream in order to calculate the hashes.
         while (!$body->eof()) {
             $body->read(1048576);
         }
         $body->seek(0);
     }
     // Set the content hash header if there is a value to set.
     if ($hash = $command['ContentSHA256']) {
         $event->getRequest()->addHeader('x-amz-content-sha256', $hash);
     }
 }
 /**
  * @param StreamInterface $stream     Stream that is validated.
  * @param HashInterface   $hash       Hash used to calculate the hash.
  * @param string          $expected   The expected hash result.
  * @param callable        $onMismatch Optional function to invoke when there
  *     is a mismatch between the calculated hash and the expected hash.
  *     The callback is called with the resulting hash and the expected hash.
  *     This callback can be used to throw specific exceptions.
  */
 public function __construct(StreamInterface $stream, HashInterface $hash, $expected, $onMismatch = null)
 {
     $this->mismatchCallback = $onMismatch;
     $this->expected = $expected;
     $that = $this;
     parent::__construct($stream, $hash, function ($result) use($that) {
         if ($that->expected !== $result) {
             $that->mismatch($result);
         }
     });
 }