zntg/io.go

188 lines
4.6 KiB
Go

package zntg
import (
"encoding/json"
"image"
_ "image/gif" // decoding of GIF
_ "image/jpeg" // decoding of JPEG
"image/png"
"io"
"io/ioutil"
"os"
"path/filepath"
)
// CreateJSONDecoder create a new a generic JSON decoder for the specified value.
func CreateJSONDecoder(value interface{}) DecoderFn {
return func(r io.Reader) (interface{}, error) {
decoder := json.NewDecoder(r)
return value, decoder.Decode(value)
}
}
// DecoderFn describes a generic decoder.
type DecoderFn func(io.Reader) (interface{}, error)
// DecodeFile is a generic decode method to decode content from disk.
func DecodeFile(path string, decoder func(io.Reader) (interface{}, error)) (interface{}, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
return decoder(f)
}
// DecodeImage tries to decode a file to an image.
func DecodeImage(path string) (image.Image, error) {
value, err := DecodeFile(path, ImageDecoder)
if err != nil {
return nil, err
}
return value.(image.Image), nil
}
// DecodeJSON tries to decode a file to specifed value.
func DecodeJSON(path string, value interface{}) error {
_, err := DecodeFile(path, CreateJSONDecoder(value))
return err
}
// Dir is a convenience struct for representing a path to a directory.
type Dir struct {
Path string
}
// FilePath returns the path of a file with the specified name in the directory.
func (d *Dir) FilePath(name string) string {
return filepath.Join(d.Path, name)
}
// Write writes the content of the reader into a file with the specified name.
func (d *Dir) Write(name string, r io.Reader) error {
path := d.FilePath(name)
dir := filepath.Dir(path)
os.MkdirAll(dir, 0777)
return EncodeFile(path, r, CopyReader)
}
// Destroy removes the directory.
func (d *Dir) Destroy() error {
return os.RemoveAll(d.Path)
}
// EncoderFn describes a generic encoder.
type EncoderFn func(io.Writer, interface{}) error
// EncodeFile is a generic encode method to encode content to disk.
func EncodeFile(path string, value interface{}, encoder EncoderFn) error {
dst, err := os.Create(path)
if err != nil {
return err
}
defer dst.Close()
return encoder(dst, value)
}
// EncodeJSON encodes a JSON struct to a file.
func EncodeJSON(path string, value interface{}) error {
return EncodeFile(path, value, JSONEncoder)
}
// EncodePNG encodes an image to a file.
func EncodePNG(path string, im image.Image) error {
return EncodeFile(path, im, PNGEncoder)
}
// FileExists returns if file exists on specified path.
func FileExists(path string) bool {
if _, err := os.Stat(path); os.IsNotExist(err) {
return false
}
return true
}
var _ DecoderFn = ImageDecoder
// ImageDecoder is a generic image decoder.
func ImageDecoder(r io.Reader) (interface{}, error) {
im, _, err := image.Decode(r)
return im, err
}
var _ EncoderFn = JSONEncoder
// JSONEncoder is a generic JSON encoder.
func JSONEncoder(w io.Writer, value interface{}) error {
encoder := json.NewEncoder(w)
return encoder.Encode(value)
}
var _ EncoderFn = PNGEncoder
// PNGEncoder is a generic PNG encoder.
func PNGEncoder(w io.Writer, value interface{}) error { return png.Encode(w, value.(image.Image)) }
// NewTempDir creates a temporary directory.
func NewTempDir(prefix string) (*Dir, error) {
path, err := ioutil.TempDir("", prefix)
if nil != err {
return nil, err
}
return &Dir{path}, nil
}
// UserCacheDir gives back the user configuration directory with given name.
func UserCacheDir(name string) (string, error) {
config, err := os.UserCacheDir()
if err != nil {
return "", err
}
dir := filepath.Join(config, name)
err = os.MkdirAll(dir, 0777)
if err != nil {
return "", err
}
return dir, nil
}
// UserCacheFile gives back the path to the file with the specified name and the directory named app.
func UserCacheFile(app, name string) (string, error) {
dir, err := UserCacheDir(app)
if err != nil {
return "", err
}
return filepath.Join(dir, name), nil
}
// UserConfigDir gives back the user configuration directory with given name.
func UserConfigDir(name string) (string, error) {
config, err := os.UserConfigDir()
if err != nil {
return "", err
}
dir := filepath.Join(config, name)
err = os.MkdirAll(dir, 0777)
if err != nil {
return "", err
}
return dir, nil
}
// UserConfigFile gives back the path to the file with the specified name and the directory named app.
func UserConfigFile(app, name string) (string, error) {
dir, err := UserConfigDir(app)
if err != nil {
return "", err
}
return filepath.Join(dir, name), nil
}
var _ EncoderFn = CopyReader
// CopyReader copies the provided value to the output.
func CopyReader(w io.Writer, value interface{}) error {
_, err := io.Copy(w, value.(io.Reader))
return err
}