| 642 | } |
| 643 | |
| 644 | func (r *jsStreamReader) Read(p []byte) (n int, err error) { |
| 645 | if r.bytesRead >= r.totalSize { |
| 646 | return 0, io.EOF |
| 647 | } |
| 648 | |
| 649 | fmt.Printf("Read %d bytes\n", len(p)) |
| 650 | |
| 651 | // If we have buffered data, use it first |
| 652 | if r.buffer.Len() > 0 { |
| 653 | n, _ = r.buffer.Read(p) |
| 654 | r.bytesRead += int64(n) |
| 655 | |
| 656 | if r.onProgress.Truthy() { |
| 657 | r.onProgress.Invoke(r.bytesRead) |
| 658 | } |
| 659 | return n, nil |
| 660 | } |
| 661 | |
| 662 | // Only read from stream if buffer is empty |
| 663 | promise := r.reader.Call("read") |
| 664 | result := await(promise) |
| 665 | |
| 666 | if result.Get("done").Bool() { |
| 667 | if r.bytesRead < r.totalSize { |
| 668 | return 0, fmt.Errorf("stream ended prematurely at %d/%d bytes", r.bytesRead, r.totalSize) |
| 669 | } |
| 670 | return 0, io.EOF |
| 671 | } |
| 672 | |
| 673 | // Get the chunk from JavaScript and write it to our buffer |
| 674 | value := result.Get("value") |
| 675 | chunk := make([]byte, value.Length()) |
| 676 | js.CopyBytesToGo(chunk, value) |
| 677 | r.buffer.Write(chunk) |
| 678 | |
| 679 | // Now read what we can into p |
| 680 | n, _ = r.buffer.Read(p) |
| 681 | r.bytesRead += int64(n) |
| 682 | |
| 683 | if r.onProgress.Truthy() { |
| 684 | r.onProgress.Invoke(r.bytesRead) |
| 685 | } |
| 686 | |
| 687 | return n, nil |
| 688 | } |
| 689 | |
| 690 | // Helper function to await a JavaScript promise |
| 691 | func await(promise js.Value) js.Value { |