package helpers import ( "fmt" "sync" "github.com/fxamacker/cbor/v2" ) var ( //nolint:gochecknoglobals // 使用 sync.Once 模式需要全局变量来确保单次初始化 canonicalEncModeOnce sync.Once canonicalEncMode cbor.EncMode //nolint:gochecknoglobals // 使用 sync.Once 模式需要全局变量来确保单次初始化 errCanonicalEncMode error ) // getCanonicalEncMode 获取 Canonical CBOR 编码模式。 // 使用 Canonical CBOR 编码模式,确保序列化结果的一致性。 // Canonical CBOR 遵循 RFC 7049 Section 3.9,保证相同数据在不同实现间产生相同的字节序列。 // 使用 TimeRFC3339Nano 模式确保 time.Time 的纳秒精度被完整保留。 func getCanonicalEncMode() (cbor.EncMode, error) { canonicalEncModeOnce.Do(func() { opts := cbor.CanonicalEncOptions() // 设置时间编码模式为 RFC3339Nano,以保留纳秒精度 opts.Time = cbor.TimeRFC3339Nano canonicalEncMode, errCanonicalEncMode = opts.EncMode() if errCanonicalEncMode != nil { errCanonicalEncMode = fmt.Errorf("failed to create canonical CBOR encoder: %w", errCanonicalEncMode) } }) return canonicalEncMode, errCanonicalEncMode } // MarshalCanonical 使用 Canonical CBOR 编码序列化数据。 // 确保相同数据在不同实现间产生相同的字节序列,适用于需要确定性序列化的场景。 func MarshalCanonical(v interface{}) ([]byte, error) { encMode, err := getCanonicalEncMode() if err != nil { return nil, err } return encMode.Marshal(v) } // Unmarshal 反序列化 CBOR 数据。 // 支持标准 CBOR 和 Canonical CBOR 格式。 func Unmarshal(data []byte, v interface{}) error { return cbor.Unmarshal(data, v) }