/**
  * @param In $inputStream The message input stream
  * @param MessageInterface $message The message to map the data into
  *
  * @throws \Avalonia\Component\Message\Exception\MapperInvalidArgumentException if the given $rawData is not of the good type
  * @throws \Avalonia\Component\Message\Exception\MapperInvalidDataException if the given $rawData doesn't not fetch the required format
  *
  * Maps the given stream into a message
  */
 public function mapStreamToMessage(In $inputStream, MessageInterface $message)
 {
     $start = $inputStream->read(strlen(static::HTTP_RESPONSE_STATUS_START));
     if (static::HTTP_RESPONSE_STATUS_START === $start) {
         $statusLine = $start . $this->readHttpLine($inputStream, false);
         if (0 === preg_match(static::HTTP_RESPONSE_STATUS_PATTERN, $statusLine, $parsedStatusLine)) {
             throw new HttpMapperInvalidStatusException(sprintf("The HTTP command line is not valid: \"%s. Expected format: HTTP/1.0|1.1 CODE MESSAGE", $statusLine));
         }
         $message->setHeader(HttpMessage::HEADER_HTTP_STATUS_CODE, (int) $parsedStatusLine["code"]);
         $message->setHeader(HttpMessage::HEADER_HTTP_STATUS_MESSAGE, $parsedStatusLine["message"]);
         $message->setHeader(HttpMessage::HEADER_HTTP_VERSION, $parsedStatusLine["version"]);
         // Then read headers and body
         $this->readHttpHeaderAndBody($inputStream, $message);
     } else {
         $message->setHeader(HttpMessage::HEADER_HTTP_VERSION, static::DEFAULT_HTTP_VERSION);
         $message->setBody($start . $inputStream->readAll());
     }
 }
 /**
  * @param In $inputStream The message input stream
  * @param MessageInterface $message The message to map the data into
  *
  * @throws \Avalonia\Component\Message\Exception\MapperInvalidArgumentException if the given $rawData is not of the good type
  * @throws \Avalonia\Component\Message\Exception\MapperInvalidDataException if the given $rawData doesn't not fetch the required format
  *
  * Maps the given stream into a message
  */
 public function mapDataToStream(In $inputStream, MessageInterface $message)
 {
     // parse http command line
     try {
         $command = $this->readHttpLine($inputStream, false, $offset);
     } catch (MapperInvalidDataEofFoundException $e) {
         // One line request, it can be an HTTP 0.9 one
         $command = $e->getRemainingBufferData();
     }
     if (0 === preg_match(static::HTTP_REQUEST_COMMAND_PATTERN, $command, $parsedCommand)) {
         throw new HttpMapperInvalidCommandException(sprintf("The HTTP command line is not valid: \"%s. Expected format: COMMAND URL [HTTP/VERSION].", $command));
     }
     $message->setHeader(HttpMessage::HEADER_HTTP_METHOD, $parsedCommand["method"]);
     $message->setHeader(HttpMessage::HEADER_HTTP_VERSION, $parsedCommand["version"] ?? static::DEFAULT_HTTP_VERSION);
     $message->setHeader(HttpMessage::HEADER_HTTP_URI, $parsedCommand["uri"]);
     // If the uri contains a query string, parse it and place its values in the headers
     if (isset($parsedCommand["query"])) {
         parse_str($parsedCommand["query"], $parsedQuery);
         foreach ($parsedQuery as $name => $value) {
             // This is equivalent to HttpMessage::setQueryHeader($name, $value)
             $message->setHeader(HttpMessage::HTTP_QUERY_HEADER_PREFIX . $name, $value);
         }
     }
     // Then read headers
     while (!$inputStream->eof()) {
         try {
             $line = $this->readHttpLine($inputStream, false, $offset);
         } catch (MapperInvalidDataEofFoundException $e) {
             // If this exception is caught, it means that the message doesn't have a body.
             // So parse the remaining data in the buffer
             $line = $e->getRemainingBufferData();
         }
         if ('' === $line) {
             // We reached the body
             $message->setBody($inputStream->readAll($offset));
             // stop the loop as the mapping is finished
             break;
         } elseif (0 === preg_match(static::HTTP_HEADER_PATTERN, $line, $parsedHeader)) {
             throw new HttpMapperInvalidHeaderException(sprintf("The given HTTP header line is not valid: \"%s\". Expected format: HEADER-NAME: VALUE.", $line));
         }
         $message->setHeader($parsedHeader["header"], $parsedHeader["value"]);
     }
 }
 /**
  * @param In $inputStream The message input stream
  * @param MessageInterface $message The message to map the data into
  *
  * @throws \Avalonia\Component\Message\Exception\MapperInvalidArgumentException if the given $rawData is not of the good type
  * @throws \Avalonia\Component\Message\Exception\MapperInvalidDataException if the given $rawData doesn't not fetch the required format
  *
  * Maps the given stream into a message
  */
 public function mapStreamToMessage(In $inputStream, MessageInterface $message)
 {
     $command = $this->readHttpLine($inputStream, false);
     if (0 === preg_match(static::HTTP_REQUEST_COMMAND_PATTERN, $command, $parsedCommand)) {
         throw new HttpMapperInvalidCommandException(sprintf("The HTTP command line is not valid: \"%s. Expected format: COMMAND URL [HTTP/1.0|1.1].", $command));
     }
     $message->setHeader(HttpMessage::HEADER_HTTP_METHOD, $parsedCommand["method"]);
     $message->setHeader(HttpMessage::HEADER_HTTP_VERSION, $parsedCommand["version"] ?? static::DEFAULT_HTTP_VERSION);
     $message->setHeader(HttpMessage::HEADER_HTTP_URI, $parsedCommand["uri"]);
     // If the uri contains a query string, parse it and place its values in the headers
     if (isset($parsedCommand["query"])) {
         parse_str($parsedCommand["query"], $parsedQuery);
         foreach ($parsedQuery as $name => $value) {
             // This is equivalent to HttpMessage::setQueryHeader($name, $value)
             $message->setHeader(HttpMessage::HTTP_QUERY_HEADER_PREFIX . $name, $value);
         }
     }
     // Then read headers and body
     $this->readHttpHeaderAndBody($inputStream, $message);
 }
 /**
  * @param In $inputStream
  * @param MessageInterface $message
  *
  * @throws HttpMapperInvalidHeaderException
  * @throws MapperInvalidDataException
  * @throws MapperMaxLineLengthException
  *
  * Parse http headers and body from the stream, and map it to $message
  */
 protected function readHttpHeaderAndBody(In $inputStream, MessageInterface $message)
 {
     while (!$inputStream->eof()) {
         try {
             $line = $this->readHttpLine($inputStream, false, $offset);
         } catch (MapperInvalidDataEofFoundException $e) {
             // If this exception is caught, it means that the message doesn't have a body.
             // So parse the remaining data in the buffer
             $line = $e->getRemainingBufferData();
         }
         if ('' === $line) {
             // We reached the body
             $message->setBody($inputStream->readAll());
             // stop the loop as the mapping is finished
             break;
         } elseif (0 === preg_match(static::HTTP_HEADER_PATTERN, $line, $parsedHeader)) {
             throw new HttpMapperInvalidHeaderException(sprintf("The given HTTP header line is not valid: \"%s\". Expected format: HEADER-NAME: VALUE.", $line));
         }
         $message->setHeader($parsedHeader["header"], $parsedHeader["content"]);
     }
 }