package registry import ( "fmt" "git.maximhutz.com/max/lambda/pkg/codec" ) // A Conversion is a type-erased transformation from one representation to // another. It operates on Expr values, hiding the underlying representation // types. type Conversion interface { // InType returns the name of the source representation. InType() string // OutType returns the name of the target representation. OutType() string // Run applies the conversion to the given expression. Returns an error if // the expression's data does not match the expected source type. Run(Expr) (Expr, error) } // A registeredConversion adapts a typed codec.Conversion[T, U] into the // type-erased Conversion interface. It extracts the underlying T from an Expr, // applies the conversion, and wraps the result as a new Expr. type registeredConversion[T, U any] struct { conversion codec.Conversion[T, U] inType, outType string } func (c registeredConversion[T, U]) Run(expr Expr) (Expr, error) { t, ok := expr.Data().(T) if !ok { return nil, fmt.Errorf("could not parse '%v' as '%s'", t, c.inType) } u, err := c.conversion(t) if err != nil { return nil, err } return NewExpr(c.outType, u), nil } func (c registeredConversion[T, U]) InType() string { return c.inType } func (c registeredConversion[T, U]) OutType() string { return c.outType } // RegisterConversion registers a typed conversion function between two // representations. func RegisterConversion[T, U any]( registry *Registry, conversion codec.Conversion[T, U], inType, outType string, ) error { registry.converter.Add(registeredConversion[T, U]{conversion, inType, outType}) return nil }