diff --git a/x/cm_idiomatic/README.md b/x/cm_idiomatic/README.md new file mode 100644 index 00000000..5fc18396 --- /dev/null +++ b/x/cm_idiomatic/README.md @@ -0,0 +1,68 @@ +# cm_idiomatic + +Idiomatic Go conversions for WebAssembly Component Model types. + +## Overview + +This library provides simple functions to convert between Go types and Component Model types: + +- **Option** ↔ **Pointer**: Convert between `cm.Option[T]` and `*T` +- **List** ↔ **Slice**: Convert between `cm.List[T]` and `[]T` +- **Map** ↔ **Tuples**: Convert between Go maps and Component Model tuple lists +- **Result** ↔ **Error**: Convert between `cm.Result[T, T, E]` and Go's `(T, error)` pattern + +### Option + +```go +// Go pointer to Component Model Option +value := 42 +opt := cm_idiomatic.FromPtr(&value) // cm.Option[int] + +// Component Model Option to Go pointer +ptr := cm_idiomatic.ToPtr(opt) // *int +``` + +### List + +```go +// Go slice to Component Model List +slice := []string{"hello", "world"} +list := cm_idiomatic.FromSlice(slice) // cm.List[string] + +// Component Model List to Go slice +result := cm_idiomatic.ToSlice(list) // []string +``` + +### Map + +```go +// Go map to Component Model tuple list +m := map[string]int{"foo": 1, "bar": 2} +tuples := cm_idiomatic.FromMap(m) // cm.List[cm.Tuple[string, int]] + +// Component Model tuple list to Go map +result := cm_idiomatic.ToMap(tuples) // map[string]int +``` + +### Result + +```go +// Go (value, error) to Component Model Result +result := cm_idiomatic.FromError[string, error]("success", nil) +// Returns cm.Result[string, string, error] + +// Component Model Result to Go (value, error) +value, err := cm_idiomatic.ToError(result) // (string, error) +``` + +## Installation + +```bash +go get go.wasmcloud.dev/x/cm_idiomatic +``` + +## Usage + +```go +import "go.wasmcloud.dev/x/cm_idiomatic" +``` diff --git a/x/cm_idiomatic/cm_idiomatic.go b/x/cm_idiomatic/cm_idiomatic.go new file mode 100644 index 00000000..1b00979b --- /dev/null +++ b/x/cm_idiomatic/cm_idiomatic.go @@ -0,0 +1,63 @@ +package cm_idiomatic + +import ( + "go.bytecodealliance.org/cm" +) + +// ToPtr converts a Component Model Option to a Go pointer. +// Returns nil if the Option is None, otherwise returns a pointer to the value. +func ToPtr[T any](opt cm.Option[T]) *T { + return opt.Some() +} + +// FromPtr converts a Go pointer to a Component Model Option. +// Returns None if the pointer is nil, otherwise returns Some with the dereferenced value. +func FromPtr[T any](ptr *T) cm.Option[T] { + if ptr == nil { + return cm.None[T]() + } + return cm.Some(*ptr) +} + +// ToSlice converts a Component Model List to a Go slice. +func ToSlice[T any](list cm.List[T]) []T { + return list.Slice() +} + +// FromSlice converts a Go slice to a Component Model List. +func FromSlice[T any](slice []T) cm.List[T] { + return cm.ToList(slice) +} + +// ToMap converts a Component Model List of tuples to a Go map. +func ToMap[K comparable, V any](list cm.List[cm.Tuple[K, V]]) map[K]V { + slice := ToSlice(list) + m := make(map[K]V, len(slice)) + + for i := 0; i < len(slice); i++ { + tuple := slice[i] + m[tuple.F0] = tuple.F1 + } + + return m +} + +// FromMap converts a Go map to a Component Model List of tuples. +func FromMap[K comparable, V any](m map[K]V) cm.List[cm.Tuple[K, V]] { + tuples := make([]cm.Tuple[K, V], 0, len(m)) + for k, v := range m { + tuples = append(tuples, cm.Tuple[K, V]{F0: k, F1: v}) + } + return FromSlice(tuples) +} + +// FromResult converts Go's (value, error) pattern to a Component Model Result. +// Returns OK(value) if error is nil, otherwise returns Err(error). +func FromResult[R cm.AnyResult[Shape, T, E], Shape, T, E any](value T, err E) R { + var zero E + // Check if err is the zero value (e.g., nil for error interface) + if any(err) == any(zero) { + return cm.OK[R](value) + } + return cm.Err[R](err) +} diff --git a/x/cm_idiomatic/go.mod b/x/cm_idiomatic/go.mod new file mode 100644 index 00000000..f420e502 --- /dev/null +++ b/x/cm_idiomatic/go.mod @@ -0,0 +1,5 @@ +module go.wasmcloud.dev/x/cm_idiomatic + +go 1.24 + +require go.bytecodealliance.org/cm v0.3.0 diff --git a/x/cm_idiomatic/go.sum b/x/cm_idiomatic/go.sum new file mode 100644 index 00000000..cf6e1ee0 --- /dev/null +++ b/x/cm_idiomatic/go.sum @@ -0,0 +1,2 @@ +go.bytecodealliance.org/cm v0.3.0 h1:VhV+4vjZPUGCozCg9+up+FNL3YU6XR+XKghk7kQ0vFc= +go.bytecodealliance.org/cm v0.3.0/go.mod h1:JD5vtVNZv7sBoQQkvBvAAVKJPhR/bqBH7yYXTItMfZI=