A super-simple, very fast data file format!
bench | ||
tests | ||
.gitignore | ||
config.go | ||
go.mod | ||
go.sum | ||
LICENSE.md | ||
pool.go | ||
README.md | ||
scanner.go | ||
token.go |
Fin
Fin is a very light, very intuitive config file format! Few symbols, few rules, quite flexible. Has support for comments, arrays, maps, and type guarantees.
Mercilessly benchmarked, fully tested. Fin competes toe-to-toe with Go's native JSON library, and handily outperforms the reference TOML and YAML implementations.
Format
Fin has very very simple syntax.
-- Lua style comments!
host "localhost"
port 8080 -- no = for assignment!
debug true
allowed_ips {
"192.168.1.1"
"192.168.1.2"
"10.0.0.1"
}
--[[
Feel free to space out your explanations!
All is well and good.
]]
database {
host "db.example.com"
port 5432
credentials {
username "admin"
password "secure123"
}
}
Installation
go get git.sharkk.net/Sharkk/Fin
Usage
Basic Usage
package main
import (
"fmt"
"os"
"git.sharkk.net/Sharkk/Fin"
)
func main() {
file, err := os.Open("config.conf")
if err != nil {
panic(err)
}
defer file.Close()
// Pass a string to be loaded by the parser!
cfg, err := fin.Load(file)
if err != nil {
panic(err)
}
// Access values with type conversion.
host, err := cfg.GetString("database.host")
port, err := cfg.GetInt("database.port")
debug, err := cfg.GetBool("debug")
// Use default values for missing keys
timeout := cfg.GetOr("timeout", 30).(int)
// Get the entire map to traverse directly (cuts traversal time by 50%!)
entireMap := cfg.GetData()
other, err := entireMap["database"]["host"].(string)
}
Type Conversion
The parser automatically converts values to appropriate types:
boolValue, err := cfg.GetBool("feature.enabled")
intValue, err := cfg.GetInt("server.port")
floatValue, err := cfg.GetFloat("threshold")
stringValue, err := cfg.GetString("app.name")
arrayValue, err := cfg.GetArray("allowed_ips")
mapValue, err := cfg.GetMap("database")
// Generic getter (returns any)
value, err := cfg.Get("some.key")
Accessing Arrays and Maps
Access array elements and nested map values using dot notation:
// Access the first element in the array
firstIP, err := cfg.GetString("allowed_ips.0")
// Access deeply nested values
username, err := cfg.GetString("database.credentials.username")
Performance
Fin goes blow-for-blow against Go's standard JSON library, and performs incredibly versus the standard TOML and YAML implementations:
Benchmark | Operations | Time (ns/op) | Memory (B/op) | Allocations (allocs/op) |
---|---|---|---|---|
Small Config Files | ||||
Fin | 1,000,000 | 1,052 | 1,743 | 15 |
JSON | 1,000,000 | 1,112 | 1,384 | 23 |
YAML | 215,121 | 5,600 | 8,888 | 82 |
TOML | 286,334 | 4,483 | 4,520 | 67 |
Medium Config Files | ||||
Fin | 211,863 | 5,696 | 4,056 | 74 |
JSON | 261,925 | 4,602 | 5,344 | 89 |
YAML | 50,010 | 23,965 | 21,577 | 347 |
TOML | 68,420 | 17,639 | 16,348 | 208 |
Large Config Files | ||||
Fin | 55,338 | 21,556 | 12,208 | 207 |
JSON | 70,219 | 17,202 | 18,140 | 297 |
YAML | 12,536 | 95,945 | 65,568 | 1,208 |
TOML | 14,732 | 74,198 | 66,050 | 669 |
AMD Ryzen 9 7950X
Why Choose Fin?
- Readability: Simple syntax that's easy for humans to read and write
- Flexibility: Supports various data types and nested structures
- Performance: Fast parsing with minimal overhead
- Type Safety: Strong typing with automatic conversion
- Simplicity: No external dependencies required
License
(Sharkk Minimal License)[LICENSE]