Skip to content

Instantly share code, notes, and snippets.

@klauspost
Last active December 20, 2025 13:20
Show Gist options
  • Select an option

  • Save klauspost/d483413676135e8d15a8d37af1157a70 to your computer and use it in GitHub Desktop.

Select an option

Save klauspost/d483413676135e8d15a8d37af1157a70 to your computer and use it in GitHub Desktop.
Luke Nerdsnipe
package example
import (
"errors"
"os"
"lite3"
)
type MyLocal struct {
Name string `lite3:"name"`
Number int `lite3:"number"`
Sub MyOtherLocal `lite3:"sub"`
Unparsed *lite3.Object `lite3:"unparsed"`
}
type MyOtherLocal struct{}
func main() {
// Parse blob as object.
obj, _ := lite3.ParseObject([]byte{})
// Map to local type.
var myType MyLocal
_ = obj.Unmarshal(&myType)
// Change values.
myType.Name = "foo"
myType.Number = 123
// marshal back to object, keeping unmapped fields.
_ = obj.Update(&myType)
// Save data..
_ = os.WriteFile("myfile", obj.Data(), 0644)
}
// generated methods...
func (m *MyLocal) UnmarshalLite3(obj *lite3.Object) error {
for key, value := range obj.Iter() {
var ok bool
switch key {
case "name":
m.Name, ok = value.(string)
if !ok {
return errors.New("name: unexpected type")
}
case "number":
m.Number, ok = value.(int)
if !ok {
return errors.New("number: unexpected type")
}
case "sub":
var dst MyOtherLocal
err := dst.UnmarshalLite3(value.(*lite3.Object))
if err != nil {
return err
}
m.Sub = dst
}
}
return nil
}
func (m *MyLocal) MarshalLite3(obj *lite3.Object) error {
obj.Set("name", m.Name)
obj.Set("number", m.Number)
obj.Set("sub", &m.Sub)
return nil
}
func (m MyOtherLocal) UnmarshalLite3(_ *lite3.Object) error { return nil }
func (m *MyOtherLocal) MarshalLite3(obj *lite3.Object) error { return nil }
package lite3
import "iter"
// reference to an object in serialized data.
type Object struct {
}
// ParseObject parses the object from the serialized data.
func ParseObject([]byte) (*Object, error) {
return nil, nil
}
// Iter returns an iterator over the keys and values in the Object.
// Using any for illustration.
func (o *Object) Iter() iter.Seq2[string, any] {
return nil
}
// Set updates the value for the given key.
func (o *Object) Set(key string, value any) {
// Detecting unchanged should be trivial
}
// Data returns the serialized data.
func (o *Object) Data() []byte {
return nil
}
// Unmarshaler will map the Object to the type.
type Unmarshaler interface {
UnmarshalLite3(o *Object) error
}
// Marshaler will map the fields on the object.
type Marshaler interface {
MarshalLite3(o *Object) error
}
// Unmarshal will map the Object to the type.
func (o *Object) Unmarshal(dst Unmarshaler) error {
return dst.UnmarshalLite3(o)
}
// Update will map the input object on to the object, replacing overlapping keys.
func (o *Object) Update(src Marshaler) error {
return src.MarshalLite3(o)
}
// Replace will map the input object on to the object.
func (o *Object) Replace(src Marshaler) error {
*o = Object{} //ofc can be more clever.
return src.MarshalLite3(o)
}
@klauspost
Copy link
Author

Ignore that I'm using any. It would probably be SetString(key, value string) etc - and maybe just GetString(key) (string, error) or something like that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment