poly

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2023 License: MIT Imports: 3 Imported by: 0

README

Go Reference

Poly

Simple polymorphic serialization and deserialization.

type Speaker interface{ Speak() }

type Dog struct { IsDog bool }
func (Dog) Speak() {}

type Cat struct { IsCat bool }
func (Cat) Speak() {}

var animal poly.Poly[Speaker, poly.TypeList[Dog, poly.TypeList[Cat, poly.Nil]]]

// write a dog to json
animal.Value = Dog{}
bytes, _ := json.Marshal(animal)

// deserialize the dog
_ = json.Unmarshal(bytes, &animal)
animal.Value.Speak() // wuff

Documentation

Overview

Package poly provides polymorphic serialization and deserialization to and from json for go values. It archives this by serializing a value that is wrapped in a Poly container together with the values type name, for example:

{"type": "mypackage.Dog", "value": {"name": "Wuffy", "barks": true}}

A little bit of work is required for golang to access the possible types for deserialization into an interface. This library provides the TypeList interface together with the generic TypeItem and Nil types, to build up a variable length list of possible deserialization types during compile time.

Given struct Cat and Dog, both of interface type Animal, a Poly type can be constructed:

type MyState struct {
	Animal poly.Poly[Animal, TypeItem[Dog, TypeItem[Cat, Nil]]]
}

Setting the Poly.Value field to a Dog or Cat instance will serialize the value and deserialize the example above back into a Cat or Dog value in the Poly.Value field.

A full example:

type Speaker interface{ Speak() }

type Dog struct { IsDog bool }
func (Dog) Speak() {}

type Cat struct { IsCat bool }
func (Cat) Speak() {}

var animal poly.Poly[Speaker, poly.TypeList[Dog, poly.TypeList[Cat, poly.Nil]]]

// write a dog to json
animal.Value = Dog{}
bytes, _ := json.Marshal(animal)

// deserialize the dog
_ = json.Unmarshal(bytes, &animal)
animal.Value.Speak() // wuff

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Nil

type Nil struct{}

Nil is a TypeList of length zero.

func (Nil) Types

func (n Nil) Types() []Type

type Poly

type Poly[I any, Tl TypeList] struct {
	Value I
}

Poly is a transparent wrapper around a generic value of type I that uses a TypeList to serialize and deserialize different subtypes of I. I should be an interface. If Value is nil, the container serializes to json 'null'.

func (*Poly[I, Tl]) MarshalJSON

func (c *Poly[I, Tl]) MarshalJSON() ([]byte, error)

func (*Poly[I, Tl]) UnmarshalJSON

func (c *Poly[I, Tl]) UnmarshalJSON(bytes []byte) error

type Type

type Type struct {
	Name        string
	RuntimeType reflect.Type
}

Type combines a runtime type with a name. This is used to map the the type field on a serialized Poly instance to a Type

type TypeItem

type TypeItem[T any, Next TypeList] struct{}

TypeItem is a compile time generic TypeList item. It contains the first type of a TypeList as well as the remaining types (Next). See https://en.wikipedia.org/wiki/Cons for this kind of recursive list definition.

func (TypeItem[T, Next]) Types

func (c TypeItem[T, Next]) Types() []Type

type TypeList

type TypeList interface {
	// Types returns the bijective type mappings
	Types() []Type
}

TypeList provides a list of runtime types.

Implementations of this interface must work directly on an uninitialized type if they are supposed to be used with Poly. For example:

var myTypeList TypeList = MyCustomTypeList{}
myTypeList.Types() // must work

The type mapping must be bijective - there must be a one to one mapping between Type.Name and Type.RuntimeType

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL