summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-kv/v2/format/struct.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/codeberg.org/gruf/go-kv/v2/format/struct.go')
-rw-r--r--vendor/codeberg.org/gruf/go-kv/v2/format/struct.go173
1 files changed, 173 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-kv/v2/format/struct.go b/vendor/codeberg.org/gruf/go-kv/v2/format/struct.go
new file mode 100644
index 000000000..cc1c8634d
--- /dev/null
+++ b/vendor/codeberg.org/gruf/go-kv/v2/format/struct.go
@@ -0,0 +1,173 @@
+package format
+
+// field stores the minimum necessary
+// data for iterating and formatting
+// each field in a given struct.
+type field struct {
+ format FormatFunc
+ name string
+ offset uintptr
+}
+
+// iterStructType returns a FormatFunc capable of iterating
+// and formatting the given struct type currently in typenode{}.
+// note this will fetch sub-FormatFuncs for each struct field.
+func (fmt *Formatter) iterStructType(t typenode) FormatFunc {
+ // Number of struct fields.
+ n := t.rtype.NumField()
+
+ // Gather format functions.
+ fields := make([]field, n)
+ for i := 0; i < n; i++ {
+
+ // Get struct field at index.
+ sfield := t.rtype.Field(i)
+ rtype := sfield.Type
+
+ // Get nested field typenode with appropriate flags.
+ flags := reflect_struct_field_flags(t.flags, rtype)
+ ft := t.next(sfield.Type, flags)
+
+ // Get field format func.
+ fn := fmt.loadOrGet(ft)
+ if fn == nil {
+ panic("unreachable")
+ }
+
+ // Set field info.
+ fields[i] = field{
+ format: fn,
+ name: sfield.Name,
+ offset: sfield.Offset,
+ }
+ }
+
+ // Handle no. fields.
+ switch len(fields) {
+ case 0:
+ return emptyStructType(t)
+ case 1:
+ return iterSingleFieldStructType(t, fields[0])
+ default:
+ return iterMultiFieldStructType(t, fields)
+ }
+}
+
+func emptyStructType(t typenode) FormatFunc {
+ if !t.needs_typestr() {
+ return func(s *State) {
+ // Append empty object.
+ s.B = append(s.B, "{}"...)
+ }
+ }
+
+ // Struct type string with refs.
+ typestr := t.typestr_with_refs()
+
+ // Append empty object
+ // with type information.
+ return func(s *State) {
+ if s.A.WithType() {
+ s.B = append(s.B, typestr...)
+ }
+ s.B = append(s.B, "{}"...)
+ }
+}
+
+func iterSingleFieldStructType(t typenode, field field) FormatFunc {
+ if field.format == nil {
+ panic("nil func")
+ }
+
+ if !t.needs_typestr() {
+ return func(s *State) {
+ // Wrap 'fn' with braces + field name.
+ s.B = append(s.B, "{"+field.name+"="...)
+ field.format(s)
+ s.B = append(s.B, "}"...)
+ }
+ }
+
+ // Struct type string with refs.
+ typestr := t.typestr_with_refs()
+
+ return func(s *State) {
+ // Include type info.
+ if s.A.WithType() {
+ s.B = append(s.B, typestr...)
+ }
+
+ // Wrap 'fn' with braces + field name.
+ s.B = append(s.B, "{"+field.name+"="...)
+ field.format(s)
+ s.B = append(s.B, "}"...)
+ }
+}
+
+func iterMultiFieldStructType(t typenode, fields []field) FormatFunc {
+ for _, field := range fields {
+ if field.format == nil {
+ panic("nil func")
+ }
+ }
+
+ if !t.needs_typestr() {
+ return func(s *State) {
+ ptr := s.P
+
+ // Prepend object brace.
+ s.B = append(s.B, '{')
+
+ for i := 0; i < len(fields); i++ {
+ // Get struct field ptr via offset.
+ s.P = add(ptr, fields[i].offset)
+
+ // Append field name and value separator.
+ s.B = append(s.B, fields[i].name+"="...)
+
+ // Format i'th field.
+ fields[i].format(s)
+ s.B = append(s.B, ',', ' ')
+ }
+
+ // Drop final ", ".
+ s.B = s.B[:len(s.B)-2]
+
+ // Append object brace.
+ s.B = append(s.B, '}')
+ }
+ }
+
+ // Struct type string with refs.
+ typestr := t.typestr_with_refs()
+
+ return func(s *State) {
+ ptr := s.P
+
+ // Include type info.
+ if s.A.WithType() {
+ s.B = append(s.B, typestr...)
+ }
+
+ // Prepend object brace.
+ s.B = append(s.B, '{')
+
+ for i := 0; i < len(fields); i++ {
+ // Get struct field ptr via offset.
+ s.P = add(ptr, fields[i].offset)
+
+ // Append field name and value separator.
+ s.B = append(s.B, fields[i].name+"="...)
+
+ // Format i'th field.
+ fields[i].format(s)
+ s.B = append(s.B, ',', ' ')
+ }
+
+ // Drop final ", ".
+ s.B = s.B[:len(s.B)-2]
+
+ // Append object brace.
+ s.B = append(s.B, '}')
+ }
+}