code: public long size() throws IOException {
      Optional<Long> sizeIfKnown = sizeIfKnown();
      if (sizeIfKnown.isPresent()) {
        return sizeIfKnown.get();
      }
  
      Closer closer = Closer.create();
      try {
        InputStream in = closer.register(openStream());
        return countBySkipping(in);
      } catch (IOException e) {
        // skip may not be supported... at any rate, try reading
      } finally {
        closer.close();
      }
  
      closer = Closer.create();
      try {
        InputStream in = closer.register(openStream());
        return ByteStreams.exhaust(in);
      } catch (Throwable e) {
        throw closer.rethrow(e);
      } finally {
        closer.close();
      }
    }
docs: Returns the size of this source in bytes, even if doing so requires opening and traversing an
  entire stream. To avoid a potentially expensive operation, see {@link #sizeIfKnown}.
  
  <p>The default implementation calls {@link #sizeIfKnown} and returns the value if present. If
  absent, it will fall back to a heavyweight operation that will open a stream, read (or {@link
  InputStream#skip(long) skip}, if possible) to the end of the stream and return the total number
  of bytes that were read.
  
  <p>Note that for some sources that implement {@link #sizeIfKnown} to provide a more efficient
  implementation, it is <i>possible</i> that this method will return a different number of bytes
  than would be returned by reading all of the bytes (for example, some special files may return
  a size of 0 despite actually having content when read).
  
  <p>In either case, for mutable sources such as files, a subsequent read may return a different
  number of bytes if the contents are changed.
  
  @throws IOException if an I/O error occurs while reading the size of this source