package cnf import ( "errors" "fmt" "os" "path/filepath" ) // ErrUnknownExtension is raised when encountering an unknown extension var ErrUnknownExtension = errors.New("unknown extension format") // ErrUnknownFormat is raised when the format cannot be guessed from the content of the file var ErrUnknownFormat = errors.New("cannot infer format from content") // Load the current file and create the configuration format accordingly func Load(path string) (ConfigurationFormat, error) { var confFormat ConfigurationFormat // 1. check file if _, err := os.Stat(path); os.IsNotExist(err) { return nil, fmt.Errorf("cannot find file '%s'", path) } // 2. Try to load from extension extension := filepath.Ext(path) if len(extension) > 0 { confFormat = loadFromExtension(extension) if confFormat == nil { return nil, ErrUnknownExtension } // open file file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() // parse _, err = confFormat.ReadFrom(file) if err == nil { return confFormat, nil } // return nil, fmt.Errorf("cannot parse file as '%s' | %s", extension, err) } // 4. Try to guess from the content confFormat, err := loadFromContent(path) if err != nil { return nil, err } if confFormat == nil { return nil, ErrUnknownFormat } return confFormat, nil } func loadFromExtension(ext string) ConfigurationFormat { // select configuration or fail if not known switch ext { case ".json": return new(json) case ".ini", ".conf": return new(ini) case ".yaml": return new(yaml) case ".nginx": return new(nginx) default: return nil } } func loadFromContent(path string) (ConfigurationFormat, error) { // 3. open file file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() // extensions ordered by strictness of the language's syntax extensions := []string{".json", ".nginx", ".yaml", ".ini"} // try to load each available extension for _, ext := range extensions { file.Seek(0, 0) // load parser c := loadFromExtension(ext) if c == nil { continue } // parse _, err := c.ReadFrom(file) if err == nil { return c, nil } } return nil, ErrUnknownFormat }