yaml

//  - zeros.go - 
// This is an example of handling default values (zero values) with yaml

package main

import (
	"fmt"
	"sort"
	"strings"

	"github.com/davecgh/go-spew/spew"
	"gopkg.in/yaml.v2"
)

type count uint64

func (c *count) IsZero() bool {
	return c == nil
}

func main() {
	tests := map[string]string{
		"with zero": "  count: 0",
		"with none": "  some: none",
		"with nums": "  count: 1",
	}

	var keys []string
	for k, _ := range tests {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, key := range keys {
		var (
			lines_of_yaml = []string{
				"main:",
				tests[key],
				`  found: string`,
			}

			in  = []byte(strings.Join(lines_of_yaml, "\n"))
			out struct {
				Main struct {
					Num *count `yaml:"count,omitempty"`
					// Test int    `yaml:"testnum,omitempty"`
				} `yaml:"main"`
			}
		)

		fmt.Println(strings.Repeat("\n", 2))
		fmt.Println(strings.Repeat("*", 4) + " " + key + " " + strings.Repeat("*", 65))

		// with 0 -> we have 0
		fmt.Println("In....")
		fmt.Println(strings.Repeat("=", 80))
		if err := yaml.Unmarshal(in, &out); err == nil {
			spew.Dump(out)
			// spew.Println(out)
		} else {
			fmt.Printf("error: %v\n", err)
		}

		fmt.Println("Out....")
		fmt.Println(strings.Repeat("=", 80))

		// out.Main.Test = 10
		if b, err := yaml.Marshal(out); err == nil {
			fmt.Println(string(b))
		}

		fmt.Println(strings.Repeat("\n", 2))
	}
}
//  - unmarshaling.go - 
package main

import (
	"errors"
	"fmt"
	"log"

	"gopkg.in/yaml.v2"
)

type VariableType int

const (
	IsString VariableType = iota
	IsInt
	IsIntSlice
)

type Variable struct {
	Type  VariableType
	Value interface{}
}

func (v *Variable) UnmarshalYAML(unmarshal func(interface{}) error) error {
	errCantValidate := errors.New("can't unmarshal value")

	type plainUint uint
	number := new(uint)
	if err := unmarshal((*plainUint)(number)); err == nil {

		v.Type = IsInt
		v.Value = *number
		return nil
	}

	type plainString string
	str := new(string)
	if err := unmarshal((*plainString)(str)); err == nil {

		v.Type = IsString
		v.Value = *str
		return nil
	}

	type plainIntSlice []int
	var intSlice []int
	if err := unmarshal((*plainIntSlice)(&intSlice)); err == nil {

		v.Type = IsIntSlice
		v.Value = intSlice
		return nil
	}

	return errCantValidate
}

func main() {
	yamls := []string{
		`variable: 1`,
		`variable: boo`,
		`variable: [1,2]`,
	}

	for _, body := range yamls {

		var v struct {
			Data Variable `yaml:"variable"`
		}

		if err := yaml.Unmarshal([]byte(body), &v); err != nil {
			log.Printf("error: %w\n", err)
		} else {
			fmt.Printf("yaml -  %s\n", body)
			fmt.Printf("var  -  %#v\n", v)
		}

		fmt.Println()
	}
}