|
| 1 | +go-piml is a Go package that provides functionality to marshal and unmarshal data to and from the PIML format. |
| 2 | +--- |
| 3 | +# go-piml |
| 4 | + |
| 5 | +`go-piml` is a Go package that provides functionality to marshal and unmarshal data to and from the PIML (Parenthesis Intended Markup Language) format. PIML is a human-readable, indentation-based data serialization format designed for configuration files and simple data structures. |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +- **Intuitive Syntax:** Easy-to-read key-value pairs, supporting nested structures. |
| 10 | +- **Go-like Tagging:** Uses `piml:"tag"` struct tags for flexible field mapping. |
| 11 | +- **Primitive Types:** Supports strings, integers, floats, and booleans. |
| 12 | +- **Complex Types:** Handles structs, slices (arrays), and maps. |
| 13 | +- **Nil Handling:** Explicitly represents `nil` for pointers, empty slices, and empty maps. |
| 14 | +- **Multi-line Strings:** Supports multi-line string values with indentation. |
| 15 | +- **Comments:** Allows single-line and inline comments using `#`. |
| 16 | +- **Time Support:** Marshals and unmarshals `time.Time` values using RFC3339Nano format. |
| 17 | + |
| 18 | +## PIML Format Overview |
| 19 | + |
| 20 | +PIML uses a simple key-value structure. Keys are enclosed in parentheses `()` and values follow. Indentation defines nesting. |
| 21 | + |
| 22 | +```piml |
| 23 | +(site_name) PIML Demo |
| 24 | +(port) 8080 |
| 25 | +(is_production) false |
| 26 | +(version) 1.2 |
| 27 | + |
| 28 | +(database) |
| 29 | + (host) localhost |
| 30 | + (port) 5432 |
| 31 | + |
| 32 | +(admins) |
| 33 | + > (User) |
| 34 | + (id) 1 |
| 35 | + (name) Alice |
| 36 | + > (User) |
| 37 | + (id) 2 |
| 38 | + (name) Bob |
| 39 | + |
| 40 | +(features) |
| 41 | + > auth |
| 42 | + > logging |
| 43 | + > metrics |
| 44 | + |
| 45 | +(description) |
| 46 | + This is a sample product description. |
| 47 | + It spans multiple lines. |
| 48 | + |
| 49 | + With an empty line in between. |
| 50 | + |
| 51 | +(metadata) |
| 52 | +(related_ids) nil |
| 53 | +``` |
| 54 | + |
| 55 | +## Installation |
| 56 | + |
| 57 | +To use `go-piml` in your Go project, simply run: |
| 58 | + |
| 59 | +```bash |
| 60 | +go get github.com/fezcode/go-piml |
| 61 | +``` |
| 62 | + |
| 63 | +## Usage |
| 64 | + |
| 65 | +### Marshalling Go Structs to PIML |
| 66 | + |
| 67 | +Define your Go struct with `piml` tags: |
| 68 | + |
| 69 | +```go |
| 70 | +package main |
| 71 | + |
| 72 | +import ( |
| 73 | + "fmt" |
| 74 | + time "time" |
| 75 | + "github.com/fezcode/go-piml" |
| 76 | +) |
| 77 | + |
| 78 | +type User struct { |
| 79 | + ID int `piml:"id"` |
| 80 | + Name string `piml:"name"` |
| 81 | +} |
| 82 | + |
| 83 | +type Config struct { |
| 84 | + SiteName string `piml:"site_name"` |
| 85 | + Port int `piml:"port"` |
| 86 | + IsProduction bool `piml:"is_production"` |
| 87 | + Admins []*User `piml:"admins"` |
| 88 | + LastUpdated time.Time `piml:"last_updated"` |
| 89 | + Description string `piml:"description"` |
| 90 | +} |
| 91 | + |
| 92 | +func main() { |
| 93 | + cfg := Config{ |
| 94 | + SiteName: "My Awesome Site", |
| 95 | + Port: 8080, |
| 96 | + IsProduction: true, |
| 97 | + Admins: []*User{ |
| 98 | + {ID: 1, Name: "Admin One"}, |
| 99 | + {ID: 2, Name: "Admin Two"}, |
| 100 | + }, |
| 101 | + LastUpdated: time.Date(2023, time.November, 10, 15, 30, 0, 0, time.UTC), |
| 102 | + Description: "This is a multi-line\ndescription for the site.", |
| 103 | + } |
| 104 | + |
| 105 | + pimlData, err := piml.Marshal(cfg) |
| 106 | + if err != nil { |
| 107 | + fmt.Println("Error marshalling:", err) |
| 108 | + return |
| 109 | + } |
| 110 | + fmt.Println(string(pimlData)) |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +Output: |
| 115 | + |
| 116 | +```piml |
| 117 | +(site_name) My Awesome Site |
| 118 | +(port) 8080 |
| 119 | +(is_production) true |
| 120 | +(admins) |
| 121 | + > (User) |
| 122 | + (id) 1 |
| 123 | + (name) Admin One |
| 124 | + > (User) |
| 125 | + (id) 2 |
| 126 | + (name) Admin Two |
| 127 | +(last_updated) 2023-11-10T15:30:00Z |
| 128 | +(description) |
| 129 | + This is a multi-line |
| 130 | + description for the site. |
| 131 | +``` |
| 132 | + |
| 133 | +### Unmarshalling PIML to Go Structs |
| 134 | + |
| 135 | +```go |
| 136 | +package main |
| 137 | + |
| 138 | +import ( |
| 139 | + "fmt" |
| 140 | + time "time" |
| 141 | + "github.com/fezcode/go-piml" |
| 142 | +) |
| 143 | + |
| 144 | +type User struct { |
| 145 | + ID int `piml:"id"` |
| 146 | + Name string `piml:"name"` |
| 147 | +} |
| 148 | + |
| 149 | +type Config struct { |
| 150 | + SiteName string `piml:"site_name"` |
| 151 | + Port int `piml:"port"` |
| 152 | + IsProduction bool `piml:"is_production"` |
| 153 | + Admins []*User `piml:"admins"` |
| 154 | + LastUpdated time.Time `piml:"last_updated"` |
| 155 | + Description string `piml:"description"` |
| 156 | +} |
| 157 | + |
| 158 | +func main() { |
| 159 | + pimlData := []byte(` |
| 160 | +(site_name) My Awesome Site |
| 161 | +(port) 8080 |
| 162 | +(is_production) true |
| 163 | +(admins) |
| 164 | + > (User) |
| 165 | + (id) 1 |
| 166 | + (name) Admin One |
| 167 | + > (User) |
| 168 | + (id) 2 |
| 169 | + (name) Admin Two |
| 170 | +(last_updated) 2023-11-10T15:30:00Z |
| 171 | +(description) |
| 172 | + This is a multi-line |
| 173 | + description for the site. |
| 174 | +`) |
| 175 | + |
| 176 | + var cfg Config |
| 177 | + err := piml.Unmarshal(pimlData, &cfg) |
| 178 | + if err != nil { |
| 179 | + fmt.Println("Error unmarshalling:", err) |
| 180 | + return |
| 181 | + } |
| 182 | + |
| 183 | + fmt.Printf("%+v\n", cfg) |
| 184 | + for _, admin := range cfg.Admins { |
| 185 | + fmt.Printf("Admin: ID=%d, Name=%s\n", admin.ID, admin.Name) |
| 186 | + } |
| 187 | +} |
| 188 | +``` |
| 189 | + |
| 190 | +Output: |
| 191 | + |
| 192 | +``` |
| 193 | +{SiteName:My Awesome Site Port:8080 IsProduction:true Admins:[0xc0000a4000 0xc0000a4020] LastUpdated:2023-11-10 15:30:00 +0000 UTC Description:This is a multi-line |
| 194 | +description for the site.} |
| 195 | +Admin: ID=1, Name:Admin One |
| 196 | +Admin: ID:2, Name:Admin Two |
| 197 | +``` |
| 198 | + |
| 199 | +## Contributing |
| 200 | + |
| 201 | +Contributions are welcome! Please open an issue or submit a pull request. |
| 202 | + |
| 203 | +## License |
| 204 | + |
| 205 | +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. |
0 commit comments