1// Copyright 2019 Istio Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package codegen
16
17import (
18	"bytes"
19	"strings"
20	"text/template"
21)
22
23const (
24	commentLinePrefix = "// "
25)
26
27func applyTemplate(tmpl string, i interface{}) (string, error) {
28	t := template.New("tmpl").Funcs(template.FuncMap{
29		"wordWrap":     wordWrap,
30		"commentBlock": commentBlock,
31		"hasPrefix":    strings.HasPrefix,
32	})
33
34	t2 := template.Must(t.Parse(tmpl))
35
36	var b bytes.Buffer
37	if err := t2.Execute(&b, i); err != nil {
38		return "", err
39	}
40
41	return b.String(), nil
42}
43
44func commentBlock(in []string, indentTabs int) string {
45	// Copy the input array.
46	in = append([]string{}, in...)
47
48	// Apply the tabs and comment prefix to each line.
49	for lineIndex := range in {
50		prefix := ""
51		for tabIndex := 0; lineIndex > 0 && tabIndex < indentTabs; tabIndex++ {
52			prefix += "\t"
53		}
54		prefix += commentLinePrefix
55		in[lineIndex] = prefix + in[lineIndex]
56	}
57
58	// Join the lines with carriage returns.
59	return strings.Join(in, "\n")
60}
61
62func wordWrap(in string, maxLineLength int) []string {
63	// First, split the input based on any user-created lines (i.e. the string contains "\n").
64	inputLines := strings.Split(in, "\n")
65	outputLines := make([]string, 0)
66
67	line := ""
68	for i, inputLine := range inputLines {
69		if i > 0 {
70			// Process a user-defined carriage return.
71			outputLines = append(outputLines, line)
72			line = ""
73		}
74
75		words := strings.Split(inputLine, " ")
76
77		for len(words) > 0 {
78			// Take the next word.
79			word := words[0]
80			words = words[1:]
81
82			if len(line)+len(word) > maxLineLength {
83				// Need to word wrap - emit the current line.
84				outputLines = append(outputLines, line)
85				line = ""
86			}
87
88			// Add the word to the current line.
89			if len(line) > 0 {
90				line += " "
91			}
92			line += word
93		}
94	}
95
96	// Emit the final line
97	outputLines = append(outputLines, line)
98
99	return outputLines
100}
101