metric_codecs.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // DO NOT MODIFY
  4. //
  5. // ┻━┻ ︵ヽ(`Д´)ノ︵ ┻━┻
  6. //
  7. //
  8. // This source file was automatically generated by bingen.
  9. //
  10. ////////////////////////////////////////////////////////////////////////////////
  11. package metric
  12. import (
  13. "fmt"
  14. "io"
  15. "iter"
  16. "os"
  17. "reflect"
  18. "strings"
  19. "sync"
  20. "time"
  21. bstream "github.com/opencost/bingen/pkg/stream"
  22. stringtable "github.com/opencost/bingen/pkg/table"
  23. util "github.com/opencost/bingen/pkg/util"
  24. )
  25. const (
  26. // GeneratorPackageName is the package the generator is targetting
  27. GeneratorPackageName string = "metric"
  28. // DefaultCodecVersion is used for any resources listed in the Default version set
  29. DefaultCodecVersion uint8 = 1
  30. )
  31. //--------------------------------------------------------------------------
  32. // Configuration
  33. //--------------------------------------------------------------------------
  34. var (
  35. bingenConfigLock sync.RWMutex
  36. bingenConfig *BingenConfiguration = DefaultBingenConfiguration()
  37. )
  38. // BingenConfiguration is used to set any custom configuration in the way files are encoded
  39. // or decoded.
  40. type BingenConfiguration struct {
  41. // FileBackedStringTableEnabled enables the use of file-backed string tables for streaming
  42. // bingen decoding.
  43. FileBackedStringTableEnabled bool
  44. // FileBackedStringTableDir is the directory to write the string table files for reading.
  45. FileBackedStringTableDir string
  46. // FileBackedStringTableMemoMaxBytes limits in-memory memoization for file-backed table lookups.
  47. // 0 disables memoization.
  48. FileBackedStringTableMemoMaxBytes int64
  49. }
  50. // DefaultBingenConfiguration creates the default implementation of the bingen configuration
  51. // and returns it.
  52. func DefaultBingenConfiguration() *BingenConfiguration {
  53. return &BingenConfiguration{
  54. FileBackedStringTableEnabled: false,
  55. FileBackedStringTableDir: os.TempDir(),
  56. FileBackedStringTableMemoMaxBytes: 0,
  57. }
  58. }
  59. // ConfigureBingen accepts a new *BingenConfiguration instance which updates the internal decoder
  60. // and encoder behavior.
  61. func ConfigureBingen(config *BingenConfiguration) {
  62. bingenConfigLock.Lock()
  63. defer bingenConfigLock.Unlock()
  64. if config == nil {
  65. config = DefaultBingenConfiguration()
  66. }
  67. bingenConfig = config
  68. }
  69. // IsBingenFileBackedStringTableEnabled accessor for file backed string table configuration
  70. func IsBingenFileBackedStringTableEnabled() bool {
  71. bingenConfigLock.RLock()
  72. defer bingenConfigLock.RUnlock()
  73. return bingenConfig.FileBackedStringTableEnabled
  74. }
  75. // BingenFileBackedStringTableDir returns the directory configured for file backed string tables.
  76. func BingenFileBackedStringTableDir() string {
  77. bingenConfigLock.RLock()
  78. defer bingenConfigLock.RUnlock()
  79. return bingenConfig.FileBackedStringTableDir
  80. }
  81. // BingenFileBackedStringTableMemoMaxBytes returns the maximum bytes used for file-backed memo cache.
  82. func BingenFileBackedStringTableMemoMaxBytes() int64 {
  83. bingenConfigLock.RLock()
  84. defer bingenConfigLock.RUnlock()
  85. return bingenConfig.FileBackedStringTableMemoMaxBytes
  86. }
  87. //--------------------------------------------------------------------------
  88. // Type Map
  89. //--------------------------------------------------------------------------
  90. // Generated type map for resolving interface implementations to to concrete types
  91. var typeMap map[string]reflect.Type = map[string]reflect.Type{
  92. "Update": reflect.TypeFor[Update](),
  93. "UpdateSet": reflect.TypeFor[UpdateSet](),
  94. }
  95. //--------------------------------------------------------------------------
  96. // Type Helpers
  97. //--------------------------------------------------------------------------
  98. // isBinaryTag returns true when the first bytes in the provided binary matches the tag
  99. func isBinaryTag(data []byte, tag string) bool {
  100. if len(data) < len(tag) {
  101. return false
  102. }
  103. return string(data[:len(tag)]) == tag
  104. }
  105. // isReaderBinaryTag is used to peek the header for an io.Reader Buffer
  106. func isReaderBinaryTag(buff *util.Buffer, tag string) bool {
  107. data, err := buff.Peek(len(tag))
  108. if err != nil && err != io.EOF {
  109. panic(fmt.Sprintf("called Peek() on a non buffered reader: %s", err))
  110. }
  111. if len(data) < len(tag) {
  112. return false
  113. }
  114. return string(data[:len(tag)]) == tag
  115. }
  116. // typeToString determines the basic properties of the type, the qualifier, package path, and
  117. // type name, and returns the qualified type
  118. func typeToString(f interface{}) string {
  119. qual := ""
  120. t := reflect.TypeOf(f)
  121. if t.Kind() == reflect.Ptr {
  122. t = t.Elem()
  123. qual = "*"
  124. }
  125. return fmt.Sprintf("%s%s.%s", qual, t.PkgPath(), t.Name())
  126. }
  127. // resolveType uses the name of a type and returns the package, base type name, and whether
  128. // or not it's a pointer.
  129. func resolveType(t string) (pkg string, name string, isPtr bool) {
  130. isPtr = t[:1] == "*"
  131. if isPtr {
  132. t = t[1:]
  133. }
  134. slashIndex := strings.LastIndex(t, "/")
  135. if slashIndex >= 0 {
  136. t = t[slashIndex+1:]
  137. }
  138. parts := strings.Split(t, ".")
  139. if parts[0] == GeneratorPackageName {
  140. parts[0] = ""
  141. }
  142. pkg = parts[0]
  143. name = parts[1]
  144. return
  145. }
  146. //--------------------------------------------------------------------------
  147. // Stream Helpers
  148. //--------------------------------------------------------------------------
  149. // StreamFactoryFunc is an alias for a func that creates a BingenStream implementation.
  150. type StreamFactoryFunc func(io.Reader) bstream.BingenStream
  151. // Generated streamable factory map for finding the specific new stream methods
  152. // by T type
  153. var streamFactoryMap map[reflect.Type]StreamFactoryFunc = map[reflect.Type]StreamFactoryFunc{
  154. reflect.TypeFor[UpdateSet](): NewUpdateSetStream,
  155. }
  156. // NewStreamFor accepts an io.Reader, and returns a new BingenStream for the generic T
  157. // type provided _if_ it is a registered bingen type that is annotated as 'streamable'. See
  158. // the streamFactoryMap for generated type listings.
  159. func NewStreamFor[T any](reader io.Reader) (bstream.BingenStream, error) {
  160. typeKey := reflect.TypeFor[T]()
  161. factory, ok := streamFactoryMap[typeKey]
  162. if !ok {
  163. return nil, fmt.Errorf("the type: %s is not a registered bingen streamable type", typeKey.Name())
  164. }
  165. return factory(reader), nil
  166. }
  167. //--------------------------------------------------------------------------
  168. // Codec Context
  169. //--------------------------------------------------------------------------
  170. // EncodingContext is a context object passed to the encoders to ensure reuse of buffer
  171. // and table data
  172. type EncodingContext struct {
  173. Buffer *util.Buffer
  174. Table stringtable.StringTableWriter
  175. }
  176. // NewEncodingContext creates a new EncodingContext instance that will create a new []byte buffer
  177. // for writing, and return the context
  178. func NewEncodingContext(tableWriter stringtable.StringTableWriter) *EncodingContext {
  179. return &EncodingContext{
  180. Buffer: util.NewBuffer(),
  181. Table: tableWriter,
  182. }
  183. }
  184. // NewEncodingContextFromWriter creates a new EncodingContext instance that will create a new Buffer
  185. // from the provided io.Writer and StringTableWriter.
  186. func NewEncodingContextFromWriter(writer io.Writer, tableWriter stringtable.StringTableWriter) *EncodingContext {
  187. return &EncodingContext{
  188. Buffer: util.NewBufferFromWriter(writer),
  189. Table: tableWriter,
  190. }
  191. }
  192. // NewEncodingContextFromBuffer creates a new EncodingContext instance that will leverage an existing
  193. // Buffer and StringTableWriter.
  194. func NewEncodingContextFromBuffer(buffer *util.Buffer, tableWriter stringtable.StringTableWriter) *EncodingContext {
  195. return &EncodingContext{
  196. Buffer: buffer,
  197. Table: tableWriter,
  198. }
  199. }
  200. // ToBytes returns the encoded string table bytes (if applicable) combined with the encoded buffer bytes. If
  201. // a string table is being used, the string table bytes will be written first to ensure correct ordering for
  202. // decoding.
  203. func (ec *EncodingContext) ToBytes() []byte {
  204. encBytes := ec.Buffer.Bytes()
  205. if ec.Table != nil {
  206. buff := util.NewBuffer()
  207. ec.Table.WriteTo(buff)
  208. buff.WriteBytes(encBytes)
  209. return buff.Bytes()
  210. }
  211. return encBytes
  212. }
  213. // IsStringTable returns true if the table is available
  214. func (ec *EncodingContext) IsStringTable() bool {
  215. return ec.Table != nil
  216. }
  217. // DecodingContext is a context object passed to the decoders to ensure parent objects
  218. // reuse as much data as possible
  219. type DecodingContext struct {
  220. Buffer *util.Buffer
  221. Table stringtable.StringTableReader
  222. }
  223. // NewDecodingContextFromBytes creates a new DecodingContext instance using an byte slice
  224. func NewDecodingContextFromBytes(data []byte) *DecodingContext {
  225. var table stringtable.StringTableReader
  226. buff := util.NewBufferFromBytes(data)
  227. // string table header validation
  228. if isBinaryTag(data, stringtable.BinaryTagStringTable) {
  229. buff.ReadBytes(len(stringtable.BinaryTagStringTable)) // strip tag length
  230. // always use a slice string table with a byte array since the
  231. // data is already in memory
  232. table = stringtable.NewSliceStringTableReaderFrom(buff)
  233. }
  234. return &DecodingContext{
  235. Buffer: buff,
  236. Table: table,
  237. }
  238. }
  239. // NewDecodingContextFromReader creates a new DecodingContext instance using an io.Reader
  240. // implementation
  241. func NewDecodingContextFromReader(reader io.Reader) *DecodingContext {
  242. var table stringtable.StringTableReader
  243. buff := util.NewBufferFromReader(reader)
  244. if isReaderBinaryTag(buff, stringtable.BinaryTagStringTable) {
  245. buff.ReadBytes(len(stringtable.BinaryTagStringTable)) // strip tag length
  246. // create correct string table implementation
  247. if IsBingenFileBackedStringTableEnabled() {
  248. table = stringtable.NewFileStringTableReaderFrom(buff, BingenFileBackedStringTableDir(), GeneratorPackageName, BingenFileBackedStringTableMemoMaxBytes())
  249. } else {
  250. table = stringtable.NewSliceStringTableReaderFrom(buff)
  251. }
  252. }
  253. return &DecodingContext{
  254. Buffer: buff,
  255. Table: table,
  256. }
  257. }
  258. // IsStringTable returns true if the table is available
  259. func (dc *DecodingContext) IsStringTable() bool {
  260. return dc.Table != nil && dc.Table.Len() > 0
  261. }
  262. // Close will ensure that any string table resources and buffer resources are
  263. // cleaned up.
  264. func (dc *DecodingContext) Close() {
  265. if dc.Table != nil {
  266. _ = dc.Table.Close()
  267. dc.Table = nil
  268. }
  269. }
  270. //--------------------------------------------------------------------------
  271. // Binary Codec
  272. //--------------------------------------------------------------------------
  273. // BinEncoder is an encoding interface which defines a context based marshal contract.
  274. type BinEncoder interface {
  275. MarshalBinaryWithContext(*EncodingContext) error
  276. }
  277. // BinDecoder is a decoding interface which defines a context based unmarshal contract.
  278. type BinDecoder interface {
  279. UnmarshalBinaryWithContext(*DecodingContext) error
  280. }
  281. //--------------------------------------------------------------------------
  282. // Update
  283. //--------------------------------------------------------------------------
  284. // MarshalBinary serializes the internal properties of this Update instance
  285. // into a byte array
  286. func (target *Update) MarshalBinary() (data []byte, err error) {
  287. ctx := NewEncodingContext(nil)
  288. e := target.MarshalBinaryWithContext(ctx)
  289. if e != nil {
  290. return nil, e
  291. }
  292. return ctx.ToBytes(), nil
  293. }
  294. // MarshalBinary serializes the internal properties of this Update instance
  295. // into an io.Writer.
  296. func (target *Update) MarshalBinaryTo(writer io.Writer) error {
  297. buff := util.NewBufferFromWriter(writer)
  298. defer buff.Flush()
  299. ctx := NewEncodingContextFromBuffer(buff, nil)
  300. return target.MarshalBinaryWithContext(ctx)
  301. }
  302. // MarshalBinaryWithContext serializes the internal properties of this Update instance
  303. // into a byte array leveraging a predefined context.
  304. func (target *Update) MarshalBinaryWithContext(ctx *EncodingContext) (err error) {
  305. // panics are recovered and propagated as errors
  306. defer func() {
  307. if r := recover(); r != nil {
  308. if e, ok := r.(error); ok {
  309. err = e
  310. } else if s, ok := r.(string); ok {
  311. err = fmt.Errorf("unexpected panic: %s", s)
  312. } else {
  313. err = fmt.Errorf("unexpected panic: %+v", r)
  314. }
  315. }
  316. }()
  317. buff := ctx.Buffer
  318. buff.WriteUInt8(DefaultCodecVersion) // version
  319. if ctx.IsStringTable() {
  320. a := ctx.Table.AddOrGet(target.Name)
  321. buff.WriteInt(a) // write table index
  322. } else {
  323. buff.WriteString(target.Name) // write string
  324. }
  325. if target.Labels == nil {
  326. buff.WriteUInt8(uint8(0)) // write nil byte
  327. } else {
  328. buff.WriteUInt8(uint8(1)) // write non-nil byte
  329. // --- [begin][write][map](map[string]string) ---
  330. buff.WriteInt(len(target.Labels)) // map length
  331. for v, z := range target.Labels {
  332. if ctx.IsStringTable() {
  333. b := ctx.Table.AddOrGet(v)
  334. buff.WriteInt(b) // write table index
  335. } else {
  336. buff.WriteString(v) // write string
  337. }
  338. if ctx.IsStringTable() {
  339. c := ctx.Table.AddOrGet(z)
  340. buff.WriteInt(c) // write table index
  341. } else {
  342. buff.WriteString(z) // write string
  343. }
  344. }
  345. // --- [end][write][map](map[string]string) ---
  346. }
  347. buff.WriteFloat64(target.Value) // write float64
  348. if target.AdditionalInfo == nil {
  349. buff.WriteUInt8(uint8(0)) // write nil byte
  350. } else {
  351. buff.WriteUInt8(uint8(1)) // write non-nil byte
  352. // --- [begin][write][map](map[string]string) ---
  353. buff.WriteInt(len(target.AdditionalInfo)) // map length
  354. for vv, zz := range target.AdditionalInfo {
  355. if ctx.IsStringTable() {
  356. d := ctx.Table.AddOrGet(vv)
  357. buff.WriteInt(d) // write table index
  358. } else {
  359. buff.WriteString(vv) // write string
  360. }
  361. if ctx.IsStringTable() {
  362. e := ctx.Table.AddOrGet(zz)
  363. buff.WriteInt(e) // write table index
  364. } else {
  365. buff.WriteString(zz) // write string
  366. }
  367. }
  368. // --- [end][write][map](map[string]string) ---
  369. }
  370. return nil
  371. }
  372. // UnmarshalBinary uses the data passed byte array to set all the internal properties of
  373. // the Update type
  374. func (target *Update) UnmarshalBinary(data []byte) error {
  375. ctx := NewDecodingContextFromBytes(data)
  376. defer ctx.Close()
  377. err := target.UnmarshalBinaryWithContext(ctx)
  378. if err != nil {
  379. return err
  380. }
  381. return nil
  382. }
  383. // UnmarshalBinaryFromReader uses the io.Reader data to set all the internal properties of
  384. // the Update type
  385. func (target *Update) UnmarshalBinaryFromReader(reader io.Reader) error {
  386. ctx := NewDecodingContextFromReader(reader)
  387. defer ctx.Close()
  388. err := target.UnmarshalBinaryWithContext(ctx)
  389. if err != nil {
  390. return err
  391. }
  392. return nil
  393. }
  394. // UnmarshalBinaryWithContext uses the context containing a string table and binary buffer to set all the internal properties of
  395. // the Update type
  396. func (target *Update) UnmarshalBinaryWithContext(ctx *DecodingContext) (err error) {
  397. // panics are recovered and propagated as errors
  398. defer func() {
  399. if r := recover(); r != nil {
  400. if e, ok := r.(error); ok {
  401. err = e
  402. } else if s, ok := r.(string); ok {
  403. err = fmt.Errorf("unexpected panic: %s", s)
  404. } else {
  405. err = fmt.Errorf("unexpected panic: %+v", r)
  406. }
  407. }
  408. }()
  409. buff := ctx.Buffer
  410. version := buff.ReadUInt8()
  411. if version > DefaultCodecVersion {
  412. return fmt.Errorf("Invalid Version Unmarshalling Update. Expected %d or less, got %d", DefaultCodecVersion, version)
  413. }
  414. var b string
  415. if ctx.IsStringTable() {
  416. c := buff.ReadInt() // read string index
  417. b = ctx.Table.At(c)
  418. } else {
  419. b = buff.ReadString() // read string
  420. }
  421. a := b
  422. target.Name = a
  423. if buff.ReadUInt8() == uint8(0) {
  424. target.Labels = nil
  425. } else {
  426. // --- [begin][read][map](map[string]string) ---
  427. e := buff.ReadInt() // map len
  428. d := make(map[string]string, e)
  429. for range e {
  430. var v string
  431. var g string
  432. if ctx.IsStringTable() {
  433. h := buff.ReadInt() // read string index
  434. g = ctx.Table.At(h)
  435. } else {
  436. g = buff.ReadString() // read string
  437. }
  438. f := g
  439. v = f
  440. var z string
  441. var m string
  442. if ctx.IsStringTable() {
  443. n := buff.ReadInt() // read string index
  444. m = ctx.Table.At(n)
  445. } else {
  446. m = buff.ReadString() // read string
  447. }
  448. l := m
  449. z = l
  450. d[v] = z
  451. }
  452. target.Labels = d
  453. // --- [end][read][map](map[string]string) ---
  454. }
  455. o := buff.ReadFloat64() // read float64
  456. target.Value = o
  457. if buff.ReadUInt8() == uint8(0) {
  458. target.AdditionalInfo = nil
  459. } else {
  460. // --- [begin][read][map](map[string]string) ---
  461. q := buff.ReadInt() // map len
  462. p := make(map[string]string, q)
  463. for range q {
  464. var vv string
  465. var s string
  466. if ctx.IsStringTable() {
  467. t := buff.ReadInt() // read string index
  468. s = ctx.Table.At(t)
  469. } else {
  470. s = buff.ReadString() // read string
  471. }
  472. r := s
  473. vv = r
  474. var zz string
  475. var w string
  476. if ctx.IsStringTable() {
  477. x := buff.ReadInt() // read string index
  478. w = ctx.Table.At(x)
  479. } else {
  480. w = buff.ReadString() // read string
  481. }
  482. u := w
  483. zz = u
  484. p[vv] = zz
  485. }
  486. target.AdditionalInfo = p
  487. // --- [end][read][map](map[string]string) ---
  488. }
  489. return nil
  490. }
  491. //--------------------------------------------------------------------------
  492. // UpdateSet
  493. //--------------------------------------------------------------------------
  494. // MarshalBinary serializes the internal properties of this UpdateSet instance
  495. // into a byte array
  496. func (target *UpdateSet) MarshalBinary() (data []byte, err error) {
  497. ctx := NewEncodingContext(stringtable.NewIndexedStringTableWriter())
  498. e := target.MarshalBinaryWithContext(ctx)
  499. if e != nil {
  500. return nil, e
  501. }
  502. return ctx.ToBytes(), nil
  503. }
  504. // MarshalBinary serializes the internal properties of this UpdateSet instance
  505. // into an io.Writer.
  506. func (target *UpdateSet) MarshalBinaryTo(writer io.Writer) error {
  507. buff := util.NewBufferFromWriter(writer)
  508. defer buff.Flush()
  509. // run a pre-pass to collect all strings into the string table and discard all writes to the main
  510. // buffer. Then, we write the string table, sorted by number of repeated uses (descending), to the
  511. // main buffer, and use the resulting table as part of the context for the main pass.
  512. prepass := stringtable.NewPrepassStringTableWriter()
  513. prepassCtx := NewEncodingContextFromWriter(io.Discard, prepass)
  514. e := target.MarshalBinaryWithContext(prepassCtx)
  515. if e != nil {
  516. return e
  517. }
  518. tableWriter := prepass.WriteSortedTo(buff)
  519. ctx := NewEncodingContextFromBuffer(buff, tableWriter)
  520. return target.MarshalBinaryWithContext(ctx)
  521. }
  522. // MarshalBinaryWithContext serializes the internal properties of this UpdateSet instance
  523. // into a byte array leveraging a predefined context.
  524. func (target *UpdateSet) MarshalBinaryWithContext(ctx *EncodingContext) (err error) {
  525. // panics are recovered and propagated as errors
  526. defer func() {
  527. if r := recover(); r != nil {
  528. if e, ok := r.(error); ok {
  529. err = e
  530. } else if s, ok := r.(string); ok {
  531. err = fmt.Errorf("unexpected panic: %s", s)
  532. } else {
  533. err = fmt.Errorf("unexpected panic: %+v", r)
  534. }
  535. }
  536. }()
  537. buff := ctx.Buffer
  538. buff.WriteUInt8(DefaultCodecVersion) // version
  539. // --- [begin][write][reference](time.Time) ---
  540. a, errA := target.Timestamp.MarshalBinary()
  541. if errA != nil {
  542. return errA
  543. }
  544. buff.WriteInt(len(a))
  545. buff.WriteBytes(a)
  546. // --- [end][write][reference](time.Time) ---
  547. if target.Updates == nil {
  548. buff.WriteUInt8(uint8(0)) // write nil byte
  549. } else {
  550. buff.WriteUInt8(uint8(1)) // write non-nil byte
  551. // --- [begin][write][slice]([]Update) ---
  552. buff.WriteInt(len(target.Updates)) // slice length
  553. for i := range target.Updates {
  554. // --- [begin][write][struct](Update) ---
  555. buff.WriteInt(0) // [compatibility, unused]
  556. errB := target.Updates[i].MarshalBinaryWithContext(ctx)
  557. if errB != nil {
  558. return errB
  559. }
  560. // --- [end][write][struct](Update) ---
  561. }
  562. // --- [end][write][slice]([]Update) ---
  563. }
  564. return nil
  565. }
  566. // UnmarshalBinary uses the data passed byte array to set all the internal properties of
  567. // the UpdateSet type
  568. func (target *UpdateSet) UnmarshalBinary(data []byte) error {
  569. ctx := NewDecodingContextFromBytes(data)
  570. defer ctx.Close()
  571. err := target.UnmarshalBinaryWithContext(ctx)
  572. if err != nil {
  573. return err
  574. }
  575. return nil
  576. }
  577. // UnmarshalBinaryFromReader uses the io.Reader data to set all the internal properties of
  578. // the UpdateSet type
  579. func (target *UpdateSet) UnmarshalBinaryFromReader(reader io.Reader) error {
  580. ctx := NewDecodingContextFromReader(reader)
  581. defer ctx.Close()
  582. err := target.UnmarshalBinaryWithContext(ctx)
  583. if err != nil {
  584. return err
  585. }
  586. return nil
  587. }
  588. // UnmarshalBinaryWithContext uses the context containing a string table and binary buffer to set all the internal properties of
  589. // the UpdateSet type
  590. func (target *UpdateSet) UnmarshalBinaryWithContext(ctx *DecodingContext) (err error) {
  591. // panics are recovered and propagated as errors
  592. defer func() {
  593. if r := recover(); r != nil {
  594. if e, ok := r.(error); ok {
  595. err = e
  596. } else if s, ok := r.(string); ok {
  597. err = fmt.Errorf("unexpected panic: %s", s)
  598. } else {
  599. err = fmt.Errorf("unexpected panic: %+v", r)
  600. }
  601. }
  602. }()
  603. buff := ctx.Buffer
  604. version := buff.ReadUInt8()
  605. if version > DefaultCodecVersion {
  606. return fmt.Errorf("Invalid Version Unmarshalling UpdateSet. Expected %d or less, got %d", DefaultCodecVersion, version)
  607. }
  608. // --- [begin][read][reference](time.Time) ---
  609. a := new(time.Time)
  610. b := buff.ReadInt() // byte array length
  611. c := buff.ReadBytes(b)
  612. errA := a.UnmarshalBinary(c)
  613. if errA != nil {
  614. return errA
  615. }
  616. target.Timestamp = *a
  617. // --- [end][read][reference](time.Time) ---
  618. if buff.ReadUInt8() == uint8(0) {
  619. target.Updates = nil
  620. } else {
  621. // --- [begin][read][slice]([]Update) ---
  622. e := buff.ReadInt() // slice len
  623. d := make([]Update, e)
  624. for i := range e {
  625. // --- [begin][read][struct](Update) ---
  626. g := new(Update)
  627. buff.ReadInt() // [compatibility, unused]
  628. errB := g.UnmarshalBinaryWithContext(ctx)
  629. if errB != nil {
  630. return errB
  631. }
  632. f := *g
  633. // --- [end][read][struct](Update) ---
  634. d[i] = f
  635. }
  636. target.Updates = d
  637. // --- [end][read][slice]([]Update) ---
  638. }
  639. return nil
  640. }
  641. //--------------------------------------------------------------------------
  642. // UpdateSetStream
  643. //--------------------------------------------------------------------------
  644. // UpdateSetStream is a single use field stream for the contents of an UpdateSet instance. Instead of creating an instance and populating
  645. // the fields on that instance, we provide a streaming iterator which yields (BingenFieldInfo, *BingenValue) tuples for each
  646. // streamable element. All slices and maps will be flattened one depth and each element streamed individually.
  647. type UpdateSetStream struct {
  648. reader io.Reader
  649. ctx *DecodingContext
  650. err error
  651. }
  652. // Closes closes the internal io.Reader used to read and parse the UpdateSet fields.
  653. // This should be called once the stream is no longer needed.
  654. func (stream *UpdateSetStream) Close() {
  655. if closer, ok := stream.reader.(io.Closer); ok {
  656. closer.Close()
  657. }
  658. stream.ctx.Close()
  659. }
  660. // Error returns an error if one occurred during the process of streaming the UpdateSet
  661. // This can be checked after iterating through the Stream().
  662. func (stream *UpdateSetStream) Error() error {
  663. return stream.err
  664. }
  665. // NewUpdateSetStream creates a new UpdateSetStream, which uses the io.Reader data to stream all internal fields of an UpdateSet instance
  666. func NewUpdateSetStream(reader io.Reader) bstream.BingenStream {
  667. ctx := NewDecodingContextFromReader(reader)
  668. return &UpdateSetStream{
  669. ctx: ctx,
  670. reader: reader,
  671. }
  672. }
  673. // Stream returns the iterator which will stream each field of the target type.
  674. func (stream *UpdateSetStream) Stream() iter.Seq2[bstream.BingenFieldInfo, *bstream.BingenValue] {
  675. return func(yield func(bstream.BingenFieldInfo, *bstream.BingenValue) bool) {
  676. var fi bstream.BingenFieldInfo
  677. ctx := stream.ctx
  678. buff := ctx.Buffer
  679. version := buff.ReadUInt8()
  680. if version > DefaultCodecVersion {
  681. stream.err = fmt.Errorf("Invalid Version Unmarshalling UpdateSet. Expected %d or less, got %d", DefaultCodecVersion, version)
  682. return
  683. }
  684. fi = bstream.BingenFieldInfo{
  685. Type: reflect.TypeFor[time.Time](),
  686. Name: "Timestamp",
  687. }
  688. // --- [begin][read][reference](time.Time) ---
  689. b := new(time.Time)
  690. c := buff.ReadInt() // byte array length
  691. d := buff.ReadBytes(c)
  692. errA := b.UnmarshalBinary(d)
  693. if errA != nil {
  694. stream.err = errA
  695. return
  696. }
  697. a := *b
  698. // --- [end][read][reference](time.Time) ---
  699. if !yield(fi, bstream.SingleV(a)) {
  700. return
  701. }
  702. fi = bstream.BingenFieldInfo{
  703. Type: reflect.TypeFor[[]Update](),
  704. Name: "Updates",
  705. }
  706. if buff.ReadUInt8() == uint8(0) {
  707. if !yield(fi, nil) {
  708. return
  709. }
  710. } else {
  711. // --- [begin][read][streaming-slice]([]Update) ---
  712. e := buff.ReadInt() // slice len
  713. for i := range e {
  714. // --- [begin][read][struct](Update) ---
  715. g := new(Update)
  716. buff.ReadInt() // [compatibility, unused]
  717. errB := g.UnmarshalBinaryWithContext(ctx)
  718. if errB != nil {
  719. stream.err = errB
  720. return
  721. }
  722. f := *g
  723. // --- [end][read][struct](Update) ---
  724. if !yield(fi, bstream.PairV(i, f)) {
  725. return
  726. }
  727. }
  728. // --- [end][read][streaming-slice]([]Update) ---
  729. }
  730. }
  731. }