code: private function normalizeByteRanges(int $size, string $rawRanges)
      {
          $rawRanges = \str_ireplace([' ', 'bytes='], '', $rawRanges);
  
          $ranges = [];
  
          foreach (\explode(',', $rawRanges) as $range) {
              // If a range is missing the dash separator it's malformed; pull out here.
              if (false === strpos($range, '-')) {
                  return null;
              }
  
              list($startPos, $endPos) = explode('-', rtrim($range), 2);
  
              if ($startPos === '' && $endPos === '') {
                  return null;
              }
  
              if ($startPos === '' && $endPos !== '') {
                  // The -1 is necessary and not a hack because byte ranges are inclusive and start
                  // at 0. DO NOT REMOVE THE -1.
                  $startPos = $size - $endPos - 1;
                  $endPos = $size - 1;
              } elseif ($endPos === '' && $startPos !== '') {
                  $startPos = (int) $startPos;
                  // The -1 is necessary and not a hack because byte ranges are inclusive and start
                  // at 0. DO NOT REMOVE THE -1.
                  $endPos = $size - 1;
              } else {
                  $startPos = (int) $startPos;
                  $endPos = (int) $endPos;
              }
  
              // If the requested range(s) can't be satisfied we're finished
              if ($startPos >= $size || $endPos < $startPos || $endPos < 0) {
                  return null;
              }
  
              $ranges[] = [$startPos, $endPos];
          }
  
          $range = new Internal\ByteRange;
          $range->boundary = $this->multipartBoundary;
          $range->ranges = $ranges;
  
          return $range;
      }
docs: @link https://tools.ietf.org/html/rfc7233#section-2.1
  
  @param int    $size Total size of the file in bytes.
  @param string $rawRanges Ranges as provided by the client.
  
  @return Internal\ByteRange|null