github.com/traefik/yaegi@v0.15.1/_test/issue-1460.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"net/netip"
     8  	"reflect"
     9  )
    10  
    11  func unmarshalJSON[T any](b []byte, x *[]T) error {
    12  	if *x != nil {
    13  		return errors.New("already initialized")
    14  	}
    15  	if len(b) == 0 {
    16  		return nil
    17  	}
    18  	return json.Unmarshal(b, x)
    19  }
    20  
    21  func SliceOfViews[T ViewCloner[T, V], V StructView[T]](x []T) SliceView[T, V] {
    22  	return SliceView[T, V]{x}
    23  }
    24  
    25  type StructView[T any] interface {
    26  	Valid() bool
    27  	AsStruct() T
    28  }
    29  
    30  type SliceView[T ViewCloner[T, V], V StructView[T]] struct {
    31  	ж []T
    32  }
    33  
    34  type ViewCloner[T any, V StructView[T]] interface {
    35  	View() V
    36  	Clone() T
    37  }
    38  
    39  func (v SliceView[T, V]) MarshalJSON() ([]byte, error) { return json.Marshal(v.ж) }
    40  
    41  func (v *SliceView[T, V]) UnmarshalJSON(b []byte) error { return unmarshalJSON(b, &v.ж) }
    42  
    43  type Slice[T any] struct {
    44  	ж []T
    45  }
    46  
    47  func (v Slice[T]) MarshalJSON() ([]byte, error) { return json.Marshal(v.ж) }
    48  
    49  func (v *Slice[T]) UnmarshalJSON(b []byte) error { return unmarshalJSON(b, &v.ж) }
    50  
    51  func SliceOf[T any](x []T) Slice[T] {
    52  	return Slice[T]{x}
    53  }
    54  
    55  type IPPrefixSlice struct {
    56  	ж Slice[netip.Prefix]
    57  }
    58  
    59  type viewStruct struct {
    60  	Int        int
    61  	Strings    Slice[string]
    62  	StringsPtr *Slice[string] `json:",omitempty"`
    63  }
    64  
    65  func main() {
    66  	ss := SliceOf([]string{"bar"})
    67  	in := viewStruct{
    68  		Int:        1234,
    69  		Strings:    ss,
    70  		StringsPtr: &ss,
    71  	}
    72  
    73  	var buf bytes.Buffer
    74  	encoder := json.NewEncoder(&buf)
    75  	encoder.SetIndent("", "")
    76  	err1 := encoder.Encode(&in)
    77  	b := buf.Bytes()
    78  	var got viewStruct
    79  	err2 := json.Unmarshal(b, &got)
    80  	println(err1 == nil, err2 == nil, reflect.DeepEqual(got, in))
    81  }
    82  
    83  // Output:
    84  // true true true