@Override
	public long read(T target) throws IOException {
		int totalRead = 0;
		Date started = timeout == 0 ? null : new Date();
		// if we still need to read something and we haven't done so already, do so
		while (target.remainingSpace() > 0) {
			long read = parent.read(target);
			if (read == -1) {
				return totalRead == 0 ? -1 : totalRead;
			}
			else if (read == 0 && alreadyRead >= minimumAmountToRead) {
				break;
			}
			// the minimum amount is not yet reached
			// check that the read did not time out (avoid long read attacks)
			else if (alreadyRead < minimumAmountToRead && started != null && new Date().getTime() - started.getTime() > timeout) {
				throw new IOException("The read timed out");
			}
			totalRead += read;
			alreadyRead += read;
		}
		return totalRead;
	}