File: modifier.go

package info (click to toggle)
golang-github-joomcode-errorx 1.2.0-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 280 kB
  • sloc: makefile: 2
file content (98 lines) | stat: -rw-r--r-- 2,514 bytes parent folder | download
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
package errorx

// TypeModifier is a way to change a default behaviour for an error type, directly or via type hierarchy.
// Modification is intentionally one-way, as it provides much more clarity.
// If there is a modifier on a type or a namespace, all its descendants definitely have the same default behaviour.
// If some of a subtypes must lack a specific modifier, then the modifier must be removed from the common ancestor.
type TypeModifier int

const (
	// TypeModifierTransparent is a type modifier; an error type with such modifier creates transparent wrappers by default
	TypeModifierTransparent TypeModifier = 1
	// TypeModifierOmitStackTrace is a type modifier; an error type with such modifier omits the stack trace collection upon creation of an error instance
	TypeModifierOmitStackTrace TypeModifier = 2
)

type modifiers interface {
	CollectStackTrace() bool
	Transparent() bool
	ReplaceWith(new modifiers) modifiers
}

var _ modifiers = noModifiers{}
var _ modifiers = typeModifiers{}
var _ modifiers = inheritedModifiers{}

type noModifiers struct {
}

func (noModifiers) CollectStackTrace() bool {
	return true
}

func (noModifiers) Transparent() bool {
	return false
}

func (noModifiers) ReplaceWith(new modifiers) modifiers {
	return new
}

type typeModifiers struct {
	omitStackTrace bool
	transparent    bool
}

func newTypeModifiers(modifiers ...TypeModifier) modifiers {
	m := typeModifiers{}
	for _, modifier := range modifiers {
		switch modifier {
		case TypeModifierOmitStackTrace:
			m.omitStackTrace = true
		case TypeModifierTransparent:
			m.transparent = true
		}
	}
	return m
}

func (m typeModifiers) CollectStackTrace() bool {
	return !m.omitStackTrace
}

func (m typeModifiers) Transparent() bool {
	return m.transparent
}

func (typeModifiers) ReplaceWith(new modifiers) modifiers {
	panic("attempt to modify type modifiers the second time")
}

type inheritedModifiers struct {
	parent   modifiers
	override modifiers
}

func newInheritedModifiers(modifiers modifiers) modifiers {
	if _, ok := modifiers.(noModifiers); ok {
		return noModifiers{}
	}

	return inheritedModifiers{
		parent:   modifiers,
		override: noModifiers{},
	}
}

func (m inheritedModifiers) CollectStackTrace() bool {
	return m.parent.CollectStackTrace() && m.override.CollectStackTrace()
}

func (m inheritedModifiers) Transparent() bool {
	return m.parent.Transparent() || m.override.Transparent()
}

func (m inheritedModifiers) ReplaceWith(new modifiers) modifiers {
	m.override = new
	return m
}