1package ansi
2
3import (
4 "image/color"
5 "strconv"
6 "strings"
7)
8
9// ResetStyle is a SGR (Select Graphic Rendition) style sequence that resets
10// all attributes.
11// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
12const ResetStyle = "\x1b[m"
13
14// Attr is a SGR (Select Graphic Rendition) style attribute.
15type Attr = int
16
17// Style represents an ANSI SGR (Select Graphic Rendition) style.
18type Style []string
19
20// NewStyle returns a new style with the given attributes.
21func NewStyle(attrs ...Attr) Style {
22 if len(attrs) == 0 {
23 return Style{}
24 }
25 s := make(Style, 0, len(attrs))
26 for _, a := range attrs {
27 attr, ok := attrStrings[a]
28 if ok {
29 s = append(s, attr)
30 } else {
31 if a < 0 {
32 a = 0
33 }
34 s = append(s, strconv.Itoa(a))
35 }
36 }
37 return s
38}
39
40// String returns the ANSI SGR (Select Graphic Rendition) style sequence for
41// the given style.
42func (s Style) String() string {
43 if len(s) == 0 {
44 return ResetStyle
45 }
46 return "\x1b[" + strings.Join(s, ";") + "m"
47}
48
49// Styled returns a styled string with the given style applied.
50func (s Style) Styled(str string) string {
51 if len(s) == 0 {
52 return str
53 }
54 return s.String() + str + ResetStyle
55}
56
57// Reset appends the reset style attribute to the style.
58func (s Style) Reset() Style {
59 return append(s, resetAttr)
60}
61
62// Bold appends the bold style attribute to the style.
63func (s Style) Bold() Style {
64 return append(s, boldAttr)
65}
66
67// Faint appends the faint style attribute to the style.
68func (s Style) Faint() Style {
69 return append(s, faintAttr)
70}
71
72// Italic appends the italic style attribute to the style.
73func (s Style) Italic() Style {
74 return append(s, italicAttr)
75}
76
77// Underline appends the underline style attribute to the style.
78func (s Style) Underline() Style {
79 return append(s, underlineAttr)
80}
81
82// UnderlineStyle appends the underline style attribute to the style.
83func (s Style) UnderlineStyle(u UnderlineStyle) Style {
84 switch u {
85 case NoUnderlineStyle:
86 return s.NoUnderline()
87 case SingleUnderlineStyle:
88 return s.Underline()
89 case DoubleUnderlineStyle:
90 return append(s, doubleUnderlineStyle)
91 case CurlyUnderlineStyle:
92 return append(s, curlyUnderlineStyle)
93 case DottedUnderlineStyle:
94 return append(s, dottedUnderlineStyle)
95 case DashedUnderlineStyle:
96 return append(s, dashedUnderlineStyle)
97 }
98 return s
99}
100
101// DoubleUnderline appends the double underline style attribute to the style.
102// This is a convenience method for UnderlineStyle(DoubleUnderlineStyle).
103func (s Style) DoubleUnderline() Style {
104 return s.UnderlineStyle(DoubleUnderlineStyle)
105}
106
107// CurlyUnderline appends the curly underline style attribute to the style.
108// This is a convenience method for UnderlineStyle(CurlyUnderlineStyle).
109func (s Style) CurlyUnderline() Style {
110 return s.UnderlineStyle(CurlyUnderlineStyle)
111}
112
113// DottedUnderline appends the dotted underline style attribute to the style.
114// This is a convenience method for UnderlineStyle(DottedUnderlineStyle).
115func (s Style) DottedUnderline() Style {
116 return s.UnderlineStyle(DottedUnderlineStyle)
117}
118
119// DashedUnderline appends the dashed underline style attribute to the style.
120// This is a convenience method for UnderlineStyle(DashedUnderlineStyle).
121func (s Style) DashedUnderline() Style {
122 return s.UnderlineStyle(DashedUnderlineStyle)
123}
124
125// SlowBlink appends the slow blink style attribute to the style.
126func (s Style) SlowBlink() Style {
127 return append(s, slowBlinkAttr)
128}
129
130// RapidBlink appends the rapid blink style attribute to the style.
131func (s Style) RapidBlink() Style {
132 return append(s, rapidBlinkAttr)
133}
134
135// Reverse appends the reverse style attribute to the style.
136func (s Style) Reverse() Style {
137 return append(s, reverseAttr)
138}
139
140// Conceal appends the conceal style attribute to the style.
141func (s Style) Conceal() Style {
142 return append(s, concealAttr)
143}
144
145// Strikethrough appends the strikethrough style attribute to the style.
146func (s Style) Strikethrough() Style {
147 return append(s, strikethroughAttr)
148}
149
150// NormalIntensity appends the normal intensity style attribute to the style.
151func (s Style) NormalIntensity() Style {
152 return append(s, normalIntensityAttr)
153}
154
155// NoItalic appends the no italic style attribute to the style.
156func (s Style) NoItalic() Style {
157 return append(s, noItalicAttr)
158}
159
160// NoUnderline appends the no underline style attribute to the style.
161func (s Style) NoUnderline() Style {
162 return append(s, noUnderlineAttr)
163}
164
165// NoBlink appends the no blink style attribute to the style.
166func (s Style) NoBlink() Style {
167 return append(s, noBlinkAttr)
168}
169
170// NoReverse appends the no reverse style attribute to the style.
171func (s Style) NoReverse() Style {
172 return append(s, noReverseAttr)
173}
174
175// NoConceal appends the no conceal style attribute to the style.
176func (s Style) NoConceal() Style {
177 return append(s, noConcealAttr)
178}
179
180// NoStrikethrough appends the no strikethrough style attribute to the style.
181func (s Style) NoStrikethrough() Style {
182 return append(s, noStrikethroughAttr)
183}
184
185// DefaultForegroundColor appends the default foreground color style attribute to the style.
186func (s Style) DefaultForegroundColor() Style {
187 return append(s, defaultForegroundColorAttr)
188}
189
190// DefaultBackgroundColor appends the default background color style attribute to the style.
191func (s Style) DefaultBackgroundColor() Style {
192 return append(s, defaultBackgroundColorAttr)
193}
194
195// DefaultUnderlineColor appends the default underline color style attribute to the style.
196func (s Style) DefaultUnderlineColor() Style {
197 return append(s, defaultUnderlineColorAttr)
198}
199
200// ForegroundColor appends the foreground color style attribute to the style.
201func (s Style) ForegroundColor(c Color) Style {
202 return append(s, foregroundColorString(c))
203}
204
205// BackgroundColor appends the background color style attribute to the style.
206func (s Style) BackgroundColor(c Color) Style {
207 return append(s, backgroundColorString(c))
208}
209
210// UnderlineColor appends the underline color style attribute to the style.
211func (s Style) UnderlineColor(c Color) Style {
212 return append(s, underlineColorString(c))
213}
214
215// UnderlineStyle represents an ANSI SGR (Select Graphic Rendition) underline
216// style.
217type UnderlineStyle = byte
218
219const (
220 doubleUnderlineStyle = "4:2"
221 curlyUnderlineStyle = "4:3"
222 dottedUnderlineStyle = "4:4"
223 dashedUnderlineStyle = "4:5"
224)
225
226const (
227 // NoUnderlineStyle is the default underline style.
228 NoUnderlineStyle UnderlineStyle = iota
229 // SingleUnderlineStyle is a single underline style.
230 SingleUnderlineStyle
231 // DoubleUnderlineStyle is a double underline style.
232 DoubleUnderlineStyle
233 // CurlyUnderlineStyle is a curly underline style.
234 CurlyUnderlineStyle
235 // DottedUnderlineStyle is a dotted underline style.
236 DottedUnderlineStyle
237 // DashedUnderlineStyle is a dashed underline style.
238 DashedUnderlineStyle
239)
240
241// SGR (Select Graphic Rendition) style attributes.
242// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
243const (
244 ResetAttr Attr = 0
245 BoldAttr Attr = 1
246 FaintAttr Attr = 2
247 ItalicAttr Attr = 3
248 UnderlineAttr Attr = 4
249 SlowBlinkAttr Attr = 5
250 RapidBlinkAttr Attr = 6
251 ReverseAttr Attr = 7
252 ConcealAttr Attr = 8
253 StrikethroughAttr Attr = 9
254 NormalIntensityAttr Attr = 22
255 NoItalicAttr Attr = 23
256 NoUnderlineAttr Attr = 24
257 NoBlinkAttr Attr = 25
258 NoReverseAttr Attr = 27
259 NoConcealAttr Attr = 28
260 NoStrikethroughAttr Attr = 29
261 BlackForegroundColorAttr Attr = 30
262 RedForegroundColorAttr Attr = 31
263 GreenForegroundColorAttr Attr = 32
264 YellowForegroundColorAttr Attr = 33
265 BlueForegroundColorAttr Attr = 34
266 MagentaForegroundColorAttr Attr = 35
267 CyanForegroundColorAttr Attr = 36
268 WhiteForegroundColorAttr Attr = 37
269 ExtendedForegroundColorAttr Attr = 38
270 DefaultForegroundColorAttr Attr = 39
271 BlackBackgroundColorAttr Attr = 40
272 RedBackgroundColorAttr Attr = 41
273 GreenBackgroundColorAttr Attr = 42
274 YellowBackgroundColorAttr Attr = 43
275 BlueBackgroundColorAttr Attr = 44
276 MagentaBackgroundColorAttr Attr = 45
277 CyanBackgroundColorAttr Attr = 46
278 WhiteBackgroundColorAttr Attr = 47
279 ExtendedBackgroundColorAttr Attr = 48
280 DefaultBackgroundColorAttr Attr = 49
281 ExtendedUnderlineColorAttr Attr = 58
282 DefaultUnderlineColorAttr Attr = 59
283 BrightBlackForegroundColorAttr Attr = 90
284 BrightRedForegroundColorAttr Attr = 91
285 BrightGreenForegroundColorAttr Attr = 92
286 BrightYellowForegroundColorAttr Attr = 93
287 BrightBlueForegroundColorAttr Attr = 94
288 BrightMagentaForegroundColorAttr Attr = 95
289 BrightCyanForegroundColorAttr Attr = 96
290 BrightWhiteForegroundColorAttr Attr = 97
291 BrightBlackBackgroundColorAttr Attr = 100
292 BrightRedBackgroundColorAttr Attr = 101
293 BrightGreenBackgroundColorAttr Attr = 102
294 BrightYellowBackgroundColorAttr Attr = 103
295 BrightBlueBackgroundColorAttr Attr = 104
296 BrightMagentaBackgroundColorAttr Attr = 105
297 BrightCyanBackgroundColorAttr Attr = 106
298 BrightWhiteBackgroundColorAttr Attr = 107
299
300 RGBColorIntroducerAttr Attr = 2
301 ExtendedColorIntroducerAttr Attr = 5
302)
303
304const (
305 resetAttr = "0"
306 boldAttr = "1"
307 faintAttr = "2"
308 italicAttr = "3"
309 underlineAttr = "4"
310 slowBlinkAttr = "5"
311 rapidBlinkAttr = "6"
312 reverseAttr = "7"
313 concealAttr = "8"
314 strikethroughAttr = "9"
315 normalIntensityAttr = "22"
316 noItalicAttr = "23"
317 noUnderlineAttr = "24"
318 noBlinkAttr = "25"
319 noReverseAttr = "27"
320 noConcealAttr = "28"
321 noStrikethroughAttr = "29"
322 blackForegroundColorAttr = "30"
323 redForegroundColorAttr = "31"
324 greenForegroundColorAttr = "32"
325 yellowForegroundColorAttr = "33"
326 blueForegroundColorAttr = "34"
327 magentaForegroundColorAttr = "35"
328 cyanForegroundColorAttr = "36"
329 whiteForegroundColorAttr = "37"
330 extendedForegroundColorAttr = "38"
331 defaultForegroundColorAttr = "39"
332 blackBackgroundColorAttr = "40"
333 redBackgroundColorAttr = "41"
334 greenBackgroundColorAttr = "42"
335 yellowBackgroundColorAttr = "43"
336 blueBackgroundColorAttr = "44"
337 magentaBackgroundColorAttr = "45"
338 cyanBackgroundColorAttr = "46"
339 whiteBackgroundColorAttr = "47"
340 extendedBackgroundColorAttr = "48"
341 defaultBackgroundColorAttr = "49"
342 extendedUnderlineColorAttr = "58"
343 defaultUnderlineColorAttr = "59"
344 brightBlackForegroundColorAttr = "90"
345 brightRedForegroundColorAttr = "91"
346 brightGreenForegroundColorAttr = "92"
347 brightYellowForegroundColorAttr = "93"
348 brightBlueForegroundColorAttr = "94"
349 brightMagentaForegroundColorAttr = "95"
350 brightCyanForegroundColorAttr = "96"
351 brightWhiteForegroundColorAttr = "97"
352 brightBlackBackgroundColorAttr = "100"
353 brightRedBackgroundColorAttr = "101"
354 brightGreenBackgroundColorAttr = "102"
355 brightYellowBackgroundColorAttr = "103"
356 brightBlueBackgroundColorAttr = "104"
357 brightMagentaBackgroundColorAttr = "105"
358 brightCyanBackgroundColorAttr = "106"
359 brightWhiteBackgroundColorAttr = "107"
360)
361
362// foregroundColorString returns the style SGR attribute for the given
363// foreground color.
364// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
365func foregroundColorString(c Color) string {
366 switch c := c.(type) {
367 case BasicColor:
368 // 3-bit or 4-bit ANSI foreground
369 // "3<n>" or "9<n>" where n is the color number from 0 to 7
370 switch c {
371 case Black:
372 return blackForegroundColorAttr
373 case Red:
374 return redForegroundColorAttr
375 case Green:
376 return greenForegroundColorAttr
377 case Yellow:
378 return yellowForegroundColorAttr
379 case Blue:
380 return blueForegroundColorAttr
381 case Magenta:
382 return magentaForegroundColorAttr
383 case Cyan:
384 return cyanForegroundColorAttr
385 case White:
386 return whiteForegroundColorAttr
387 case BrightBlack:
388 return brightBlackForegroundColorAttr
389 case BrightRed:
390 return brightRedForegroundColorAttr
391 case BrightGreen:
392 return brightGreenForegroundColorAttr
393 case BrightYellow:
394 return brightYellowForegroundColorAttr
395 case BrightBlue:
396 return brightBlueForegroundColorAttr
397 case BrightMagenta:
398 return brightMagentaForegroundColorAttr
399 case BrightCyan:
400 return brightCyanForegroundColorAttr
401 case BrightWhite:
402 return brightWhiteForegroundColorAttr
403 }
404 case ExtendedColor:
405 // 256-color ANSI foreground
406 // "38;5;<n>"
407 return "38;5;" + strconv.FormatUint(uint64(c), 10)
408 case TrueColor, color.Color:
409 // 24-bit "true color" foreground
410 // "38;2;<r>;<g>;<b>"
411 r, g, b, _ := c.RGBA()
412 return "38;2;" +
413 strconv.FormatUint(uint64(shift(r)), 10) + ";" +
414 strconv.FormatUint(uint64(shift(g)), 10) + ";" +
415 strconv.FormatUint(uint64(shift(b)), 10)
416 }
417 return defaultForegroundColorAttr
418}
419
420// backgroundColorString returns the style SGR attribute for the given
421// background color.
422// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
423func backgroundColorString(c Color) string {
424 switch c := c.(type) {
425 case BasicColor:
426 // 3-bit or 4-bit ANSI foreground
427 // "4<n>" or "10<n>" where n is the color number from 0 to 7
428 switch c {
429 case Black:
430 return blackBackgroundColorAttr
431 case Red:
432 return redBackgroundColorAttr
433 case Green:
434 return greenBackgroundColorAttr
435 case Yellow:
436 return yellowBackgroundColorAttr
437 case Blue:
438 return blueBackgroundColorAttr
439 case Magenta:
440 return magentaBackgroundColorAttr
441 case Cyan:
442 return cyanBackgroundColorAttr
443 case White:
444 return whiteBackgroundColorAttr
445 case BrightBlack:
446 return brightBlackBackgroundColorAttr
447 case BrightRed:
448 return brightRedBackgroundColorAttr
449 case BrightGreen:
450 return brightGreenBackgroundColorAttr
451 case BrightYellow:
452 return brightYellowBackgroundColorAttr
453 case BrightBlue:
454 return brightBlueBackgroundColorAttr
455 case BrightMagenta:
456 return brightMagentaBackgroundColorAttr
457 case BrightCyan:
458 return brightCyanBackgroundColorAttr
459 case BrightWhite:
460 return brightWhiteBackgroundColorAttr
461 }
462 case ExtendedColor:
463 // 256-color ANSI foreground
464 // "48;5;<n>"
465 return "48;5;" + strconv.FormatUint(uint64(c), 10)
466 case TrueColor, color.Color:
467 // 24-bit "true color" foreground
468 // "38;2;<r>;<g>;<b>"
469 r, g, b, _ := c.RGBA()
470 return "48;2;" +
471 strconv.FormatUint(uint64(shift(r)), 10) + ";" +
472 strconv.FormatUint(uint64(shift(g)), 10) + ";" +
473 strconv.FormatUint(uint64(shift(b)), 10)
474 }
475 return defaultBackgroundColorAttr
476}
477
478// underlineColorString returns the style SGR attribute for the given underline
479// color.
480// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
481func underlineColorString(c Color) string {
482 switch c := c.(type) {
483 // NOTE: we can't use 3-bit and 4-bit ANSI color codes with underline
484 // color, use 256-color instead.
485 //
486 // 256-color ANSI underline color
487 // "58;5;<n>"
488 case BasicColor:
489 return "58;5;" + strconv.FormatUint(uint64(c), 10)
490 case ExtendedColor:
491 return "58;5;" + strconv.FormatUint(uint64(c), 10)
492 case TrueColor, color.Color:
493 // 24-bit "true color" foreground
494 // "38;2;<r>;<g>;<b>"
495 r, g, b, _ := c.RGBA()
496 return "58;2;" +
497 strconv.FormatUint(uint64(shift(r)), 10) + ";" +
498 strconv.FormatUint(uint64(shift(g)), 10) + ";" +
499 strconv.FormatUint(uint64(shift(b)), 10)
500 }
501 return defaultUnderlineColorAttr
502}
503
504// ReadStyleColor decodes a color from a slice of parameters. It returns the
505// number of parameters read and the color. This function is used to read SGR
506// color parameters following the ITU T.416 standard.
507//
508// It supports reading the following color types:
509// - 0: implementation defined
510// - 1: transparent
511// - 2: RGB direct color
512// - 3: CMY direct color
513// - 4: CMYK direct color
514// - 5: indexed color
515// - 6: RGBA direct color (WezTerm extension)
516//
517// The parameters can be separated by semicolons (;) or colons (:). Mixing
518// separators is not allowed.
519//
520// The specs supports defining a color space id, a color tolerance value, and a
521// tolerance color space id. However, these values have no effect on the
522// returned color and will be ignored.
523//
524// This implementation includes a few modifications to the specs:
525// 1. Support for legacy color values separated by semicolons (;) with respect to RGB, and indexed colors
526// 2. Support ignoring and omitting the color space id (second parameter) with respect to RGB colors
527// 3. Support ignoring and omitting the 6th parameter with respect to RGB and CMY colors
528// 4. Support reading RGBA colors
529func ReadStyleColor(params Params, co *color.Color) (n int) {
530 if len(params) < 2 { // Need at least SGR type and color type
531 return 0
532 }
533
534 // First parameter indicates one of 38, 48, or 58 (foreground, background, or underline)
535 s := params[0]
536 p := params[1]
537 colorType := p.Param(0)
538 n = 2
539
540 paramsfn := func() (p1, p2, p3, p4 int) {
541 // Where should we start reading the color?
542 switch {
543 case s.HasMore() && p.HasMore() && len(params) > 8 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && params[5].HasMore() && params[6].HasMore() && params[7].HasMore():
544 // We have color space id, a 6th parameter, a tolerance value, and a tolerance color space
545 n += 7
546 return params[3].Param(0), params[4].Param(0), params[5].Param(0), params[6].Param(0)
547 case s.HasMore() && p.HasMore() && len(params) > 7 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && params[5].HasMore() && params[6].HasMore():
548 // We have color space id, a 6th parameter, and a tolerance value
549 n += 6
550 return params[3].Param(0), params[4].Param(0), params[5].Param(0), params[6].Param(0)
551 case s.HasMore() && p.HasMore() && len(params) > 6 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && params[5].HasMore():
552 // We have color space id and a 6th parameter
553 // 48 : 4 : : 1 : 2 : 3 :4
554 n += 5
555 return params[3].Param(0), params[4].Param(0), params[5].Param(0), params[6].Param(0)
556 case s.HasMore() && p.HasMore() && len(params) > 5 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && !params[5].HasMore():
557 // We have color space
558 // 48 : 3 : : 1 : 2 : 3
559 n += 4
560 return params[3].Param(0), params[4].Param(0), params[5].Param(0), -1
561 case s.HasMore() && p.HasMore() && p.Param(0) == 2 && params[2].HasMore() && params[3].HasMore() && !params[4].HasMore():
562 // We have color values separated by colons (:)
563 // 48 : 2 : 1 : 2 : 3
564 fallthrough
565 case !s.HasMore() && !p.HasMore() && p.Param(0) == 2 && !params[2].HasMore() && !params[3].HasMore() && !params[4].HasMore():
566 // Support legacy color values separated by semicolons (;)
567 // 48 ; 2 ; 1 ; 2 ; 3
568 n += 3
569 return params[2].Param(0), params[3].Param(0), params[4].Param(0), -1
570 }
571 // Ambiguous SGR color
572 return -1, -1, -1, -1
573 }
574
575 switch colorType {
576 case 0: // implementation defined
577 return 2
578 case 1: // transparent
579 *co = color.Transparent
580 return 2
581 case 2: // RGB direct color
582 if len(params) < 5 {
583 return 0
584 }
585
586 r, g, b, _ := paramsfn()
587 if r == -1 || g == -1 || b == -1 {
588 return 0
589 }
590
591 *co = color.RGBA{
592 R: uint8(r), //nolint:gosec
593 G: uint8(g), //nolint:gosec
594 B: uint8(b), //nolint:gosec
595 A: 0xff,
596 }
597 return
598
599 case 3: // CMY direct color
600 if len(params) < 5 {
601 return 0
602 }
603
604 c, m, y, _ := paramsfn()
605 if c == -1 || m == -1 || y == -1 {
606 return 0
607 }
608
609 *co = color.CMYK{
610 C: uint8(c), //nolint:gosec
611 M: uint8(m), //nolint:gosec
612 Y: uint8(y), //nolint:gosec
613 K: 0,
614 }
615 return
616
617 case 4: // CMYK direct color
618 if len(params) < 6 {
619 return 0
620 }
621
622 c, m, y, k := paramsfn()
623 if c == -1 || m == -1 || y == -1 || k == -1 {
624 return 0
625 }
626
627 *co = color.CMYK{
628 C: uint8(c), //nolint:gosec
629 M: uint8(m), //nolint:gosec
630 Y: uint8(y), //nolint:gosec
631 K: uint8(k), //nolint:gosec
632 }
633 return
634
635 case 5: // indexed color
636 if len(params) < 3 {
637 return 0
638 }
639 switch {
640 case s.HasMore() && p.HasMore() && !params[2].HasMore():
641 // Colon separated indexed color
642 // 38 : 5 : 234
643 case !s.HasMore() && !p.HasMore() && !params[2].HasMore():
644 // Legacy semicolon indexed color
645 // 38 ; 5 ; 234
646 default:
647 return 0
648 }
649 *co = ExtendedColor(params[2].Param(0)) //nolint:gosec
650 return 3
651
652 case 6: // RGBA direct color
653 if len(params) < 6 {
654 return 0
655 }
656
657 r, g, b, a := paramsfn()
658 if r == -1 || g == -1 || b == -1 || a == -1 {
659 return 0
660 }
661
662 *co = color.RGBA{
663 R: uint8(r), //nolint:gosec
664 G: uint8(g), //nolint:gosec
665 B: uint8(b), //nolint:gosec
666 A: uint8(a), //nolint:gosec
667 }
668 return
669
670 default:
671 return 0
672 }
673}