You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: downloaders.go
    path of file: ./repos/rclone/vfs/vfscache/downloaders
    
    the code of the file until where you have to start completion: // Package downloaders provides utilities for the VFS layer
package downloaders

import (
	"context"
	"errors"
	"fmt"
	"sync"
	"time"

	"github.com/rclone/rclone/fs"
	"github.com/rclone/rclone/fs/accounting"
	"github.com/rclone/rclone/fs/asyncreader"
	"github.com/rclone/rclone/fs/chunkedreader"
	"github.com/rclone/rclone/fs/fserrors"
	"github.com/rclone/rclone/lib/ranges"
	"github.com/rclone/rclone/vfs/vfscommon"
)

// FIXME implement max downloaders

const (
	// max time a downloader can be idle before closing itself
	maxDownloaderIdleTime = 5 * time.Second
	// max number of bytes a reader should skip over before closing it
	maxSkipBytes = 1024 * 1024
	// time between background kicks of waiters to pick up errors
	backgroundKickerInterval = 5 * time.Second
	// maximum number of errors before declaring dead
	maxErrorCount = 10
	// If a downloader is within this range or --buffer-size
	// whichever is the larger, we will reuse the downloader
	minWindow = 1024 * 1024
)

// Item is the interface that an item to download must obey
type Item interface {
	// FindMissing adjusts r returning a new ranges.Range which only
	// contains the range which needs to be downloaded. This could be
	// empty - check with IsEmpty. It also adjust this to make sure it is
	// not larger than the file.
	FindMissing(r ranges.Range) (outr ranges.Range)

	// HasRange returns true if the current ranges entirely include range
	HasRange(r ranges.Range) bool

	// WriteAtNoOverwrite writes b to the file, but will not overwrite
	// already present ranges.
	//
	// This is used by the downloader to write bytes to the file
	//

    
func (dl *downloader) Write(p []byte) (n int, err error) {
	// defer log.Trace(dl.dls.src, "p_len=%d", len(p))("n=%d, err=%v", &n, &err)

	// Kick the waiters on exit if some characters received
	defer func() {
		if n <= 0 {
			return
		}
		if waitErr := dl.dls.kickWaiters(); waitErr != nil {
			fs.Errorf(dl.dls.src, "vfs cache: download write: failed to kick waiters: %v", waitErr)
			if err == nil {
				err = waitErr
			}
		}
	}()

	dl.mu.Lock()
	defer dl.mu.Unlock()

	// Wait here if we have reached maxOffset until
	// - we are quitting
	// - we get kicked
	// - timeout happens
loop:
	for dl.offset >= dl.maxOffset {
		var timeout = time.NewTimer(maxDownloaderIdleTime)
		dl.mu.Unlock()
		select {
		case <-dl.quit:
			dl.mu.Lock()
			timeout.Stop()
			break loop
		case <-dl.kick:
			dl.mu.Lock()
			timeout.Stop()
		case <-timeout.C:
			// stop any future reading
			dl.mu.Lock()
			if !dl.stop {
				fs.Debugf(dl.dls.src, "vfs cache: stopping download thread as it timed out")
				dl._stop()
			}
			break loop
		}
	}

	n, skipped, err := dl.dls.item.WriteAtNoOverwrite(p, dl.offset)
	if skipped == n {
		dl.skipped += int64(skipped)
	} else {
		dl.skipped = 0
	}
	dl.offset += int64(n)

	// Kill this downloader if skipped too many bytes
	if !dl.stop && dl.skipped > maxSkipBytes {
		fs.Debugf(dl.dls.src, "vfs cache: stopping download thread as it has skipped %d bytes", dl.skipped)
		dl._stop()
	}

	// If running without a async buffer then stop now as
	// StopBuffering has no effect if the Account wasn't buffered
	// so we need to stop manually now rather than wait for the
	// AsyncReader to stop.
	if dl.stop && !dl.in.HasBuffer() {
		err = asyncreader.ErrorStreamAbandoned
	}
	return n, err
}