Skip to content

Commit

Permalink
embed: implement openFile.ReadAt
Browse files Browse the repository at this point in the history
Implementation copied from testing/fstest/mapfs.go

Fixes golang#57803

Change-Id: I531682b50ab6663511bac41fce7614ab9197bf38
GitHub-Last-Rev: d9bcc1c
GitHub-Pull-Request: golang#59489
Reviewed-on: https://go-review.googlesource.com/c/go/+/483235
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: David Chase <drchase@google.com>
  • Loading branch information
ncruces authored and gopherbot committed Apr 12, 2023
1 parent 6116a47 commit da2755b
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 2 deletions.
16 changes: 14 additions & 2 deletions src/embed/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ func (f FS) readDir(dir string) []file {

// Open opens the named file for reading and returns it as an fs.File.
//
// The returned file implements io.Seeker when the file is not a directory.
// The returned file implements io.Seeker and io.ReaderAt when the file is not a directory.
func (f FS) Open(name string) (fs.File, error) {
file := f.lookup(name)
if file == nil {
Expand Down Expand Up @@ -346,7 +346,8 @@ type openFile struct {
}

var (
_ io.Seeker = (*openFile)(nil)
_ io.Seeker = (*openFile)(nil)
_ io.ReaderAt = (*openFile)(nil)
)

func (f *openFile) Close() error { return nil }
Expand Down Expand Up @@ -380,6 +381,17 @@ func (f *openFile) Seek(offset int64, whence int) (int64, error) {
return offset, nil
}

func (f *openFile) ReadAt(b []byte, offset int64) (int, error) {
if offset < 0 || offset > int64(len(f.f.data)) {
return 0, &fs.PathError{Op: "read", Path: f.f.name, Err: fs.ErrInvalid}
}
n := copy(b, f.f.data[offset:])
if n < len(b) {
return n, io.EOF
}
return n, nil
}

// An openDir is a directory open for reading.
type openDir struct {
f *file // the directory file itself
Expand Down
57 changes: 57 additions & 0 deletions src/embed/internal/embedtest/embed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package embedtest

import (
"embed"
"io"
"reflect"
"testing"
"testing/fstest"
Expand Down Expand Up @@ -176,3 +177,59 @@ func TestAliases(t *testing.T) {
check(helloBytes)
check(helloString)
}

func TestOffset(t *testing.T) {
file, err := testDirAll.Open("testdata/hello.txt")
if err != nil {
t.Fatal("Open:", err)
}

const want = "hello, world\n"

// Read the entire file.
got := make([]byte, len(want))
n, err := file.Read(got)
if err != nil {
t.Fatal("Read:", err)
}
if n != len(want) {
t.Fatal("Read:", n)
}
if string(got) != want {
t.Fatalf("Read: %q", got)
}

// Try to read one byte; confirm we're at the EOF.
var buf [1]byte
n, err = file.Read(buf[:])
if err != io.EOF {
t.Fatal("Read:", err)
}
if n != 0 {
t.Fatal("Read:", n)
}

// Use seek to get the offset at the EOF.
seeker := file.(io.Seeker)
off, err := seeker.Seek(0, io.SeekCurrent)
if err != nil {
t.Fatal("Seek:", err)
}
if off != int64(len(want)) {
t.Fatal("Seek:", off)
}

// Use ReadAt to read the entire file, ignoring the offset.
at := file.(io.ReaderAt)
got = make([]byte, len(want))
n, err = at.ReadAt(got, 0)
if err != nil {
t.Fatal("ReadAt:", err)
}
if n != len(want) {
t.Fatal("ReadAt:", n)
}
if string(got) != want {
t.Fatalf("ReadAt: %q", got)
}
}

0 comments on commit da2755b

Please sign in to comment.