protected override async Task <IReadOnlyCollection <Blob> > ListAtAsync(string path, ListOptions options, CancellationToken cancellationToken)
        {
            ObjectsResource.ListRequest request = _client.Service.Objects.List(_bucketName);
            request.Prefix    = StoragePath.IsRootPath(path) ? null : (NormalisePath(path) + "/");
            request.Delimiter = "/";

            var page = new List <Blob>();

            do
            {
                Objects serviceObjects = await request.ExecuteAsync(cancellationToken : cancellationToken).ConfigureAwait(false);

                if (serviceObjects.Items != null)
                {
                    page.AddRange(GConvert.ToBlobs(serviceObjects.Items, options));
                }

                if (serviceObjects.Prefixes != null)
                {
                    //the only info we have about prefixes is it's name
                    page.AddRange(serviceObjects.Prefixes.Select(p => new Blob(p, BlobItemKind.Folder)));
                }


                request.PageToken = serviceObjects.NextPageToken;
            }while(request.PageToken != null);

            return(page);
        }
        private async Task <IReadOnlyCollection <Blob> > LegacyListAtAsync(string path, ListOptions options, CancellationToken cancellationToken)
        {
            PagedAsyncEnumerable <Objects, Object> objects = _client.ListObjectsAsync(
                _bucketName,
                StoragePath.IsRootPath(options.FolderPath) ? null : options.FolderPath,
                new ListObjectsOptions
            {
                Delimiter = options.Recurse ? null : "/"
            });

            return(await GConvert.ToBlobsAsync(objects, options).ConfigureAwait(false));
        }
        protected override async Task <Blob> GetBlobAsync(string fullPath, CancellationToken cancellationToken)
        {
            fullPath = NormalisePath(fullPath);

            try
            {
                Object obj = await _client.GetObjectAsync(_bucketName, fullPath,
                                                          new GetObjectOptions
                {
                    //todo
                },
                                                          cancellationToken).ConfigureAwait(false);

                return(GConvert.ToBlob(obj));
            }
            catch (GoogleApiException ex) when(ex.HttpStatusCode == HttpStatusCode.NotFound)
            {
                return(null);
            }
        }