summaryrefslogtreecommitdiffhomepage
path: root/util/syspolicy/setting/summary.go
blob: 4cb15c7c4d0788f03d5f03626c62e4254cfa8091 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause

package setting

import (
	jsonv2 "github.com/go-json-experiment/json"
	"github.com/go-json-experiment/json/jsontext"
	"tailscale.com/types/opt"
)

// Summary is an immutable [PolicyScope] and [Origin].
type Summary struct {
	data summary
}

type summary struct {
	Scope  opt.Value[PolicyScope] `json:",omitzero"`
	Origin opt.Value[Origin]      `json:",omitzero"`
}

// SummaryWith returns a [Summary] with the specified options.
func SummaryWith(opts ...SummaryOption) Summary {
	var summary Summary
	for _, o := range opts {
		o.applySummaryOption(&summary)
	}
	return summary
}

// IsEmpty reports whether s is empty.
func (s Summary) IsEmpty() bool {
	return s == Summary{}
}

// Scope reports the [PolicyScope] in s.
func (s Summary) Scope() opt.Value[PolicyScope] {
	return s.data.Scope
}

// Origin reports the [Origin] in s.
func (s Summary) Origin() opt.Value[Origin] {
	return s.data.Origin
}

// String implements [fmt.Stringer].
func (s Summary) String() string {
	if s.IsEmpty() {
		return "{Empty}"
	}
	if origin, ok := s.data.Origin.GetOk(); ok {
		return origin.String()
	}
	return s.data.Scope.String()
}

var (
	_ jsonv2.MarshalerTo     = (*Summary)(nil)
	_ jsonv2.UnmarshalerFrom = (*Summary)(nil)
)

// MarshalJSONTo implements [jsonv2.MarshalerTo].
func (s Summary) MarshalJSONTo(out *jsontext.Encoder) error {
	return jsonv2.MarshalEncode(out, &s.data)
}

// UnmarshalJSONFrom implements [jsonv2.UnmarshalerFrom].
func (s *Summary) UnmarshalJSONFrom(in *jsontext.Decoder) error {
	return jsonv2.UnmarshalDecode(in, &s.data)
}

// MarshalJSON implements [json.Marshaler].
func (s Summary) MarshalJSON() ([]byte, error) {
	return jsonv2.Marshal(s) // uses MarshalJSONTo
}

// UnmarshalJSON implements [json.Unmarshaler].
func (s *Summary) UnmarshalJSON(b []byte) error {
	return jsonv2.Unmarshal(b, s) // uses UnmarshalJSONFrom
}

// SummaryOption is an option that configures [Summary]
// The following are allowed options:
//
//   - [Summary]
//   - [PolicyScope]
//   - [Origin]
type SummaryOption interface {
	applySummaryOption(summary *Summary)
}

func (s PolicyScope) applySummaryOption(summary *Summary) {
	summary.data.Scope.Set(s)
}

func (o Origin) applySummaryOption(summary *Summary) {
	summary.data.Origin.Set(o)
	if !summary.data.Scope.IsSet() {
		summary.data.Scope.Set(o.Scope())
	}
}

func (s Summary) applySummaryOption(summary *Summary) {
	*summary = s
}