aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2024-02-03 11:40:08 +0100
committerBjørn Erik Pedersen <[email protected]>2024-02-03 15:07:59 +0100
commite33a63255187bb4c5323e107b727e1d7b0117d19 (patch)
tree1f0b7942c54fbbcb2a442a2ac53bb00c748dd7e2
parent28733248983c1afc1e4e15dfc30fcf4c442e6ca4 (diff)
downloadhugo-e33a63255187bb4c5323e107b727e1d7b0117d19.tar.gz
hugo-e33a63255187bb4c5323e107b727e1d7b0117d19.zip
resources: Optimize reading resource Content when it's already a string
-rw-r--r--common/hugio/readers.go47
-rw-r--r--resources/resource.go7
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 {