// Code generated by go run gob_gen.go; DO NOT EDIT.

package python

import (
	"android/soong/android"
	"bytes"
	"fmt"
	"github.com/google/blueprint/gobtools"
	"github.com/google/blueprint/proptools"
	"reflect"
)

// begin of binary.go
func init() {
	PythonBinaryInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(PythonBinaryInfo) })
}

func (r PythonBinaryInfo) Encode(ctx gobtools.EncContext, buf *bytes.Buffer) error {
	var err error
	return err
}

func (r PythonBinaryInfo) CustomHash(hasher *proptools.Hasher) error {
	hasher.WriteString(":python.PythonBinaryInfo")
	hasher.WriteInt(0)
	return nil
}

func (r *PythonBinaryInfo) Decode(ctx gobtools.EncContext, buf *bytes.Reader) error {
	var err error

	return err
}

var PythonBinaryInfoGobRegId int16

func (r PythonBinaryInfo) GetTypeId() int16 {
	return PythonBinaryInfoGobRegId
}

// end of binary.go

// begin of python.go
func init() {
	PythonLibraryInfoGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(PythonLibraryInfo) })
	pathMappingGobRegId = gobtools.RegisterType(func() gobtools.CustomDec { return new(pathMapping) })
}

func (r PythonLibraryInfo) Encode(ctx gobtools.EncContext, buf *bytes.Buffer) error {
	var err error

	if err = r.SrcsPathMappings.Encode(ctx, buf); err != nil {
		return err
	}

	if err = r.DataPathMappings.Encode(ctx, buf); err != nil {
		return err
	}

	if err = r.SrcsZip.EncodeInterface(ctx, buf); err != nil {
		return err
	}

	if err = r.PrecompiledSrcsZip.EncodeInterface(ctx, buf); err != nil {
		return err
	}

	if err = gobtools.EncodeString(buf, r.PkgPath); err != nil {
		return err
	}

	if err = r.BundleSharedLibs.EncodeInterface(ctx, buf); err != nil {
		return err
	}
	return err
}

func (r PythonLibraryInfo) CustomHash(hasher *proptools.Hasher) error {
	hasher.WriteString(":python.PythonLibraryInfo")
	hasher.WriteInt(6)
	val2 := func(hasher *proptools.Hasher, val1 pathMapping) error {
		if err := val1.CustomHash(hasher); err != nil {
			return err
		}
		return nil
	}
	if err := r.SrcsPathMappings.Hash(hasher, "pathMapping", val2); err != nil {
		return err
	}
	val4 := func(hasher *proptools.Hasher, val3 pathMapping) error {
		if err := val3.CustomHash(hasher); err != nil {
			return err
		}
		return nil
	}
	if err := r.DataPathMappings.Hash(hasher, "pathMapping", val4); err != nil {
		return err
	}
	val9 := func(hasher *proptools.Hasher, val5 android.Path) error {
		hasher.WriteString(":python.android.Path")
		val6 := val5 == nil
		if val6 {
			hasher.WriteByte(0)
		} else {
			if v := reflect.ValueOf(val5); v.Kind() == reflect.Ptr {
				if v.IsNil() {
					panic(fmt.Errorf("nil pointer is not supported in interface"))
				} else {
					val7 := val5 == nil
					if val7 {
						hasher.WriteByte(0)
					} else {
						val8 := func(hasher *proptools.Hasher) error { return val5.(proptools.CustomHash).CustomHash(hasher) }
						if err := proptools.HashReference(hasher, uintptr(v.Pointer()), val8); err != nil {
							return err
						}
					}
				}
			} else {
				val5.(proptools.CustomHash).CustomHash(hasher)
			}
		}
		return nil
	}
	if err := r.SrcsZip.Hash(hasher, "android.Path", val9); err != nil {
		return err
	}
	val14 := func(hasher *proptools.Hasher, val10 android.Path) error {
		hasher.WriteString(":python.android.Path")
		val11 := val10 == nil
		if val11 {
			hasher.WriteByte(0)
		} else {
			if v := reflect.ValueOf(val10); v.Kind() == reflect.Ptr {
				if v.IsNil() {
					panic(fmt.Errorf("nil pointer is not supported in interface"))
				} else {
					val12 := val10 == nil
					if val12 {
						hasher.WriteByte(0)
					} else {
						val13 := func(hasher *proptools.Hasher) error { return val10.(proptools.CustomHash).CustomHash(hasher) }
						if err := proptools.HashReference(hasher, uintptr(v.Pointer()), val13); err != nil {
							return err
						}
					}
				}
			} else {
				val10.(proptools.CustomHash).CustomHash(hasher)
			}
		}
		return nil
	}
	if err := r.PrecompiledSrcsZip.Hash(hasher, "android.Path", val14); err != nil {
		return err
	}
	hasher.WriteString(":.string")
	hasher.WriteString(r.PkgPath)
	val19 := func(hasher *proptools.Hasher, val15 android.Path) error {
		hasher.WriteString(":python.android.Path")
		val16 := val15 == nil
		if val16 {
			hasher.WriteByte(0)
		} else {
			if v := reflect.ValueOf(val15); v.Kind() == reflect.Ptr {
				if v.IsNil() {
					panic(fmt.Errorf("nil pointer is not supported in interface"))
				} else {
					val17 := val15 == nil
					if val17 {
						hasher.WriteByte(0)
					} else {
						val18 := func(hasher *proptools.Hasher) error { return val15.(proptools.CustomHash).CustomHash(hasher) }
						if err := proptools.HashReference(hasher, uintptr(v.Pointer()), val18); err != nil {
							return err
						}
					}
				}
			} else {
				val15.(proptools.CustomHash).CustomHash(hasher)
			}
		}
		return nil
	}
	if err := r.BundleSharedLibs.Hash(hasher, "android.Path", val19); err != nil {
		return err
	}
	return nil
}

func (r *PythonLibraryInfo) Decode(ctx gobtools.EncContext, buf *bytes.Reader) error {
	var err error

	if err = r.SrcsPathMappings.Decode(ctx, buf); err != nil {
		return err
	}

	if err = r.DataPathMappings.Decode(ctx, buf); err != nil {
		return err
	}

	if err = r.SrcsZip.DecodeInterface(ctx, buf); err != nil {
		return err
	}

	if err = r.PrecompiledSrcsZip.DecodeInterface(ctx, buf); err != nil {
		return err
	}

	err = gobtools.DecodeString(buf, &r.PkgPath)
	if err != nil {
		return err
	}

	if err = r.BundleSharedLibs.DecodeInterface(ctx, buf); err != nil {
		return err
	}

	return err
}

var PythonLibraryInfoGobRegId int16

func (r PythonLibraryInfo) GetTypeId() int16 {
	return PythonLibraryInfoGobRegId
}

func (r pathMapping) Encode(ctx gobtools.EncContext, buf *bytes.Buffer) error {
	var err error

	if err = gobtools.EncodeString(buf, r.module); err != nil {
		return err
	}

	if err = gobtools.EncodeString(buf, r.dest); err != nil {
		return err
	}

	if err = gobtools.EncodeInterface(ctx, buf, r.src); err != nil {
		return err
	}
	return err
}

func (r pathMapping) CustomHash(hasher *proptools.Hasher) error {
	hasher.WriteString(":python.pathMapping")
	hasher.WriteInt(3)
	hasher.WriteString(":.string")
	hasher.WriteString(r.module)
	hasher.WriteString(":.string")
	hasher.WriteString(r.dest)
	hasher.WriteString(":python.android.Path")
	val1 := r.src == nil
	if val1 {
		hasher.WriteByte(0)
	} else {
		if v := reflect.ValueOf(r.src); v.Kind() == reflect.Ptr {
			if v.IsNil() {
				panic(fmt.Errorf("nil pointer is not supported in interface"))
			} else {
				val2 := r.src == nil
				if val2 {
					hasher.WriteByte(0)
				} else {
					val3 := func(hasher *proptools.Hasher) error { return r.src.(proptools.CustomHash).CustomHash(hasher) }
					if err := proptools.HashReference(hasher, uintptr(v.Pointer()), val3); err != nil {
						return err
					}
				}
			}
		} else {
			r.src.(proptools.CustomHash).CustomHash(hasher)
		}
	}
	return nil
}

func (r *pathMapping) Decode(ctx gobtools.EncContext, buf *bytes.Reader) error {
	var err error

	err = gobtools.DecodeString(buf, &r.module)
	if err != nil {
		return err
	}

	err = gobtools.DecodeString(buf, &r.dest)
	if err != nil {
		return err
	}

	if val4, err := gobtools.DecodeInterface(ctx, buf); err != nil {
		return err
	} else if val4 == nil {
		r.src = nil
	} else {
		r.src = val4.(android.Path)
	}

	return err
}

var pathMappingGobRegId int16

func (r pathMapping) GetTypeId() int16 {
	return pathMappingGobRegId
}

// end of python.go
