// Code generated by bebopc-go; DO NOT EDIT.

package generated

import (
	"github.com/200sc/bebop"
	"github.com/200sc/bebop/iohelp"
	"io"
)

type instrument uint32

const (
	instrument_Sax instrument = 0
	instrument_Trumpet instrument = 1
	instrument_Clarinet instrument = 2
)

var _ bebop.Record = &musician{}

type musician struct {
	name string
	plays instrument
}

func (bbp musician) MarshalBebopTo(buf []byte) int {
	at := 0
	iohelp.WriteUint32Bytes(buf[at:], uint32(len(bbp.name)))
	copy(buf[at+4:at+4+len(bbp.name)], []byte(bbp.name))
	at += 4 + len(bbp.name)
	iohelp.WriteUint32Bytes(buf[at:], uint32(bbp.plays))
	at += 4
	return at
}

func (bbp *musician) UnmarshalBebop(buf []byte) (err error) {
	at := 0
	bbp.name, err = iohelp.ReadStringBytes(buf[at:])
	if err != nil {
		return err
	}
	at += 4 + len(bbp.name)
	bbp.plays = instrument(iohelp.ReadUint32Bytes(buf[at:]))
	at += 4
	return nil
}

func (bbp *musician) MustUnmarshalBebop(buf []byte) {
	at := 0
	bbp.name = iohelp.MustReadStringBytes(buf[at:])
	at += 4 + len(bbp.name)
	bbp.plays = instrument(iohelp.ReadUint32Bytes(buf[at:]))
	at += 4
}

func (bbp musician) EncodeBebop(iow io.Writer) (err error) {
	w := iohelp.NewErrorWriter(iow)
	iohelp.WriteUint32(w, uint32(len(bbp.name)))
	w.Write([]byte(bbp.name))
	iohelp.WriteUint32(w, uint32(bbp.plays))
	return w.Err
}

func (bbp *musician) DecodeBebop(ior io.Reader) (err error) {
	r := iohelp.NewErrorReader(ior)
	bbp.name = iohelp.ReadString(r)
	bbp.plays = instrument(iohelp.ReadUint32(r))
	return r.Err
}

func (bbp musician) Size() int {
	bodyLen := 0
	bodyLen += 4 + len(bbp.name)
	bodyLen += 4
	return bodyLen
}

func (bbp musician) MarshalBebop() []byte {
	buf := make([]byte, bbp.Size())
	bbp.MarshalBebopTo(buf)
	return buf
}

func makemusician(r *iohelp.ErrorReader) (musician, error) {
	v := musician{}
	err := v.DecodeBebop(r)
	return v, err
}

func makemusicianFromBytes(buf []byte) (musician, error) {
	v := musician{}
	err := v.UnmarshalBebop(buf)
	return v, err
}

func mustMakemusicianFromBytes(buf []byte) musician {
	v := musician{}
	v.MustUnmarshalBebop(buf)
	return v
}

func (bbp musician) Getname() string {
	return bbp.name
}

func (bbp musician) Getplays() instrument {
	return bbp.plays
}

func newmusician(
		name string,
		plays instrument,
) musician {
	return musician{
		name: name,
		plays: plays,
	}
}

var _ bebop.Record = &library{}

type library struct {
	songs map[[16]byte]song
}

func (bbp library) MarshalBebopTo(buf []byte) int {
	at := 0
	iohelp.WriteUint32Bytes(buf[at:], uint32(len(bbp.songs)))
	at += 4
	for k1, v1 := range bbp.songs {
		iohelp.WriteGUIDBytes(buf[at:], k1)
		at += 16
		(v1).MarshalBebopTo(buf[at:])
		{
			tmp := (v1)
			at += tmp.Size()
		}
		
	}
	return at
}

func (bbp *library) UnmarshalBebop(buf []byte) (err error) {
	at := 0
	ln1 := iohelp.ReadUint32Bytes(buf[at:])
	at += 4
	bbp.songs = make(map[[16]byte]song,ln1)
	for i := uint32(0); i < ln1; i++ {
		if len(buf[at:]) < 16 {
			return io.ErrUnexpectedEOF
		}
		k1 := iohelp.ReadGUIDBytes(buf[at:])
		at += 16
		(bbp.songs)[k1], err = makesongFromBytes(buf[at:])
		if err != nil {
			return err
		}
		{
			tmp := ((bbp.songs)[k1])
			at += tmp.Size()
		}
		
	}
	return nil
}

func (bbp *library) MustUnmarshalBebop(buf []byte) {
	at := 0
	ln2 := iohelp.ReadUint32Bytes(buf[at:])
	at += 4
	bbp.songs = make(map[[16]byte]song,ln2)
	for i := uint32(0); i < ln2; i++ {
		k1 := iohelp.ReadGUIDBytes(buf[at:])
		at += 16
		(bbp.songs)[k1] = mustMakesongFromBytes(buf[at:])
		{
			tmp := ((bbp.songs)[k1])
			at += tmp.Size()
		}
		
	}
}

func (bbp library) EncodeBebop(iow io.Writer) (err error) {
	w := iohelp.NewErrorWriter(iow)
	iohelp.WriteUint32(w, uint32(len(bbp.songs)))
	for k1, v1 := range bbp.songs {
		iohelp.WriteGUID(w, k1)
		err = (v1).EncodeBebop(w)
		if err != nil {
			return err
		}
	}
	return w.Err
}

func (bbp *library) DecodeBebop(ior io.Reader) (err error) {
	r := iohelp.NewErrorReader(ior)
	ln1 := iohelp.ReadUint32(r)
	bbp.songs = make(map[[16]byte]song, ln1)
	for i1 := uint32(0); i1 < ln1; i1++ {
		k1 := iohelp.ReadGUID(r)
		((bbp.songs[k1])), err = makesong(r)
		if err != nil {
			return err
		}
	}
	return r.Err
}

func (bbp library) Size() int {
	bodyLen := 0
	bodyLen += 4
	for _, v1 := range bbp.songs {
		bodyLen += 16
		{
			tmp := (v1)
			bodyLen += tmp.Size()
		}
		
	}
	return bodyLen
}

func (bbp library) MarshalBebop() []byte {
	buf := make([]byte, bbp.Size())
	bbp.MarshalBebopTo(buf)
	return buf
}

func makelibrary(r *iohelp.ErrorReader) (library, error) {
	v := library{}
	err := v.DecodeBebop(r)
	return v, err
}

func makelibraryFromBytes(buf []byte) (library, error) {
	v := library{}
	err := v.UnmarshalBebop(buf)
	return v, err
}

func mustMakelibraryFromBytes(buf []byte) library {
	v := library{}
	v.MustUnmarshalBebop(buf)
	return v
}

var _ bebop.Record = &song{}

type song struct {
	title *string
	year *uint16
	performers *[]musician
}

func (bbp song) MarshalBebopTo(buf []byte) int {
	at := 0
	iohelp.WriteUint32Bytes(buf[at:], uint32(bbp.Size()-4))
	at += 4
	if bbp.title != nil {
		buf[at] = 1
		at++
		iohelp.WriteUint32Bytes(buf[at:], uint32(len(*bbp.title)))
		copy(buf[at+4:at+4+len(*bbp.title)], []byte(*bbp.title))
		at += 4 + len(*bbp.title)
	}
	if bbp.year != nil {
		buf[at] = 2
		at++
		iohelp.WriteUint16Bytes(buf[at:], *bbp.year)
		at += 2
	}
	if bbp.performers != nil {
		buf[at] = 3
		at++
		iohelp.WriteUint32Bytes(buf[at:], uint32(len(*bbp.performers)))
		at += 4
		for _, v2 := range *bbp.performers {
			(v2).MarshalBebopTo(buf[at:])
			{
				tmp := (v2)
				at += tmp.Size()
			}
			
		}
	}
	return at
}

func (bbp *song) UnmarshalBebop(buf []byte) (err error) {
	at := 0
	_ = iohelp.ReadUint32Bytes(buf[at:])
	buf = buf[4:]
	for {
		switch buf[at] {
		case 1:
			at += 1
			bbp.title = new(string)
			(*bbp.title), err = iohelp.ReadStringBytes(buf[at:])
			if err != nil {
				return err
			}
			at += 4 + len((*bbp.title))
		case 2:
			at += 1
			bbp.year = new(uint16)
			if len(buf[at:]) < 2 {
				return io.ErrUnexpectedEOF
			}
			(*bbp.year) = iohelp.ReadUint16Bytes(buf[at:])
			at += 2
		case 3:
			at += 1
			bbp.performers = new([]musician)
			if len(buf[at:]) < 4 {
				return io.ErrUnexpectedEOF
			}
			(*bbp.performers) = make([]musician, iohelp.ReadUint32Bytes(buf[at:]))
			at += 4
			for i3 := range (*bbp.performers) {
				((*bbp.performers))[i3], err = makemusicianFromBytes(buf[at:])
				if err != nil {
					return err
				}
				{
					tmp := (((*bbp.performers))[i3])
					at += tmp.Size()
				}
				
			}
		default:
			return nil
		}
	}
}

func (bbp *song) MustUnmarshalBebop(buf []byte) {
	at := 0
	_ = iohelp.ReadUint32Bytes(buf[at:])
	buf = buf[4:]
	for {
		switch buf[at] {
		case 1:
			at += 1
			bbp.title = new(string)
			(*bbp.title) = iohelp.MustReadStringBytes(buf[at:])
			at += 4 + len((*bbp.title))
		case 2:
			at += 1
			bbp.year = new(uint16)
			(*bbp.year) = iohelp.ReadUint16Bytes(buf[at:])
			at += 2
		case 3:
			at += 1
			bbp.performers = new([]musician)
			(*bbp.performers) = make([]musician, iohelp.ReadUint32Bytes(buf[at:]))
			at += 4
			for i3 := range (*bbp.performers) {
				((*bbp.performers))[i3] = mustMakemusicianFromBytes(buf[at:])
				{
					tmp := (((*bbp.performers))[i3])
					at += tmp.Size()
				}
				
			}
		default:
			return
		}
	}
}

func (bbp song) EncodeBebop(iow io.Writer) (err error) {
	w := iohelp.NewErrorWriter(iow)
	iohelp.WriteUint32(w, uint32(bbp.Size()-4))
	if bbp.title != nil {
		w.Write([]byte{1})
		iohelp.WriteUint32(w, uint32(len(*bbp.title)))
		w.Write([]byte(*bbp.title))
	}
	if bbp.year != nil {
		w.Write([]byte{2})
		iohelp.WriteUint16(w, *bbp.year)
	}
	if bbp.performers != nil {
		w.Write([]byte{3})
		iohelp.WriteUint32(w, uint32(len(*bbp.performers)))
		for _, elem := range *bbp.performers {
			err = (elem).EncodeBebop(w)
			if err != nil {
				return err
			}
		}
	}
	w.Write([]byte{0})
	return w.Err
}

func (bbp *song) DecodeBebop(ior io.Reader) (err error) {
	r := iohelp.NewErrorReader(ior)
	bodyLen := iohelp.ReadUint32(r)
	baseReader := r.Reader
	r.Reader = &io.LimitedReader{R: baseReader, N: int64(bodyLen)}
	for {
		switch iohelp.ReadByte(r) {
		case 1:
			bbp.title = new(string)
			*bbp.title = iohelp.ReadString(r)
		case 2:
			bbp.year = new(uint16)
			*bbp.year = iohelp.ReadUint16(r)
		case 3:
			bbp.performers = new([]musician)
			*bbp.performers = make([]musician, iohelp.ReadUint32(r))
			for i := range *bbp.performers {
				((*bbp.performers)[i]), err = makemusician(r)
				if err != nil {
					return err
				}
			}
		default:
			r.Drain()
			r.Reader = baseReader
			return r.Err
		}
	}
}

func (bbp song) Size() int {
	bodyLen := 5
	if bbp.title != nil {
		bodyLen += 1
		bodyLen += 4 + len(*bbp.title)
	}
	if bbp.year != nil {
		bodyLen += 1
		bodyLen += 2
	}
	if bbp.performers != nil {
		bodyLen += 1
		bodyLen += 4
		for _, elem := range *bbp.performers {
			{
				tmp := (elem)
				bodyLen += tmp.Size()
			}
			
		}
	}
	return bodyLen
}

func (bbp song) MarshalBebop() []byte {
	buf := make([]byte, bbp.Size())
	bbp.MarshalBebopTo(buf)
	return buf
}

func makesong(r *iohelp.ErrorReader) (song, error) {
	v := song{}
	err := v.DecodeBebop(r)
	return v, err
}

func makesongFromBytes(buf []byte) (song, error) {
	v := song{}
	err := v.UnmarshalBebop(buf)
	return v, err
}

func mustMakesongFromBytes(buf []byte) song {
	v := song{}
	v.MustUnmarshalBebop(buf)
	return v
}

