diff options
author | Bjørn Erik Pedersen <[email protected]> | 2024-02-03 11:40:08 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2024-02-03 15:07:59 +0100 |
commit | e33a63255187bb4c5323e107b727e1d7b0117d19 (patch) | |
tree | 1f0b7942c54fbbcb2a442a2ac53bb00c748dd7e2 | |
parent | 28733248983c1afc1e4e15dfc30fcf4c442e6ca4 (diff) | |
download | hugo-e33a63255187bb4c5323e107b727e1d7b0117d19.tar.gz hugo-e33a63255187bb4c5323e107b727e1d7b0117d19.zip |
resources: Optimize reading resource Content when it's already a string
-rw-r--r-- | common/hugio/readers.go | 47 | ||||
-rw-r--r-- | resources/resource.go | 7 |
2 files changed, 38 insertions, 16 deletions
diff --git a/common/hugio/readers.go b/common/hugio/readers.go index feb1b1412..9745d7841 100644 --- a/common/hugio/readers.go +++ b/common/hugio/readers.go @@ -37,32 +37,47 @@ type ReadSeekCloserProvider interface { ReadSeekCloser() (ReadSeekCloser, error) } -// ReadSeekerNoOpCloser implements ReadSeekCloser by doing nothing in Close. -// TODO(bep) rename this and similar to ReadSeekerNopCloser, naming used in stdlib, which kind of makes sense. -type ReadSeekerNoOpCloser struct { +// readSeekerNopCloser implements ReadSeekCloser by doing nothing in Close. +type readSeekerNopCloser struct { ReadSeeker } // Close does nothing. -func (r ReadSeekerNoOpCloser) Close() error { +func (r readSeekerNopCloser) Close() error { return nil } // NewReadSeekerNoOpCloser creates a new ReadSeekerNoOpCloser with the given ReadSeeker. -func NewReadSeekerNoOpCloser(r ReadSeeker) ReadSeekerNoOpCloser { - return ReadSeekerNoOpCloser{r} +func NewReadSeekerNoOpCloser(r ReadSeeker) ReadSeekCloser { + return readSeekerNopCloser{r} } // NewReadSeekerNoOpCloserFromString uses strings.NewReader to create a new ReadSeekerNoOpCloser // from the given string. -func NewReadSeekerNoOpCloserFromString(content string) ReadSeekerNoOpCloser { - return ReadSeekerNoOpCloser{strings.NewReader(content)} +func NewReadSeekerNoOpCloserFromString(content string) ReadSeekCloser { + return strigReadSeeker{s: content, readSeekerNopCloser: readSeekerNopCloser{strings.NewReader(content)}} +} + +var _ StringReader = (*strigReadSeeker)(nil) + +type strigReadSeeker struct { + s string + readSeekerNopCloser +} + +func (s *strigReadSeeker) ReadString() string { + return s.s +} + +// StringReader provides a way to read a string. +type StringReader interface { + ReadString() string } // NewReadSeekerNoOpCloserFromString uses strings.NewReader to create a new ReadSeekerNoOpCloser // from the given bytes slice. -func NewReadSeekerNoOpCloserFromBytes(content []byte) ReadSeekerNoOpCloser { - return ReadSeekerNoOpCloser{bytes.NewReader(content)} +func NewReadSeekerNoOpCloserFromBytes(content []byte) readSeekerNopCloser { + return readSeekerNopCloser{bytes.NewReader(content)} } // NewReadSeekCloser creates a new ReadSeekCloser from the given ReadSeeker. @@ -77,3 +92,15 @@ func NewOpenReadSeekCloser(r ReadSeekCloser) OpenReadSeekCloser { // OpenReadSeekCloser allows setting some other way (than reading from a filesystem) // to open or create a ReadSeekCloser. type OpenReadSeekCloser func() (ReadSeekCloser, error) + +// ReadString reads from the given reader and returns the content as a string. +func ReadString(r io.Reader) (string, error) { + if sr, ok := r.(StringReader); ok { + return sr.ReadString(), nil + } + b, err := io.ReadAll(r) + if err != nil { + return "", err + } + return string(b), nil +} diff --git a/resources/resource.go b/resources/resource.go index 6bef1b275..c11756bca 100644 --- a/resources/resource.go +++ b/resources/resource.go @@ -418,12 +418,7 @@ func (l *genericResource) Content(context.Context) (any, error) { } defer r.Close() - var b []byte - b, err = io.ReadAll(r) - if err != nil { - return "", err - } - return string(b), nil + return hugio.ReadString(r) } func (r *genericResource) Err() resource.ResourceError { |