summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-mangler/helpers.go
blob: 6658fbef40e11c16f5e37fc2cab31e15516e9912 (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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package mangler

import (
	"reflect"
	"unsafe"
)

type (
	// serializing interfacing types.
	stringer        interface{ String() string }
	binarymarshaler interface{ MarshalBinary() ([]byte, error) }
	textmarshaler   interface{ MarshalText() ([]byte, error) }
	jsonmarshaler   interface{ MarshalJSON() ([]byte, error) }
)

func append_uint16(b []byte, u uint16) []byte {
	return append(b, // LE
		byte(u),
		byte(u>>8),
	)
}

func append_uint32(b []byte, u uint32) []byte {
	return append(b, // LE
		byte(u),
		byte(u>>8),
		byte(u>>16),
		byte(u>>24),
	)
}

func append_uint64(b []byte, u uint64) []byte {
	return append(b, // LE
		byte(u),
		byte(u>>8),
		byte(u>>16),
		byte(u>>24),
		byte(u>>32),
		byte(u>>40),
		byte(u>>48),
		byte(u>>56),
	)
}

func deref_ptr_mangler(mangle Mangler, count int) rMangler {
	return func(buf []byte, v reflect.Value) []byte {
		for i := 0; i < count; i++ {
			// Check for nil
			if v.IsNil() {
				buf = append(buf, '0')
				return buf
			}

			// Further deref ptr
			buf = append(buf, '1')
			v = v.Elem()
		}

		// Mangle fully deref'd ptr
		return mangle(buf, v.Interface())
	}
}

func deref_ptr_rmangler(mangle rMangler, count int) rMangler {
	return func(buf []byte, v reflect.Value) []byte {
		for i := 0; i < count; i++ {
			// Check for nil
			if v.IsNil() {
				buf = append(buf, '0')
				return buf
			}

			// Further deref ptr
			buf = append(buf, '1')
			v = v.Elem()
		}

		// Mangle fully deref'd ptr
		return mangle(buf, v)
	}
}

func array_to_slice_mangler(mangle Mangler) rMangler {
	return func(buf []byte, v reflect.Value) []byte {
		// Get slice of whole array
		v = v.Slice(0, v.Len())

		// Mangle as known slice type
		return mangle(buf, v.Interface())
	}
}

func iter_array_mangler(mangle Mangler) rMangler {
	return func(buf []byte, v reflect.Value) []byte {
		n := v.Len()
		for i := 0; i < n; i++ {
			buf = mangle(buf, v.Index(i).Interface())
			buf = append(buf, ',')
		}
		if n > 0 {
			buf = buf[:len(buf)-1]
		}
		return buf
	}
}

func iter_array_rmangler(mangle rMangler) rMangler {
	return func(buf []byte, v reflect.Value) []byte {
		n := v.Len()
		for i := 0; i < n; i++ {
			buf = mangle(buf, v.Index(i))
			buf = append(buf, ',')
		}
		if n > 0 {
			buf = buf[:len(buf)-1]
		}
		return buf
	}
}

func iter_map_rmangler(kMangle, vMangle rMangler) rMangler {
	return func(buf []byte, v reflect.Value) []byte {
		r := v.MapRange()
		for r.Next() {
			buf = kMangle(buf, r.Key())
			buf = append(buf, ':')
			buf = vMangle(buf, r.Value())
			buf = append(buf, ',')
		}
		if v.Len() > 0 {
			buf = buf[:len(buf)-1]
		}
		return buf
	}
}

// iface_value returns the raw value ptr for input boxed within interface{} type.
func iface_value(a any) unsafe.Pointer {
	type eface struct {
		Type  unsafe.Pointer
		Value unsafe.Pointer
	}
	return (*eface)(unsafe.Pointer(&a)).Value
}