| package ndr |
| |
| import ( |
| "errors" |
| "fmt" |
| "reflect" |
| "strconv" |
| ) |
| |
| // type MyBytes []byte |
| // implement RawBytes interface |
| |
| const ( |
| sizeMethod = "Size" |
| ) |
| |
| // RawBytes interface should be implemented if reading just a number of bytes from the NDR stream |
| type RawBytes interface { |
| Size(interface{}) int |
| } |
| |
| func rawBytesSize(parent reflect.Value, v reflect.Value) (int, error) { |
| sf := v.MethodByName(sizeMethod) |
| if !sf.IsValid() { |
| return 0, fmt.Errorf("could not find a method called %s on the implementation of RawBytes", sizeMethod) |
| } |
| in := []reflect.Value{parent} |
| f := sf.Call(in) |
| if f[0].Kind() != reflect.Int { |
| return 0, errors.New("the RawBytes size function did not return an integer") |
| } |
| return int(f[0].Int()), nil |
| } |
| |
| func addSizeToTag(parent reflect.Value, v reflect.Value, tag reflect.StructTag) (reflect.StructTag, error) { |
| size, err := rawBytesSize(parent, v) |
| if err != nil { |
| return tag, err |
| } |
| ndrTag := parseTags(tag) |
| ndrTag.Map["size"] = strconv.Itoa(size) |
| return ndrTag.StructTag(), nil |
| } |
| |
| func (dec *Decoder) readRawBytes(v reflect.Value, tag reflect.StructTag) error { |
| ndrTag := parseTags(tag) |
| sizeStr, ok := ndrTag.Map["size"] |
| if !ok { |
| return errors.New("size tag not available") |
| } |
| size, err := strconv.Atoi(sizeStr) |
| if err != nil { |
| return fmt.Errorf("size not valid: %v", err) |
| } |
| b, err := dec.readBytes(size) |
| if err != nil { |
| return err |
| } |
| v.Set(reflect.ValueOf(b).Convert(v.Type())) |
| return nil |
| } |