| 2801 | } |
| 2802 | |
| 2803 | void ApiWrap::filePartDone(int64 offset, const MTPupload_File &result) { |
| 2804 | Expects(_fileProcess != nullptr); |
| 2805 | Expects(!_fileProcess->requests.empty()); |
| 2806 | |
| 2807 | if (result.type() == mtpc_upload_fileCdnRedirect) { |
| 2808 | error("Cdn redirect is not supported."); |
| 2809 | return; |
| 2810 | } |
| 2811 | const auto &data = result.c_upload_file(); |
| 2812 | if (data.vbytes().v.isEmpty()) { |
| 2813 | if (_fileProcess->size > 0) { |
| 2814 | error("Empty bytes received in file part."); |
| 2815 | return; |
| 2816 | } |
| 2817 | const auto result = _fileProcess->file.writeBlock({}); |
| 2818 | if (!result) { |
| 2819 | ioError(result); |
| 2820 | return; |
| 2821 | } |
| 2822 | } else { |
| 2823 | using Request = FileProcess::Request; |
| 2824 | auto &requests = _fileProcess->requests; |
| 2825 | const auto i = ranges::find( |
| 2826 | requests, |
| 2827 | offset, |
| 2828 | [](const Request &request) { return request.offset; }); |
| 2829 | Assert(i != end(requests)); |
| 2830 | |
| 2831 | i->bytes = data.vbytes().v; |
| 2832 | |
| 2833 | auto &file = _fileProcess->file; |
| 2834 | while (!requests.empty() && !requests.front().bytes.isEmpty()) { |
| 2835 | const auto &bytes = requests.front().bytes; |
| 2836 | if (const auto result = file.writeBlock(bytes); !result) { |
| 2837 | ioError(result); |
| 2838 | return; |
| 2839 | } |
| 2840 | requests.pop_front(); |
| 2841 | } |
| 2842 | |
| 2843 | if (_fileProcess->progress) { |
| 2844 | _fileProcess->progress(FileProgress{ |
| 2845 | file.size(), |
| 2846 | _fileProcess->size }); |
| 2847 | } |
| 2848 | |
| 2849 | if (!requests.empty() |
| 2850 | || !_fileProcess->size |
| 2851 | || _fileProcess->size > _fileProcess->offset) { |
| 2852 | loadFilePart(); |
| 2853 | return; |
| 2854 | } |
| 2855 | } |
| 2856 | |
| 2857 | auto process = base::take(_fileProcess); |
| 2858 | const auto relativePath = process->relativePath; |
| 2859 | _fileCache->save(process->location, relativePath); |
| 2860 | process->done(process->relativePath); |