go-hep.org/x/hep@v0.40.0/hbook/ann.go (about) 1 // Copyright ©2020 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package hbook 6 7 import ( 8 "bufio" 9 "bytes" 10 "encoding/gob" 11 "fmt" 12 "io" 13 "sort" 14 "strings" 15 16 "gopkg.in/yaml.v3" 17 ) 18 19 // Annotation is a bag of attributes that are attached to a histogram. 20 type Annotation map[string]any 21 22 func (ann Annotation) clone() Annotation { 23 buf := new(bytes.Buffer) 24 err := gob.NewEncoder(buf).Encode(&ann) 25 if err != nil { 26 panic(err) 27 } 28 out := make(Annotation, len(ann)) 29 err = gob.NewDecoder(buf).Decode(&out) 30 if err != nil { 31 panic(err) 32 } 33 return out 34 } 35 36 // MarshalYODA implements the YODAMarshaler interface. 37 func (ann Annotation) MarshalYODA() ([]byte, error) { 38 return ann.marshalYODAv2() 39 } 40 41 // marshalYODAv1 implements the YODAMarshaler interface. 42 func (ann Annotation) marshalYODAv1() ([]byte, error) { 43 keys := make([]string, 0, len(ann)) 44 for k := range ann { 45 if k == "" { 46 continue 47 } 48 keys = append(keys, k) 49 } 50 sort.Strings(keys) 51 buf := new(bytes.Buffer) 52 for _, k := range keys { 53 fmt.Fprintf(buf, "%s=%v\n", k, ann[k]) 54 } 55 return buf.Bytes(), nil 56 } 57 58 // marshalYODAv2 implements the YODAMarshaler interface. 59 func (ann Annotation) marshalYODAv2() ([]byte, error) { 60 return yaml.Marshal(ann) 61 } 62 63 // UnmarshalYODA implements the YODAUnmarshaler interface. 64 func (ann *Annotation) UnmarshalYODA(data []byte) error { 65 return ann.unmarshalYODAv2(data) 66 } 67 68 // unmarshalYODAv1 unmarshal YODA v1. 69 func (ann *Annotation) unmarshalYODAv1(data []byte) error { 70 var err error 71 s := bufio.NewScanner(bytes.NewReader(data)) 72 for s.Scan() { 73 txt := s.Text() 74 k, v, _ := strings.Cut(txt, "=") 75 (*ann)[k] = v 76 } 77 err = s.Err() 78 if err == io.EOF { 79 err = nil 80 } 81 return err 82 } 83 84 // unmarshalYODAv2 unmarshal YODA v2. 85 func (ann *Annotation) unmarshalYODAv2(data []byte) error { 86 return yaml.Unmarshal(data, ann) 87 } 88 89 // MarshalBinary implements encoding.BinaryMarshaler 90 func (ann *Annotation) MarshalBinary() ([]byte, error) { 91 var v map[string]any = *ann 92 buf := new(bytes.Buffer) 93 err := gob.NewEncoder(buf).Encode(v) 94 return buf.Bytes(), err 95 } 96 97 // UnmarshalBinary implements encoding.BinaryUnmarshaler 98 func (ann *Annotation) UnmarshalBinary(data []byte) error { 99 var v = make(map[string]any) 100 buf := bytes.NewReader(data) 101 err := gob.NewDecoder(buf).Decode(&v) 102 if err != nil { 103 return err 104 } 105 *ann = Annotation(v) 106 return nil 107 }