Skip to content

Commit 0381ea2

Browse files
committed
x/stream: ReadSource, ReadSourceLocal, ReadSourceFromURI
1 parent 9f8e7fb commit 0381ea2

File tree

1 file changed

+68
-11
lines changed

1 file changed

+68
-11
lines changed

stream/stream.go

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,22 @@
1717
package stream
1818

1919
import (
20+
"bytes"
2021
"errors"
2122
"io"
2223
"io/fs"
2324
"os"
2425
"strings"
26+
27+
"github.com/qiniu/x/byteutil"
2528
)
2629

2730
var (
2831
// ErrUnknownScheme is returned when an unknown scheme is encountered in a URL.
2932
ErrUnknownScheme = errors.New("unknown scheme")
33+
34+
// ErrInvalidSource is returned when an invalid source is encountered.
35+
ErrInvalidSource = errors.New("invalid source")
3036
)
3137

3238
// -------------------------------------------------------------------------------------
@@ -43,28 +49,79 @@ func Register(scheme string, open OpenFunc) {
4349
openers[scheme] = open
4450
}
4551

46-
// Open opens a resource identified by the given URL.
52+
// Open opens a resource identified by the given URI.
4753
// It supports different schemes by utilizing registered open functions.
48-
// If the URL has no scheme, it is treated as a file path.
49-
func Open(url string) (io.ReadCloser, error) {
50-
scheme := schemeOf(url)
54+
// If the URI has no scheme, it is treated as a file path.
55+
func Open(uri string) (io.ReadCloser, error) {
56+
scheme := schemeOf(uri)
5157
if scheme == "" {
52-
return os.Open(url)
58+
return os.Open(uri)
5359
}
5460
if open, ok := openers[scheme]; ok {
55-
return open(url)
61+
return open(uri)
5662
}
57-
return nil, &fs.PathError{Op: "stream.Open", Err: ErrUnknownScheme, Path: url}
63+
return nil, &fs.PathError{Op: "stream.Open", Err: ErrUnknownScheme, Path: uri}
5864
}
5965

60-
func schemeOf(url string) (scheme string) {
61-
pos := strings.IndexAny(url, ":/")
66+
func schemeOf(uri string) (scheme string) {
67+
pos := strings.IndexAny(uri, ":/")
6268
if pos > 0 {
63-
if url[pos] == ':' {
64-
return url[:pos]
69+
if uri[pos] == ':' {
70+
return uri[:pos]
6571
}
6672
}
6773
return ""
6874
}
6975

7076
// -------------------------------------------------------------------------------------
77+
78+
// ReadSource converts src to a []byte if possible; otherwise it returns an error.
79+
// Supported types for src are:
80+
// - string (as content, NOT as filename)
81+
// - []byte (as content)
82+
// - *bytes.Buffer (as content)
83+
// - io.Reader (as content)
84+
func ReadSource(src any) ([]byte, error) {
85+
switch s := src.(type) {
86+
case string:
87+
return byteutil.Bytes(s), nil
88+
case []byte:
89+
return s, nil
90+
case *bytes.Buffer:
91+
// is io.Reader, but src is already available in []byte form
92+
if s != nil {
93+
return s.Bytes(), nil
94+
}
95+
case io.Reader:
96+
return io.ReadAll(s)
97+
}
98+
return nil, ErrInvalidSource
99+
}
100+
101+
// If src != nil, ReadSourceLocal converts src to a []byte if possible;
102+
// otherwise it returns an error. If src == nil, ReadSourceLocal returns
103+
// the result of reading the file specified by filename.
104+
func ReadSourceLocal(filename string, src any) ([]byte, error) {
105+
if src != nil {
106+
return ReadSource(src)
107+
}
108+
return os.ReadFile(filename)
109+
}
110+
111+
// ReadSourceFromURI reads the source from the given URI.
112+
// If src != nil, it reads from src; otherwise, it opens the URI and reads
113+
// from it.
114+
func ReadSourceFromURI(uri string, src any) (ret []byte, err error) {
115+
if src == nil {
116+
var f io.ReadCloser
117+
f, err = Open(uri)
118+
if err != nil {
119+
return
120+
}
121+
defer f.Close()
122+
src = f
123+
}
124+
return ReadSource(src)
125+
}
126+
127+
// -------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)