public async Task<bool> SetContentAsync(RootName root, FileId target, Stream content, IProgress<ProgressValue> progress, Func<FileSystemInfoLocator> locatorResolver)
        {
            var context = await RequireContext(root);

            var itemReference = await AsyncFunc.Retry<GoogleFile, GoogleApiException>(async () => await context.Service.Files.Get(target.Value).ExecuteAsync(), RETRIES);
            var update = context.Service.Files.Update(itemReference, target.Value, content, itemReference.MimeType);
            update.ProgressChanged += p => progress.Report(new ProgressValue((int)p.BytesSent, (int)content.Length));
            await AsyncFunc.Retry<IUploadProgress, GoogleApiException>(async () => await update.UploadAsync(), RETRIES);

            return true;
        }
 public void ClearContent(RootName root, FileId target)
 {
     throw new NotSupportedException(Resources.SettingOfFileContentNotSupported);
 }
        public async Task<bool> ClearContentAsync(RootName root, FileId target, Func<FileSystemInfoLocator> locatorResolver)
        {
            var context = await RequireContext(root);

            await AsyncFunc.Retry<IUploadProgress, GoogleApiException>(async () => await context.Service.Files.Update(null, target.Value, new MemoryStream(), MIME_TYPE_FILE).UploadAsync(), RETRIES);

            return true;
        }
        public async Task<Stream> GetContentAsync(RootName root, FileId source)
        {
            var context = await RequireContext(root);

            var itemReference = await AsyncFunc.Retry<GoogleFile, GoogleApiException>(async () => await context.Service.Files.Get(source.Value).ExecuteAsync(), RETRIES);
            //var stream = new MemoryStream(await AsyncFunc.Retry<byte[], GoogleApiException>(async () => await context.Service.HttpClient.GetByteArrayAsync(itemReference.DownloadUrl), RETRIES));
            var stream = await AsyncFunc.Retry<Stream, GoogleApiException>(async () => await context.Service.HttpClient.GetStreamAsync(itemReference.DownloadUrl), RETRIES);

            return stream;
        }
        public async Task<bool> SetContentAsync(RootName root, FileId target, Stream content, IProgress<ProgressValue> progress, Func<FileSystemInfoLocator> locatorResolver)
        {
            var context = await RequireContext(root);

            var locator = locatorResolver();
            var tokenSource = new CancellationTokenSource();
            await context.Client.UploadFileAsync(content, ToId(locator.ParentId), locator.Name, tokenSource.Token);

            return true;
        }
        private static long ToId(FileId fileId)
        {
            if (!fileId.Value.StartsWith("f", StringComparison.Ordinal))
                throw new FormatException(string.Format(CultureInfo.InvariantCulture, Resources.InvalidFileId, fileId));

            return long.Parse(fileId.Value.Substring(1), NumberStyles.Number);
        }
        public async Task<bool> ClearContentAsync(RootName root, FileId target, Func<FileSystemInfoLocator> locatorResolver)
        {
            var context = await RequireContext(root);

            var locator = locatorResolver();
            var tokenSource = new CancellationTokenSource();
            await context.Client.UploadFileAsync(new MemoryStream(), ToId(locator.ParentId), locator.Name, tokenSource.Token);

            return true;
        }
        public async Task<Stream> GetContentAsync(RootName root, FileId source)
        {
            var context = await RequireContext(root);

            var stream = await AsyncFunc.Retry<Stream, BoxException>(async () => await context.Client.FilesManager.DownloadStreamAsync(source.Value), RETRIES);

            return stream;
        }
        public void SetContent(RootName root, FileId target, Stream content, IProgress<ProgressValue> progress)
        {
            if (root == null)
                throw new ArgumentNullException(nameof(root));
            if (target == null)
                throw new ArgumentNullException(nameof(target));
            if (content == null)
                throw new ArgumentNullException(nameof(content));

            var effectivePath = GetFullPath(root, target.Value);

            var file = new FileInfo(effectivePath);
            using (var stream = file.OpenWrite()) {
                content.CopyTo(stream);
            }
        }
        public void ClearContent(RootName root, FileId target)
        {
            if (root == null)
                throw new ArgumentNullException(nameof(root));
            if (target == null)
                throw new ArgumentNullException(nameof(target));

            var effectivePath = GetFullPath(root, target.Value);

            var file = new FileInfo(effectivePath);
            if (!file.Exists)
                throw new FileNotFoundException(string.Empty, target.Value);

            using (var stream = file.Open(FileMode.Truncate, FileAccess.Write)) {
                stream.Flush();
            }
        }
        public Stream GetContent(RootName root, FileId source)
        {
            if (root == null)
                throw new ArgumentNullException(nameof(root));
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            var effectivePath = GetFullPath(root, source.Value);

            var file = new FileInfo(effectivePath);
            if (!file.Exists)
                throw new FileNotFoundException(string.Empty, source.Value);

            return new BufferedStream(file.OpenRead());
        }
        public async Task<bool> SetContentAsync(RootName root, FileId target, Stream content, IProgress<ProgressValue> progress, Func<FileSystemInfoLocator> locatorResolver)
        {
            var context = await RequireContext(root);

            var locator = locatorResolver();
            var item = await AsyncFunc.Retry<FileSystem, ServerException>(async () => await context.Client.FileSystemManager.UploadNewFileStreamAsync(locator.ParentId.Value, locator.Name, new ProgressStream(content, progress), true), RETRIES);

            return true;
        }
        public async Task<Stream> GetContentAsync(RootName root, FileId source)
        {
            var context = await RequireContext(root);

            var stream = new MemoryStream();
            //await AsyncFunc.Retry<ServerException>(() => context.Client.FileSystemManager.DownloadFileStreamAsync(source.Value, stream), RETRIES);
            await context.Client.FileSystemManager.DownloadFileStreamAsync(source.Value, stream);
            stream.Seek(0, SeekOrigin.Begin);

            return stream;
        }
        public Stream GetContent(RootName root, FileId source)
        {
            var context = RequireContext(root);

            var nodes = context.Client.GetNodes();
            var item = nodes.Single(n => n.Id == source.Value);
            var stream = context.Client.Download(item);

            return stream;
        }
        public async Task<Stream> GetContentAsync(RootName root, FileId source)
        {
            var context = await RequireContext(root);

            var stream = new MemoryStream();
            var tokenSource = new CancellationTokenSource();
            //await AsyncFunc.Retry<Stream, pCloudException>(async () => await context.Client.DownloadFileAsync(ToId(source), stream, tokenSource.Token), RETRIES);
            await context.Client.DownloadFileAsync(ToId(source), stream, tokenSource.Token);
            stream.Seek(0, SeekOrigin.Begin);

            return stream;
        }
 public void SetContent(RootName root, FileId target, Stream content, IProgress<ProgressValue> progress)
 {
     throw new NotSupportedException(Resources.SettingOfFileContentNotSupported);
 }
        public async Task<bool> ClearContentAsync(RootName root, FileId target, Func<FileSystemInfoLocator> locatorResolver)
        {
            var context = await RequireContext(root);

            var locator = locatorResolver();
            await AsyncFunc.Retry<BoxFile, BoxException>(async () => await context.Client.FilesManager.UploadNewVersionAsync(locator.Name, target.Value, new MemoryStream()), RETRIES);

            return true;
        }