File: encode_map.go

package info (click to toggle)
golang-github-fxamacker-cbor 2.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, sid, trixie
  • size: 1,716 kB
  • sloc: makefile: 2
file content (92 lines) | stat: -rw-r--r-- 1,844 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
// Copyright (c) Faye Amacker. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

package cbor

import (
	"bytes"
	"reflect"
	"sync"
)

type mapKeyValueEncodeFunc struct {
	kf, ef       encodeFunc
	kpool, vpool sync.Pool
}

func (me *mapKeyValueEncodeFunc) encodeKeyValues(e *bytes.Buffer, em *encMode, v reflect.Value, kvs []keyValue) error {
	iterk := me.kpool.Get().(*reflect.Value)
	defer func() {
		iterk.SetZero()
		me.kpool.Put(iterk)
	}()
	iterv := me.vpool.Get().(*reflect.Value)
	defer func() {
		iterv.SetZero()
		me.vpool.Put(iterv)
	}()

	if kvs == nil {
		for i, iter := 0, v.MapRange(); iter.Next(); i++ {
			iterk.SetIterKey(iter)
			iterv.SetIterValue(iter)

			if err := me.kf(e, em, *iterk); err != nil {
				return err
			}
			if err := me.ef(e, em, *iterv); err != nil {
				return err
			}
		}
		return nil
	}

	initial := e.Len()
	for i, iter := 0, v.MapRange(); iter.Next(); i++ {
		iterk.SetIterKey(iter)
		iterv.SetIterValue(iter)

		offset := e.Len()
		if err := me.kf(e, em, *iterk); err != nil {
			return err
		}
		valueOffset := e.Len()
		if err := me.ef(e, em, *iterv); err != nil {
			return err
		}
		kvs[i] = keyValue{
			offset:      offset - initial,
			valueOffset: valueOffset - initial,
			nextOffset:  e.Len() - initial,
		}
	}

	return nil
}

func getEncodeMapFunc(t reflect.Type) encodeFunc {
	kf, _, _ := getEncodeFunc(t.Key())
	ef, _, _ := getEncodeFunc(t.Elem())
	if kf == nil || ef == nil {
		return nil
	}
	mkv := &mapKeyValueEncodeFunc{
		kf: kf,
		ef: ef,
		kpool: sync.Pool{
			New: func() any {
				rk := reflect.New(t.Key()).Elem()
				return &rk
			},
		},
		vpool: sync.Pool{
			New: func() any {
				rv := reflect.New(t.Elem()).Elem()
				return &rv
			},
		},
	}
	return mapEncodeFunc{
		e: mkv.encodeKeyValues,
	}.encode
}