1717package stream
1818
1919import (
20+ "bytes"
2021 "errors"
2122 "io"
2223 "io/fs"
2324 "os"
2425 "strings"
26+
27+ "github.com/qiniu/x/byteutil"
2528)
2629
2730var (
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,78 @@ 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 ) ([]byte , error ) {
115+ if src == nil {
116+ f , err := Open (uri )
117+ if err != nil {
118+ return nil , err
119+ }
120+ defer f .Close ()
121+ src = f
122+ }
123+ return ReadSource (src )
124+ }
125+
126+ // -------------------------------------------------------------------------------------
0 commit comments