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