code: func NewFileReader(ctx context.Context, fetcher blob.Fetcher, fileBlobRef blob.Ref) (*FileReader, error) {
  	// TODO(bradfitz): rename this into bytes reader? but for now it's still
  	//                 named FileReader, but can also read a "bytes" schema.
  	if !fileBlobRef.Valid() {
  		return nil, errors.New("schema/filereader: NewFileReader blobref invalid")
  	}
  	rc, _, err := fetcher.Fetch(ctx, fileBlobRef)
  	if err != nil {
  		return nil, fmt.Errorf("schema/filereader: fetching file schema blob: %v", err)
  	}
  	defer rc.Close()
  	ss, err := parseSuperset(rc)
  	if err != nil {
  		return nil, fmt.Errorf("schema/filereader: decoding file schema blob: %v", err)
  	}
  	ss.BlobRef = fileBlobRef
  	if ss.Type != "file" && ss.Type != "bytes" {
  		return nil, fmt.Errorf("schema/filereader: expected \"file\" or \"bytes\" schema blob, got %q", ss.Type)
  	}
  	fr, err := ss.NewFileReader(fetcher)
  	if err != nil {
  		return nil, fmt.Errorf("schema/filereader: creating FileReader for %s: %v", fileBlobRef, err)
  	}
  	return fr, nil
  }
docs: // NewFileReader returns a new FileReader reading the contents of fileBlobRef,
  // fetching blobs from fetcher.  The fileBlobRef must be of a "bytes" or "file"
  // schema blob.
  //
  // The caller should call Close on the FileReader when done reading.