···155155 return b, nil
156156}
157157158158+type chunk struct {
159159+ start uint64
160160+ end uint64
161161+}
162162+163163+func (c chunk) size() uint64 { return (c.end + 1) - c.start }
164164+func (c chunk) rangeHeader() string { return fmt.Sprintf("bytes=%d-%d", c.start, c.end) }
165165+166166+func (d *Downloader) chunks(t uint64) []chunk {
167167+ var start uint64
168168+ last := t - 1
169169+ var c []chunk
170170+ for {
171171+ end := start + d.ChunkSize - 1
172172+ if end > last {
173173+ end = last
174174+ }
175175+ c = append(c, chunk{start, end})
176176+ if end == last {
177177+ break
178178+ }
179179+ start = end + 1
180180+ }
181181+ return c
182182+}
183183+158184// DownloadWithContext is a version of Download that takes a context. The
159185// context can be used to stop all downloads in progress.
160186func (d *Downloader) DownloadWithContext(ctx context.Context, urls ...string) <-chan DownloadStatus {
+26
main_test.go
···176176 t.Error("expected channel closed, but did not get it")
177177 }
178178}
179179+180180+func TestDownload_Chunks(t *testing.T) {
181181+ d := DefaultDownloader()
182182+ d.ChunkSize = 5
183183+ got := d.chunks(12)
184184+ chunks := []chunk{{0, 4}, {5, 9}, {10, 11}}
185185+ sizes := []uint64{5, 5, 2}
186186+ headers := []string{"bytes=0-4", "bytes=5-9", "bytes=10-11"}
187187+ if len(got) != len(chunks) {
188188+ t.Errorf("expected %d chunks, got %d", len(chunks), len(got))
189189+ }
190190+ for i := range got {
191191+ if got[i].start != chunks[i].start {
192192+ t.Errorf("expected chunk #%d to start at %d, got %d", i+1, chunks[i].start, got[i].start)
193193+ }
194194+ if got[i].end != chunks[i].end {
195195+ t.Errorf("expected chunk #%d to end at %d, got %d", i+1, chunks[i].end, got[i].end)
196196+ }
197197+ if got[i].size() != sizes[i] {
198198+ t.Errorf("expected chunk #%d to have size %d, got %d", i+1, sizes[i], got[i].size())
199199+ }
200200+ if got[i].rangeHeader() != headers[i] {
201201+ t.Errorf("expected chunk #%d header to be %s, got %s", i+1, headers[i], got[i].rangeHeader())
202202+ }
203203+ }
204204+}