rawbytes.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. package ndr
  2. import (
  3. "errors"
  4. "fmt"
  5. "reflect"
  6. "strconv"
  7. )
  8. // type MyBytes []byte
  9. // implement RawBytes interface
  10. const (
  11. sizeMethod = "Size"
  12. )
  13. // RawBytes interface should be implemented if reading just a number of bytes from the NDR stream
  14. type RawBytes interface {
  15. Size(interface{}) int
  16. }
  17. func rawBytesSize(parent reflect.Value, v reflect.Value) (int, error) {
  18. sf := v.MethodByName(sizeMethod)
  19. if !sf.IsValid() {
  20. return 0, fmt.Errorf("could not find a method called %s on the implementation of RawBytes", sizeMethod)
  21. }
  22. in := []reflect.Value{parent}
  23. f := sf.Call(in)
  24. if f[0].Kind() != reflect.Int {
  25. return 0, errors.New("the RawBytes size function did not return an integer")
  26. }
  27. return int(f[0].Int()), nil
  28. }
  29. func addSizeToTag(parent reflect.Value, v reflect.Value, tag reflect.StructTag) (reflect.StructTag, error) {
  30. size, err := rawBytesSize(parent, v)
  31. if err != nil {
  32. return tag, err
  33. }
  34. ndrTag := parseTags(tag)
  35. ndrTag.Map["size"] = strconv.Itoa(size)
  36. return ndrTag.StructTag(), nil
  37. }
  38. func (dec *Decoder) readRawBytes(v reflect.Value, tag reflect.StructTag) error {
  39. ndrTag := parseTags(tag)
  40. sizeStr, ok := ndrTag.Map["size"]
  41. if !ok {
  42. return errors.New("size tag not available")
  43. }
  44. size, err := strconv.Atoi(sizeStr)
  45. if err != nil {
  46. return fmt.Errorf("size not valid: %v", err)
  47. }
  48. b, err := dec.readBytes(size)
  49. if err != nil {
  50. return err
  51. }
  52. v.Set(reflect.ValueOf(b).Convert(v.Type()))
  53. return nil
  54. }