// Copyright 2021 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// idlgen is a tool used to generate code from WebIDL files and a golang
// template file
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"text/template"
	"unicode"

	"github.com/ben-clayton/webidlparser/ast"
	"github.com/ben-clayton/webidlparser/parser"
)

func main() {
	if err := run(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func showUsage() {
	fmt.Println(`
idlgen is a tool used to generate code from WebIDL files and a golang
template file

Usage:
  idlgen --template=<template-path> --output=<output-path> <idl-file> [<idl-file>...]`)
	os.Exit(1)
}

func run() error {
	var templatePath string
	var outputPath string
	flag.StringVar(&templatePath, "template", "", "the template file run with the parsed WebIDL files")
	flag.StringVar(&outputPath, "output", "", "the output file")
	flag.Parse()

	idlFiles := flag.Args()

	// Check all required arguments are provided
	if templatePath == "" || outputPath == "" || len(idlFiles) == 0 {
		showUsage()
	}

	// Open up the output file
	out := os.Stdout
	if outputPath != "" {
		dir := filepath.Dir(outputPath)
		if err := os.MkdirAll(dir, 0777); err != nil {
			return fmt.Errorf("failed to create output directory '%v'", dir)
		}
		file, err := os.Create(outputPath)
		if err != nil {
			return fmt.Errorf("failed to open output file '%v'", outputPath)
		}
		out = file
		defer file.Close()
	}

	// Read the template file
	tmpl, err := ioutil.ReadFile(templatePath)
	if err != nil {
		return fmt.Errorf("failed to open template file '%v'", templatePath)
	}

	// idl is the combination of the parsed idlFiles
	idl := &ast.File{}

	// Parse each of the WebIDL files and add the declarations to idl
	for _, path := range idlFiles {
		content, err := ioutil.ReadFile(path)
		if err != nil {
			return fmt.Errorf("failed to open file '%v'", path)
		}
		fileIDL := parser.Parse(string(content))
		if numErrs := len(fileIDL.Errors); numErrs != 0 {
			errs := make([]string, numErrs)
			for i, e := range fileIDL.Errors {
				errs[i] = e.Message
			}
			return fmt.Errorf("errors found while parsing %v:\n%v", path, strings.Join(errs, "\n"))
		}
		idl.Declarations = append(idl.Declarations, fileIDL.Declarations...)
	}

	// Initialize the generator
	g := generator{t: template.New(templatePath)}
	g.workingDir = filepath.Dir(templatePath)
	g.funcs = map[string]interface{}{
		// Functions exposed to the template
		"AttributesOf":               attributesOf,
		"ConstantsOf":                constantsOf,
		"EnumEntryName":              enumEntryName,
		"Eval":                       g.eval,
		"HasAnnotation":              hasAnnotation,
		"HasConstructor":             hasConstructor,
		"FlattenedAttributesOf":      g.flattenedAttributesOf,
		"FlattenedConstantsOf":       g.flattenedConstantsOf,
		"FlattenedMethodsOf":         g.flattenedMethodsOf,
		"Include":                    g.include,
		"IsBasicLiteral":             is(ast.BasicLiteral{}),
		"IsCallback":                 is(ast.Callback{}),
		"IsInitializer":              isInitializer,
		"IsDefaultDictionaryLiteral": is(ast.DefaultDictionaryLiteral{}),
		"IsDictionary":               is(ast.Dictionary{}),
		"IsEnum":                     is(ast.Enum{}),
		"IsInterface":                is(ast.Interface{}),
		"IsInterfaceOrNamespace":     is(ast.Interface{}, ast.Namespace{}),
		"IsMember":                   is(ast.Member{}),
		"IsNamespace":                is(ast.Namespace{}),
		"IsNullableType":             is(ast.NullableType{}),
		"IsParametrizedType":         is(ast.ParametrizedType{}),
		"IsRecordType":               is(ast.RecordType{}),
		"IsSequenceType":             is(ast.SequenceType{}),
		"IsTypedef":                  is(ast.Typedef{}),
		"IsTypeName":                 is(ast.TypeName{}),
		"IsUndefinedType":            isUndefinedType,
		"IsUnionType":                is(ast.UnionType{}),
		"Lookup":                     g.lookup,
		"MethodsOf":                  methodsOf,
		"ReturnsPromise":             returnsPromise,
		"SetlikeOf":                  setlikeOf,
		"Title":                      strings.Title,
	}
	t, err := g.t.
		Option("missingkey=invalid").
		Funcs(g.funcs).
		Parse(string(tmpl))
	if err != nil {
		return fmt.Errorf("failed to parse template file '%v': %w", templatePath, err)
	}

	// simplify the definitions in the WebIDL before passing this to the template
	idl, declarations := simplify(idl)

	// Patch the IDL for the differences we need compared to the upstream IDL.
	patch(idl, declarations)
	g.declarations = declarations

	// Write the file header
	fmt.Fprintf(out, header, strings.Join(os.Args[1:], "\n//   "))

	// Execute the template
	return t.Execute(out, idl)
}

// declarations is a map of WebIDL declaration name to its AST node.
type declarations map[string]ast.Decl

// nameOf returns the name of the AST node n.
// Returns an empty string if the node is not named.
func nameOf(n ast.Node) string {
	switch n := n.(type) {
	case *ast.Namespace:
		return n.Name
	case *ast.Interface:
		return n.Name
	case *ast.Dictionary:
		return n.Name
	case *ast.Enum:
		return n.Name
	case *ast.Typedef:
		return n.Name
	case *ast.Mixin:
		return n.Name
	case *ast.Callback:
		return n.Name
	case *ast.Includes:
		return ""

	default:
		panic(fmt.Errorf("unhandled AST declaration %T", n))
	}
}

// simplify processes the AST 'in', returning a new AST that:
// * Has all partial interfaces merged into a single interface.
// * Has all mixins flattened into their place of use.
// * Has all the declarations ordered in dependency order (leaf first)
// simplify also returns the map of declarations in the AST.
func simplify(in *ast.File) (*ast.File, declarations) {
	s := simplifier{
		declarations: declarations{},
		registered:   map[string]bool{},
		out:          &ast.File{},
	}

	// Walk the IDL declarations to merge together partial interfaces and embed
	// mixins into their uses.
	{
		interfaces := map[string]*ast.Interface{}
		mixins := map[string]*ast.Mixin{}
		includes := []*ast.Includes{}
		enums := map[string]*ast.Enum{}
		dicts := map[string]*ast.Dictionary{}
		for _, d := range in.Declarations {
			switch d := d.(type) {
			case *ast.Interface:
				if i, ok := interfaces[d.Name]; ok {
					// Merge partial body into one interface
					i.Members = append(i.Members, d.Members...)
				} else {
					clone := *d
					d := &clone
					interfaces[d.Name] = d
					s.declarations[d.Name] = d
				}
			case *ast.Mixin:
				mixins[d.Name] = d
				s.declarations[d.Name] = d
			case *ast.Includes:
				includes = append(includes, d)
			case *ast.Enum:
				if e, ok := enums[d.Name]; ok {
					// Merge partial enums into one enum
					e.Values = append(e.Values, d.Values...)
				} else {
					clone := *d
					d := &clone
					enums[d.Name] = d
					s.declarations[d.Name] = d
				}
			case *ast.Dictionary:
				if e, ok := dicts[d.Name]; ok {
					// Merge partial dictionaries into one dictionary
					e.Members = append(e.Members, d.Members...)
				} else {
					clone := *d
					d := &clone
					dicts[d.Name] = d
					s.declarations[d.Name] = d
				}
			default:
				if name := nameOf(d); name != "" {
					s.declarations[nameOf(d)] = d
				}
			}
		}

		// Merge mixin into interface
		for _, include := range includes {
			i, ok := interfaces[include.Name]
			if !ok {
				panic(fmt.Errorf("%v includes %v, but %v is not an interface", include.Name, include.Source, include.Name))
			}
			m, ok := mixins[include.Source]
			if !ok {
				panic(fmt.Errorf("%v includes %v, but %v is not an mixin", include.Name, include.Source, include.Source))
			}
			// Merge mixin into the interface
			for _, member := range m.Members {
				if member, ok := member.(*ast.Member); ok {
					i.Members = append(i.Members, member)
				}
			}
		}
	}

	// Now traverse the declarations in to produce the dependency-ordered
	// output `s.out`.
	for _, d := range in.Declarations {
		if name := nameOf(d); name != "" {
			s.visit(s.declarations[nameOf(d)])
		}
	}

	return s.out, s.declarations
}

// simplifier holds internal state for simplify()
type simplifier struct {
	// all AST declarations
	declarations declarations
	// set of visited declarations
	registered map[string]bool
	// the dependency-ordered output
	out *ast.File
}

// visit traverses the AST declaration 'd' adding all dependent declarations to
// s.out.
func (s *simplifier) visit(d ast.Decl) {
	register := func(name string) bool {
		if s.registered[name] {
			return true
		}
		s.registered[name] = true
		return false
	}
	switch d := d.(type) {
	case *ast.Namespace:
		if register(d.Name) {
			return
		}
		for _, m := range d.Members {
			if m, ok := m.(*ast.Member); ok {
				s.visitType(m.Type)
				for _, p := range m.Parameters {
					s.visitType(p.Type)
				}
			}
		}
	case *ast.Interface:
		if register(d.Name) {
			return
		}
		if d, ok := s.declarations[d.Inherits]; ok {
			s.visit(d)
		}
		for _, m := range d.Members {
			if m, ok := m.(*ast.Member); ok {
				s.visitType(m.Type)
				for _, p := range m.Parameters {
					s.visitType(p.Type)
				}
			}
		}
	case *ast.Dictionary:
		if register(d.Name) {
			return
		}
		if d, ok := s.declarations[d.Inherits]; ok {
			s.visit(d)
		}
		for _, m := range d.Members {
			s.visitType(m.Type)
			for _, p := range m.Parameters {
				s.visitType(p.Type)
			}
		}
	case *ast.Typedef:
		if register(d.Name) {
			return
		}
		s.visitType(d.Type)
	case *ast.Mixin:
		if register(d.Name) {
			return
		}
		for _, m := range d.Members {
			if m, ok := m.(*ast.Member); ok {
				s.visitType(m.Type)
				for _, p := range m.Parameters {
					s.visitType(p.Type)
				}
			}
		}
	case *ast.Enum:
		if register(d.Name) {
			return
		}
	case *ast.Includes:
		if register(d.Name) {
			return
		}
	case *ast.Callback:
		for _, p := range d.Parameters {
			s.visitType(p.Type)
		}
	default:
		panic(fmt.Errorf("unhandled AST declaration %T", d))
	}

	s.out.Declarations = append(s.out.Declarations, d)
}

// visitType traverses the AST type 't' adding all dependent declarations to
// s.out.
func (s *simplifier) visitType(t ast.Type) {
	switch t := t.(type) {
	case *ast.TypeName:
		if d, ok := s.declarations[t.Name]; ok {
			s.visit(d)
		}
	case *ast.UnionType:
		for _, t := range t.Types {
			s.visitType(t)
		}
	case *ast.ParametrizedType:
		for _, t := range t.Elems {
			s.visitType(t)
		}
	case *ast.NullableType:
		s.visitType(t.Type)
	case *ast.SequenceType:
		s.visitType(t.Elem)
	case *ast.RecordType:
		s.visitType(t.Elem)
	default:
		panic(fmt.Errorf("unhandled AST type %T", t))
	}
}

func patch(idl *ast.File, decl declarations) {
	// Add [SameObject] to GPUDevice.lost
	for _, member := range decl["GPUDevice"].(*ast.Interface).Members {
		if m := member.(*ast.Member); m != nil && m.Name == "lost" {
			annotation := &ast.Annotation{}
			annotation.Name = "SameObject"
			m.Annotations = append(m.Annotations, annotation)
		}
	}
}

// generator holds the template generator state
type generator struct {
	// the root template
	t *template.Template
	// the working directory
	workingDir string
	// map of function name to function exposed to the template executor
	funcs map[string]interface{}
	// dependency-sorted declarations
	declarations declarations
}

// eval executes the sub-template with the given name and arguments, returning
// the generated output
// args can be a single argument:
//
//	arg[0]
//
// or a list of name-value pairs:
//
//	(args[0]: name, args[1]: value), (args[2]: name, args[3]: value)...
func (g *generator) eval(template string, args ...interface{}) (string, error) {
	target := g.t.Lookup(template)
	if target == nil {
		return "", fmt.Errorf("template '%v' not found", template)
	}
	sb := strings.Builder{}
	var err error
	if len(args) == 1 {
		err = target.Execute(&sb, args[0])
	} else {
		m := newMap()
		if len(args)%2 != 0 {
			return "", fmt.Errorf("Eval expects a single argument or list name-value pairs")
		}
		for i := 0; i < len(args); i += 2 {
			name, ok := args[i].(string)
			if !ok {
				return "", fmt.Errorf("Eval argument %v is not a string", i)
			}
			m.Put(name, args[i+1])
		}
		err = target.Execute(&sb, m)
	}
	if err != nil {
		return "", fmt.Errorf("while evaluating '%v': %v", template, err)
	}
	return sb.String(), nil
}

// lookup returns the declaration with the given name, or nil if not found.
func (g *generator) lookup(name string) ast.Decl {
	return g.declarations[name]
}

// include loads the template with the given path, importing the declarations
// into the scope of the current template.
func (g *generator) include(path string) (string, error) {
	t, err := g.t.
		Option("missingkey=invalid").
		Funcs(g.funcs).
		ParseFiles(filepath.Join(g.workingDir, path))
	if err != nil {
		return "", err
	}
	g.t.AddParseTree(path, t.Tree)
	return "", nil
}

// Map is a simple generic key-value map, which can be used in the template
type Map map[interface{}]interface{}

func newMap() Map { return Map{} }

// Put adds the key-value pair into the map.
// Put always returns an empty string so nothing is printed in the template.
func (m Map) Put(key, value interface{}) string {
	m[key] = value
	return ""
}

// Get looks up and returns the value with the given key. If the map does not
// contain the given key, then nil is returned.
func (m Map) Get(key interface{}) interface{} {
	return m[key]
}

// is returns a function that returns true if the value passed to the function
// matches any of the types of the objects in 'prototypes'.
func is(prototypes ...interface{}) func(interface{}) bool {
	types := make([]reflect.Type, len(prototypes))
	for i, p := range prototypes {
		types[i] = reflect.TypeOf(p)
	}
	return func(v interface{}) bool {
		ty := reflect.TypeOf(v)
		for _, rty := range types {
			if ty == rty || ty == reflect.PtrTo(rty) {
				return true
			}
		}
		return false
	}
}

// isInitializer returns true if the object is a constructor ast.Member.
func isInitializer(v interface{}) bool {
	if member, ok := v.(*ast.Member); ok {
		if ty, ok := member.Type.(*ast.TypeName); ok {
			return ty.Name == "constructor"
		}
	}
	return false
}

// isUndefinedType returns true if the type is 'undefined'
func isUndefinedType(ty ast.Type) bool {
	if ty, ok := ty.(*ast.TypeName); ok {
		return ty.Name == "undefined"
	}
	return false
}

// enumEntryName formats the enum entry name 's' for use in a C++ enum.
func enumEntryName(s string) string {
	return "k" + strings.ReplaceAll(pascalCase(strings.Trim(s, `"`)), "-", "")
}

func findAnnotation(list []*ast.Annotation, name string) *ast.Annotation {
	for _, annotation := range list {
		if annotation.Name == name {
			return annotation
		}
	}
	return nil
}

func hasAnnotation(obj interface{}, name string) bool {
	switch obj := obj.(type) {
	case *ast.Interface:
		return findAnnotation(obj.Annotations, name) != nil
	case *ast.Member:
		return findAnnotation(obj.Annotations, name) != nil
	case *ast.Namespace:
		return findAnnotation(obj.Annotations, name) != nil
	case *ast.Parameter:
		return findAnnotation(obj.Annotations, name) != nil
	case *ast.Typedef:
		return findAnnotation(obj.Annotations, name) != nil || findAnnotation(obj.TypeAnnotations, name) != nil
	}
	panic("Unhandled AST node type in hasAnnotation")
}

func hasConstructor(obj interface{}) bool {
	iface := obj.(*ast.Interface)
	for _, member := range iface.Members {
		member := member.(*ast.Member)
		if isInitializer(member) {
			return true
		}
	}
	return false
}

// Method describes a WebIDL interface method
type Method struct {
	// Name of the method
	Name string
	// The list of overloads of the method
	Overloads []*ast.Member
}

// methodsOf returns all the methods of the given WebIDL interface.
func methodsOf(obj interface{}) []*Method {
	iface, ok := obj.(*ast.Interface)
	if !ok {
		return nil
	}
	byName := map[string]*Method{}
	out := []*Method{}
	for _, member := range iface.Members {
		member := member.(*ast.Member)
		if !member.Const && !member.Attribute && !isInitializer(member) {
			if method, ok := byName[member.Name]; ok {
				method.Overloads = append(method.Overloads, member)
			} else {
				method = &Method{
					Name:      member.Name,
					Overloads: []*ast.Member{member},
				}
				byName[member.Name] = method
				out = append(out, method)
			}
		}
	}
	return out
}

// flattenedMethodsOf returns all the methods of the given WebIDL
// interface or namespace, as well as all the methods of the full inheritance
// chain
func (g *generator) flattenedMethodsOf(obj interface{}) []*Method {
	switch obj := obj.(type) {
	case *ast.Interface:
		out := methodsOf(obj)
		if base := g.lookup(obj.Inherits); base != nil {
			out = append(out, g.flattenedMethodsOf(base)...)
		}
		return out
	default:
		return methodsOf(obj)
	}
}

// attributesOf returns all the attributes of the given WebIDL interface or
// namespace.
func attributesOf(obj interface{}) []*ast.Member {
	out := []*ast.Member{}
	add := func(m interface{}) {
		if m := m.(*ast.Member); m.Attribute {
			out = append(out, m)
		}
	}

	switch obj := obj.(type) {
	case *ast.Interface:
		for _, m := range obj.Members {
			add(m)
		}
	case *ast.Namespace:
		for _, m := range obj.Members {
			add(m)
		}
	default:
		return nil
	}
	return out
}

// flattenedAttributesOf returns all the attributes of the given WebIDL
// interface or namespace, as well as all the attributes of the full inheritance
// chain
func (g *generator) flattenedAttributesOf(obj interface{}) []*ast.Member {
	switch obj := obj.(type) {
	case *ast.Interface:
		out := attributesOf(obj)
		if base := g.lookup(obj.Inherits); base != nil {
			out = append(out, g.flattenedAttributesOf(base)...)
		}
		return out
	default:
		return attributesOf(obj)
	}
}

// constantsOf returns all the constant values of the given WebIDL interface or
// namespace.
func constantsOf(obj interface{}) []*ast.Member {
	out := []*ast.Member{}
	add := func(m interface{}) {
		if m := m.(*ast.Member); m.Const {
			out = append(out, m)
		}
	}
	switch obj := obj.(type) {
	case *ast.Interface:
		for _, m := range obj.Members {
			add(m)
		}
	case *ast.Namespace:
		for _, m := range obj.Members {
			add(m)
		}
	default:
		return nil
	}
	return out
}

// flattenedConstantsOf returns all the constants of the given WebIDL
// interface or namespace, as well as all the constants of the full inheritance
// chain
func (g *generator) flattenedConstantsOf(obj interface{}) []*ast.Member {
	switch obj := obj.(type) {
	case *ast.Interface:
		out := constantsOf(obj)
		if base := g.lookup(obj.Inherits); base != nil {
			out = append(out, g.flattenedConstantsOf(base)...)
		}
		return out
	default:
		return constantsOf(obj)
	}
}

// isPromiseType returns true if the type is 'Promise<T>'
func isPromiseType(ty ast.Type) bool {
	if ty, ok := ty.(*ast.ParametrizedType); ok {
		return ty.Name == "Promise"
	}
	return false
}

// returnsPromise returns true if the ast.Method returns a Promise.
func returnsPromise(obj interface{}) bool {
	method, ok := obj.(*Method)
	if !ok {
		panic("Unhandled AST node type in hasAnnotation")
	}

	firstIsPromise := isPromiseType(method.Overloads[0].Type)
	for _, o := range method.Overloads {
		if isPromiseType(o.Type) != firstIsPromise {
			panic("IDL has overloads that are not consistently returning Promises")
		}
	}

	return firstIsPromise
}

// setlikeOf returns the setlike ast.Pattern, if obj is a setlike interface.
func setlikeOf(obj interface{}) *ast.Pattern {
	iface, ok := obj.(*ast.Interface)
	if !ok {
		return nil
	}
	for _, pattern := range iface.Patterns {
		if pattern.Type == ast.Setlike {
			return pattern
		}
	}
	return nil
}

// pascalCase returns the snake-case string s transformed into 'PascalCase',
// Rules:
// * The first letter of the string is capitalized
// * Characters following an underscore, hyphen or number are capitalized
// * Underscores are removed from the returned string
// See: https://en.wikipedia.org/wiki/Camel_case
func pascalCase(s string) string {
	b := strings.Builder{}
	upper := true
	for _, r := range s {
		if r == '_' || r == '-' {
			upper = true
			continue
		}
		if upper {
			b.WriteRune(unicode.ToUpper(r))
			upper = false
		} else {
			b.WriteRune(r)
		}
		if unicode.IsNumber(r) {
			upper = true
		}
	}
	return b.String()
}

const header = `// Copyright 2021 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

////////////////////////////////////////////////////////////////////////////////
// File generated by tools/cmd/idlgen.go, with the arguments:
//   %v
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////

`
