| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package templates |
| |
| import ( |
| "text/template" |
| ) |
| |
| const ampersandIfNullable = ` |
| {{- define "AmpersandIfNullable" -}} |
| {{- $info := . -}} |
| {{- if $info.IsNullable -}} |
| & |
| {{- end -}} |
| {{- end -}} |
| ` |
| |
| const fieldDecodingTmplText = ` |
| {{- define "FieldDecodingTmpl" -}} |
| {{- $info := . -}} |
| {{- if $info.IsPointer -}} |
| pointer, err := decoder.ReadPointer() |
| if err != nil { |
| return err |
| } |
| if pointer == 0 { |
| {{- if $info.IsNullable}} |
| {{$info.Identifier}} = nil |
| {{- else if $info.IsUnion}} |
| return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null union pointer"} |
| {{- else}} |
| return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"} |
| {{- end }} |
| } else { |
| {{ template "NonNullableFieldDecodingTmpl" $info }} |
| } |
| {{- else -}} |
| {{ template "NonNullableFieldDecodingTmpl" $info }} |
| {{- end -}} |
| {{- end -}} |
| ` |
| |
| const nonNullableFieldDecodingTmplText = ` |
| {{- define "NonNullableFieldDecodingTmpl" -}} |
| {{- $info := . -}} |
| {{- if or $info.IsEnum $info.IsSimple -}} |
| value, err := decoder.{{$info.ReadFunction}}() |
| if err != nil { |
| return err |
| } |
| {{if $info.IsSimple -}} |
| {{$info.Identifier}} = value |
| {{- else -}} |
| {{$info.Identifier}} = {{$info.GoType}}(value) |
| {{- end -}} |
| {{- else if $info.IsHandle -}} |
| handle, err := decoder.{{$info.ReadFunction}}() |
| if err != nil { |
| return err |
| } |
| if handle.IsValid() { |
| {{- if $info.IsNullable -}} |
| {{$info.Identifier}} = &handle |
| } else { |
| {{$info.Identifier}} = nil |
| {{- else -}} |
| {{$info.Identifier}} = handle |
| } else { |
| return &bindings.ValidationError{bindings.UnexpectedInvalidHandle, "unexpected invalid handle"} |
| {{- end -}} |
| } |
| {{- else if $info.IsStruct -}} |
| {{- if $info.IsNullable -}} |
| {{$info.Identifier}} = new({{$info.GoType}}) |
| {{end -}} |
| if err := {{$info.Identifier}}.Decode(decoder); err != nil { |
| return err |
| } |
| {{- else if $info.IsUnion -}} |
| {{- if $info.IsPointer -}} |
| if err := decoder.StartNestedUnion(); err != nil { |
| return err |
| } |
| {{end -}} |
| var err error |
| {{$info.Identifier}}, err = Decode{{$info.GoType}}(decoder) |
| if err != nil { |
| return err |
| } |
| {{- if not $info.IsNullable}} |
| if {{$info.Identifier}} == nil { |
| return &bindings.ValidationError{bindings.UnexpectedNullUnion, "unexpected null union"} |
| } |
| {{- end -}} |
| {{- if $info.IsPointer}} |
| decoder.Finish() |
| {{- end -}} |
| {{- else if $info.IsInterface -}} |
| handle, err := decoder.{{$info.ReadFunction}}() |
| if err != nil { |
| return err |
| } |
| if handle.IsValid() { |
| handleOwner := bindings.NewMessagePipeHandleOwner(handle) |
| {{- if $info.IsInterfaceRequest}} |
| {{$info.Identifier}} = {{template "AmpersandIfNullable" $info}}{{$info.GoType}}_Request{handleOwner} |
| {{- else}} |
| {{$info.Identifier}} = {{template "AmpersandIfNullable" $info}}{{$info.GoType}}_Pointer{handleOwner} |
| {{- end -}} |
| } else { |
| {{- if $info.IsNullable}} |
| {{$info.Identifier}} = nil |
| {{- else}} |
| return &bindings.ValidationError{bindings.UnexpectedInvalidHandle, "unexpected invalid handle"} |
| {{- end -}} |
| } |
| {{- else if $info.IsArray -}} |
| {{ $elInfo := $info.ElementEncodingInfo -}} |
| len0, err := decoder.StartArray({{$elInfo.BitSize}}) |
| if err != nil { |
| return err |
| } |
| {{$info.Identifier}} = make({{$info.GoType}}, len0) |
| for i := uint32(0); i < len0; i++ { |
| {{ template "FieldDecodingTmpl" $elInfo }} |
| {{$info.Identifier}}[i] = {{$elInfo.Identifier}} |
| } |
| if err := decoder.Finish(); err != nil { |
| return nil |
| } |
| {{- else if $info.IsMap -}} |
| {{ $keyInfo := $info.KeyEncodingInfo -}} |
| {{ $keyElId := $info.KeyEncodingInfo.ElementEncodingInfo.Identifier -}} |
| {{ $valueInfo := $info.ValueEncodingInfo -}} |
| {{ $valueElId := $info.ValueEncodingInfo.ElementEncodingInfo.Identifier -}} |
| {{$info.Identifier}} = new({{$info.GoType}}) |
| if err := decoder.StartMap(); err != nil { |
| return err |
| } |
| var {{$keyInfo.Identifier}} {{$keyInfo.GoType}} |
| { |
| {{ template "FieldDecodingTmpl" $keyInfo }} |
| } |
| var {{$valueInfo.Identifier}} {{$valueInfo.GoType}} |
| { |
| {{ template "FieldDecodingTmpl" $valueInfo }} |
| } |
| if err := decoder.Finish(); err != nil { |
| return nil |
| } |
| if len({{$keyInfo.Identifier}}) == len({{$valueInfo.Identifier}}) { |
| return &bindings.ValidationError{bindings.DifferentSizedArraysInMap, |
| fmt.Sprintf("Number of keys %d is different from number of values %d", |
| len({{$keyInfo.Identifier}}), len({{$valueInfo.Identifier}}))} |
| } |
| for i := 0; i < len({{$keyInfo.Identifier}}); i++ { |
| (*{{$info.Identifier}})[{{$keyInfo.Identifier}}[i]] = {{$valueInfo.Identifier}}[i] |
| } |
| {{- end -}} |
| {{- end -}} |
| ` |
| |
| func initDecodingTemplates() { |
| template.Must(goFileTmpl.Parse(nonNullableFieldDecodingTmplText)) |
| template.Must(goFileTmpl.Parse(fieldDecodingTmplText)) |
| template.Must(goFileTmpl.Parse(ampersandIfNullable)) |
| } |