package rrdformat import ( "encoding" "fmt" "git.lukeshu.com/go/librrd/rrdformat/rrdbinary" ) type RRD struct { Architecture rrdbinary.Architecture `xml:"-"` Data RRDv0005 `xml:",innerxml"` } func (rrd *RRD) UnmarshalBinary(data []byte) error { arch, err := SniffArchitecture(data) if err != nil { return err } decoder := rrdbinary.NewDecoder(arch, data) var parsed RRDv0005 if err := decoder.Decode(&parsed.Header, ""); err != nil { return fmt.Errorf("field %s: %w", "Header", err) } // allocate memory based on .Header values parsed.DSDefs = make([]DSDef, parsed.Header.DSCnt) parsed.RRADefs = make([]RRADef, parsed.Header.RRACnt) parsed.PDPPreps = make([]PDPPrep, parsed.Header.DSCnt) parsed.CDPPreps = make([]CDPPrep, parsed.Header.DSCnt*parsed.Header.RRACnt) parsed.RRAPtrs = make([]RRAPtr, parsed.Header.RRACnt) // resume decoding if err := decoder.Decode(&parsed.DSDefs, ""); err != nil { return fmt.Errorf("field %s: %w", "DSDefs", err) } if err := decoder.Decode(&parsed.RRADefs, ""); err != nil { return fmt.Errorf("field %s: %w", "RRADefs", err) } // allocate memory based on .RRADefs val_cnt := 0 for i := range parsed.RRADefs { val_cnt += int(parsed.RRADefs[i].RowCnt * parsed.Header.DSCnt) } vals := make([]Value, val_cnt) parsed.Values = vals // set up some of pointers for rra_i := range parsed.RRADefs { parsed.RRADefs[rra_i].CDPPrep = &parsed.CDPPreps[rra_i] parsed.RRADefs[rra_i].Database = make([][]Value, parsed.RRADefs[rra_i].RowCnt) for row_i := 0; row_i < int(parsed.RRADefs[rra_i].RowCnt); row_i++ { parsed.RRADefs[rra_i].Database[row_i] = vals[:parsed.Header.DSCnt] vals = vals[parsed.Header.DSCnt:] } } // resume decoding var lastUpdatedPtr interface{} switch parsed.Header.Version { case "0001", "0002": lastUpdatedPtr = &parsed.LastUpdated.Sec case "0003", "0004", "0005": lastUpdatedPtr = &parsed.LastUpdated default: // version number already validated by SniffArchitecture panic("should not happen") } if err := decoder.Decode(lastUpdatedPtr, ""); err != nil { return fmt.Errorf("field %s: %w", "LastUpdated", err) } if err := decoder.Decode(&parsed.PDPPreps, ""); err != nil { return fmt.Errorf("field %s: %w", "PDPPreps", err) } if err := decoder.Decode(&parsed.CDPPreps, ""); err != nil { return fmt.Errorf("field %s: %w", "CDPPreps", err) } if err := decoder.Decode(&parsed.RRAPtrs, ""); err != nil { return fmt.Errorf("field %s: %w", "RRAPtrs", err) } if err := decoder.Decode(&parsed.Values, ""); err != nil { return fmt.Errorf("field %s: %w", "Values", err) } if err := decoder.Decode(&rrdbinary.EOF{}, ""); err != nil { return fmt.Errorf("field %s: %w", "EOF", err) } *rrd = RRD{ Architecture: arch, Data: parsed, } return nil } //var _ encoding.BinaryMarshaler = &RRD{} var _ encoding.BinaryUnmarshaler = &RRD{}