common.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
  2. // is governed by an MIT-style license that can be found in the LICENSE file.
  3. package xdr
  4. import (
  5. "fmt"
  6. "reflect"
  7. )
  8. var padBytes = []byte{0, 0, 0}
  9. // Pad returns the number of bytes that should be added to an item of length l
  10. // bytes to conform to the XDR padding standard. This function is used by the
  11. // generated marshalling code.
  12. func Padding(l int) int {
  13. d := l % 4
  14. if d == 0 {
  15. return 0
  16. }
  17. return 4 - d
  18. }
  19. // ElementSizeExceeded returns an error describing the violated size
  20. // constraint. This function is used by the generated marshalling code.
  21. func ElementSizeExceeded(field string, size, limit int) error {
  22. return fmt.Errorf("%s exceeds size limit; %d > %d", field, size, limit)
  23. }
  24. type XDRSizer interface {
  25. XDRSize() int
  26. }
  27. // SizeOfSlice returns the XDR encoded size of the given []T. Supported types
  28. // for T are string, []byte and types implementing XDRSizer. SizeOfSlice
  29. // panics if the parameter is not a slice or if T is not one of the supported
  30. // types. This function is used by the generated marshalling code.
  31. func SizeOfSlice(ss interface{}) int {
  32. l := 0
  33. switch ss := ss.(type) {
  34. case []string:
  35. for _, s := range ss {
  36. l += 4 + len(s) + Padding(len(s))
  37. }
  38. case [][]byte:
  39. for _, s := range ss {
  40. l += 4 + len(s) + Padding(len(s))
  41. }
  42. default:
  43. v := reflect.ValueOf(ss)
  44. for i := 0; i < v.Len(); i++ {
  45. l += v.Index(i).Interface().(XDRSizer).XDRSize()
  46. }
  47. }
  48. return l
  49. }