1package table
2
3import (
4	"fmt"
5	"io"
6	"reflect"
7	"strconv"
8	"strings"
9	"time"
10
11	semver "github.com/cppforlife/go-semi-semantic/version"
12	"github.com/dustin/go-humanize"
13	"gopkg.in/yaml.v2"
14
15	boshuifmt "github.com/cloudfoundry/bosh-cli/ui/fmt"
16)
17
18func NewValueString(s string) ValueString { return ValueString{S: s} }
19
20func (t ValueString) String() string { return t.S }
21func (t ValueString) Value() Value   { return t }
22
23func (t ValueString) Compare(other Value) int {
24	otherS := other.(ValueString).S
25	switch {
26	case t.S == otherS:
27		return 0
28	case t.S < otherS:
29		return -1
30	default:
31		return 1
32	}
33}
34
35func (t EmptyValue) String() string    { return "" }
36func (t EmptyValue) Value() Value      { return t }
37func (t EmptyValue) Compare(Value) int { return 0 }
38
39func NewValueStrings(s []string) ValueStrings { return ValueStrings{S: s} }
40
41func (t ValueStrings) String() string { return strings.Join(t.S, "\n") }
42func (t ValueStrings) Value() Value   { return t }
43
44func (t ValueStrings) Compare(other Value) int {
45	otherS := other.(ValueStrings).S
46	switch {
47	case len(t.S) == len(otherS):
48		return 0
49	case len(t.S) < len(otherS):
50		return -1
51	default:
52		return 1
53	}
54}
55
56func NewValueInt(i int) ValueInt { return ValueInt{I: i} }
57
58func (t ValueInt) String() string { return strconv.Itoa(t.I) }
59func (t ValueInt) Value() Value   { return t }
60
61func (t ValueInt) Compare(other Value) int {
62	otherI := other.(ValueInt).I
63	switch {
64	case t.I == otherI:
65		return 0
66	case t.I < otherI:
67		return -1
68	default:
69		return 1
70	}
71}
72
73func NewValueBytes(i uint64) ValueBytes     { return ValueBytes{I: i} }
74func NewValueMegaBytes(i uint64) ValueBytes { return ValueBytes{I: i * 1024 * 1024} }
75
76func (t ValueBytes) String() string { return humanize.IBytes(t.I) }
77func (t ValueBytes) Value() Value   { return t }
78
79func (t ValueBytes) Compare(other Value) int {
80	otherI := other.(ValueBytes).I
81	switch {
82	case t.I == otherI:
83		return 0
84	case t.I < otherI:
85		return -1
86	default:
87		return 1
88	}
89}
90
91func NewValueTime(t time.Time) ValueTime { return ValueTime{T: t} }
92
93func (t ValueTime) String() string {
94	if t.T.IsZero() {
95		return ""
96	}
97	return t.T.Format(boshuifmt.TimeFullFmt)
98}
99func (t ValueTime) Value() Value { return t }
100
101func (t ValueTime) Compare(other Value) int {
102	otherT := other.(ValueTime).T
103	switch {
104	case t.T.Equal(otherT):
105		return 0
106	case t.T.Before(otherT):
107		return -1
108	default:
109		return 1
110	}
111}
112
113func NewValueBool(b bool) ValueBool { return ValueBool{B: b} }
114
115func (t ValueBool) String() string { return fmt.Sprintf("%t", t.B) }
116func (t ValueBool) Value() Value   { return t }
117
118func (t ValueBool) Compare(other Value) int {
119	otherB := other.(ValueBool).B
120	switch {
121	case t.B == otherB:
122		return 0
123	case t.B == false && otherB == true:
124		return -1
125	default:
126		return 1
127	}
128}
129
130func NewValueVersion(v semver.Version) ValueVersion { return ValueVersion{V: v} }
131
132func (t ValueVersion) String() string { return t.V.String() }
133func (t ValueVersion) Value() Value   { return t }
134
135func (t ValueVersion) Compare(other Value) int {
136	return t.V.Compare(other.(ValueVersion).V)
137}
138
139func NewValueError(e error) ValueError { return ValueError{E: e} }
140
141func (t ValueError) String() string {
142	if t.E != nil {
143		return t.E.Error()
144	}
145	return ""
146}
147
148func NewValueInterface(i interface{}) ValueInterface { return ValueInterface{I: i} }
149
150func (t ValueInterface) String() string {
151	if t.I == nil {
152		return ""
153	}
154
155	val := reflect.ValueOf(t.I)
156
157	if val.Kind() == reflect.Map && val.Len() == 0 {
158		return ""
159	} else if val.Kind() == reflect.Slice && val.Len() == 0 {
160		return ""
161	}
162
163	bytes, err := yaml.Marshal(t.I)
164	if err != nil {
165		return fmt.Sprintf("<serialization error> : %#v", t.I)
166	}
167
168	return strings.TrimSpace(string(bytes))
169}
170func (t ValueInterface) Value() Value            { return t }
171func (t ValueInterface) Compare(other Value) int { panic("Never called") }
172
173func (t ValueError) Value() Value            { return t }
174func (t ValueError) Compare(other Value) int { panic("Never called") }
175
176func (t ValueNone) String() string          { return "" }
177func (t ValueNone) Value() Value            { return t }
178func (t ValueNone) Compare(other Value) int { panic("Never called") }
179
180func NewValueFmt(v Value, error bool) ValueFmt { return ValueFmt{V: v, Error: error} }
181
182func (t ValueFmt) String() string          { return t.V.String() }
183func (t ValueFmt) Value() Value            { return t.V }
184func (t ValueFmt) Compare(other Value) int { panic("Never called") }
185
186func (t ValueFmt) Fprintf(w io.Writer, pattern string, rest ...interface{}) (int, error) {
187	if t.Func == nil {
188		return fmt.Fprintf(w, pattern, rest...)
189	}
190	return fmt.Fprintf(w, "%s", t.Func(pattern, rest...))
191}
192
193func NewValueSuffix(v Value, s string) ValueSuffix { return ValueSuffix{V: v, Suffix: s} }
194
195func (t ValueSuffix) String() string {
196	str := t.V.String()
197	if len(str) > 0 {
198		return str + t.Suffix
199	}
200
201	return ""
202}
203
204func (t ValueSuffix) Value() Value            { return t.V }
205func (t ValueSuffix) Compare(other Value) int { panic("Never called") }
206