ReadAt reads len(b) bytes from the File starting at byte offset off. It returns the number of bytes read and the error, if any. ReadAt always returns a non-nil error when n < len(b). At end of file, that error is io.EOF.
(b []byte, offset int64)
| 461 | // ReadAt always returns a non-nil error when n < len(b). At end of |
| 462 | // file, that error is io.EOF. |
| 463 | func (o *Object) ReadAt(b []byte, offset int64) (n int, err error) { |
| 464 | if o == nil { |
| 465 | return 0, errInvalidArgument("Object is nil") |
| 466 | } |
| 467 | |
| 468 | // Locking. |
| 469 | o.mutex.Lock() |
| 470 | defer o.mutex.Unlock() |
| 471 | |
| 472 | // prevErr is error which was saved in previous operation. |
| 473 | if o.prevErr != nil && o.prevErr != io.EOF || o.isClosed { |
| 474 | return 0, o.prevErr |
| 475 | } |
| 476 | |
| 477 | // Save and restore currOffset so ReadAt doesn't affect sequential Read operations. |
| 478 | // Per io.ReaderAt: "ReadAt should not affect nor be affected by the underlying seek offset." |
| 479 | savedOffset := o.currOffset |
| 480 | defer func() { |
| 481 | o.currOffset = savedOffset |
| 482 | o.seekData = true // Force next Read to re-establish stream at correct position |
| 483 | }() |
| 484 | |
| 485 | o.currOffset = offset |
| 486 | |
| 487 | // Can only compare offsets to size when size has been set. |
| 488 | if o.objectInfoSet { |
| 489 | // If offset is negative than we return io.EOF. |
| 490 | // If offset is greater than or equal to object size we return io.EOF. |
| 491 | if (o.objectInfo.Size > -1 && offset >= o.objectInfo.Size) || offset < 0 { |
| 492 | return 0, io.EOF |
| 493 | } |
| 494 | } |
| 495 | |
| 496 | // Create the new readAt request. |
| 497 | readAtReq := getRequest{ |
| 498 | isReadOp: true, |
| 499 | isReadAt: true, |
| 500 | DidOffsetChange: true, // Offset always changes. |
| 501 | beenRead: o.beenRead, // Set if this is the first request to try and read. |
| 502 | Offset: offset, // Set the offset. |
| 503 | Buffer: b, |
| 504 | } |
| 505 | |
| 506 | // Alert that this is the first request. |
| 507 | if !o.isStarted { |
| 508 | readAtReq.isFirstReq = true |
| 509 | } |
| 510 | |
| 511 | // Send and receive from the first request. |
| 512 | response, err := o.doGetRequest(readAtReq) |
| 513 | if err != nil && err != io.EOF { |
| 514 | // Save the error. |
| 515 | o.prevErr = err |
| 516 | return response.Size, err |
| 517 | } |
| 518 | // Bytes read. |
| 519 | bytesRead := int64(response.Size) |
| 520 | // There is no valid objectInfo yet |
no test coverage detected