data_source.go raw

   1  // Copyright 2019 Unknwon
   2  //
   3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
   4  // not use this file except in compliance with the License. You may obtain
   5  // a copy of the License at
   6  //
   7  //     http://www.apache.org/licenses/LICENSE-2.0
   8  //
   9  // Unless required by applicable law or agreed to in writing, software
  10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12  // License for the specific language governing permissions and limitations
  13  // under the License.
  14  
  15  package ini
  16  
  17  import (
  18  	"bytes"
  19  	"fmt"
  20  	"io"
  21  	"io/ioutil"
  22  	"os"
  23  )
  24  
  25  var (
  26  	_ dataSource = (*sourceFile)(nil)
  27  	_ dataSource = (*sourceData)(nil)
  28  	_ dataSource = (*sourceReadCloser)(nil)
  29  )
  30  
  31  // dataSource is an interface that returns object which can be read and closed.
  32  type dataSource interface {
  33  	ReadCloser() (io.ReadCloser, error)
  34  }
  35  
  36  // sourceFile represents an object that contains content on the local file system.
  37  type sourceFile struct {
  38  	name string
  39  }
  40  
  41  func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
  42  	return os.Open(s.name)
  43  }
  44  
  45  // sourceData represents an object that contains content in memory.
  46  type sourceData struct {
  47  	data []byte
  48  }
  49  
  50  func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
  51  	return ioutil.NopCloser(bytes.NewReader(s.data)), nil
  52  }
  53  
  54  // sourceReadCloser represents an input stream with Close method.
  55  type sourceReadCloser struct {
  56  	reader io.ReadCloser
  57  }
  58  
  59  func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) {
  60  	return s.reader, nil
  61  }
  62  
  63  func parseDataSource(source interface{}) (dataSource, error) {
  64  	switch s := source.(type) {
  65  	case string:
  66  		return sourceFile{s}, nil
  67  	case []byte:
  68  		return &sourceData{s}, nil
  69  	case io.ReadCloser:
  70  		return &sourceReadCloser{s}, nil
  71  	case io.Reader:
  72  		return &sourceReadCloser{ioutil.NopCloser(s)}, nil
  73  	default:
  74  		return nil, fmt.Errorf("error parsing data source: unknown type %q", s)
  75  	}
  76  }
  77