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 }