[fidl][dart] Use struct typeshapes for requests/responses

Bug: 7704

This updates the dart bindings to use the payload struct type
info, so that parameter offsets and request/response sizes no
longer include the message header. In the bindings, this leads
to the following changes:
  - when encoding, we can just alloc the request/response size
    instead of subtracting the header size
  - when decoding, we claimMemory separately for the header than
    for the payload
  - in both encoding/decoding, the calls to MemberType.encode/decode
    use a base offset of kMessageHeaderSize instead of 0

Test: fx run-test fidl_bindings_test
Change-Id: I8297e1583541ccd842eb743626df0fd65a93a9df
diff --git a/bin/fidlgen_dart/backend/ir/ir.go b/bin/fidlgen_dart/backend/ir/ir.go
index b664bd8..67b390d 100644
--- a/bin/fidlgen_dart/backend/ir/ir.go
+++ b/bin/fidlgen_dart/backend/ir/ir.go
@@ -147,8 +147,14 @@
 }
 
 type MethodResponse struct {
-	WireParameters   []Parameter
-	MethodParameters []Parameter
+	// WireParameters represent the parameters of the top level response struct
+	// that is sent on the wire
+	WireParameters []StructMember
+	// MethodParameters represent the parameters that the user interacts with
+	// when using generated methods. When HasError is false, this is the same as
+	// WireParameters. When HasError is true, MethodParameters corresponds to the
+	// fields of a succesful response.
+	MethodParameters []StructMember
 	HasError         bool
 	ResultType       XUnion
 	ValueType        Type
@@ -158,11 +164,13 @@
 // Method represents a method declaration within an interface declaration.
 type Method struct {
 	types.Ordinals
-	Name               string
-	HasRequest         bool
-	Request            []Parameter
-	HasResponse        bool
-	Response           MethodResponse
+	Name        string
+	HasRequest  bool
+	Request     []StructMember
+	HasResponse bool
+	Response    MethodResponse
+	// AsyncResponseClass is a named tuple that wraps the MethodParameters of
+	// a response, and is only generated when there is more than one parameter
 	AsyncResponseClass string
 	AsyncResponseType  string
 	CallbackType       string
@@ -172,15 +180,6 @@
 	Documented
 }
 
-// Parameter represents an interface method parameter.
-type Parameter struct {
-	Type     Type
-	Name     string
-	OffsetV1 int
-	Convert  string
-	typeExpr string
-}
-
 // Import describes another FIDL library that will be imported.
 type Import struct {
 	URL       string
@@ -222,8 +221,6 @@
 	declarationContext = make(context)
 	// Name of a method
 	methodContext = make(context)
-	// Name of a method parameter
-	parameterContext = make(context)
 	// Everywhere
 )
 
@@ -231,8 +228,7 @@
 	var allContexts = []context{
 		enumMemberContext, structMemberContext, tableMemberContext,
 		unionMemberContext, unionMemberTagContext, constantContext,
-		declarationContext, methodContext, parameterContext,
-		bitsMemberContext,
+		declarationContext, methodContext, bitsMemberContext,
 	}
 
 	var reservedWords = map[string][]context{
@@ -387,7 +383,7 @@
 	return strconv.Itoa(*val)
 }
 
-func formatParameterList(params []Parameter) string {
+func formatParameterList(params []StructMember) string {
 	if len(params) == 0 {
 		return "null"
 	}
@@ -450,17 +446,6 @@
 	return strings.Join(parts, "_")
 }
 
-func typeExprForMethod(val types.Method, request []Parameter, response []Parameter, name string) string {
-	return fmt.Sprintf(`$fidl.MethodType(
-	    request: %s,
-		response: %s,
-		name: r"%s",
-		requestInlineSize: %d,
-		responseInlineSize: %d,
-	  )`, formatParameterList(request), formatParameterList(response), name,
-		val.RequestTypeShapeV1.InlineSize, val.ResponseTypeShapeV1.InlineSize)
-}
-
 func typeExprForPrimitiveSubtype(val types.PrimitiveSubtype) string {
 	t, ok := typeForPrimitiveSubtype[val]
 	if !ok {
@@ -474,9 +459,45 @@
 }
 
 type compiler struct {
-	decls     types.DeclMap
-	library   types.LibraryIdentifier
-	typesRoot types.Root
+	decls                  types.DeclMap
+	library                types.LibraryIdentifier
+	typesRoot              types.Root
+	requestResponsePayload map[types.EncodedCompoundIdentifier]types.Struct
+}
+
+func (c *compiler) getPayload(name types.EncodedCompoundIdentifier) types.Struct {
+	val, ok := c.requestResponsePayload[name]
+	if !ok {
+		panic(fmt.Sprintf("Unknown request/response struct: %s", name))
+	}
+	return val
+}
+
+func (c *compiler) typeExprForMethod(val types.Method, request []StructMember, response []StructMember, name string) string {
+	var (
+		requestSize  = 0
+		responseSize = 0
+	)
+	if val.RequestPayload != "" {
+		payload := c.getPayload(val.RequestPayload)
+		requestSize = payload.TypeShapeV1.InlineSize
+	}
+	if val.ResponsePayload != "" {
+		payload := c.getPayload(val.ResponsePayload)
+		responseSize = payload.TypeShapeV1.InlineSize
+	}
+
+	// request/response and requestInlineSize/responseInlineSize are null/0 for both empty
+	// payloads and when there are no request/responses. The HasRequest and HasResponse fields
+	// are used to distinguish between these two cases during codegen.
+	return fmt.Sprintf(`$fidl.MethodType(
+	    request: %s,
+		response: %s,
+		name: r"%s",
+		requestInlineSize: %d,
+		responseInlineSize: %d,
+	  )`, formatParameterList(request), formatParameterList(response), name,
+		requestSize, responseSize)
 }
 
 func (c *compiler) inExternalLibrary(ci types.CompoundIdentifier) bool {
@@ -813,34 +834,12 @@
 	return b
 }
 
-func (c *compiler) compileParameter(paramName types.Identifier, paramType types.Type, offsetV1 int) Parameter {
-	var (
-		t         = c.compileType(paramType)
-		typeStr   = fmt.Sprintf("type: %s", t.typeExpr)
-		offsetStr = fmt.Sprintf("offset: %v", offsetV1)
-		name      = c.compileLowerCamelIdentifier(paramName, parameterContext)
-		convert   string
-	)
-	if t.declType == types.InterfaceDeclType {
-		convert = "$fidl.convertInterfaceHandle"
-	} else if paramType.Kind == types.RequestType {
-		convert = "$fidl.convertInterfaceRequest"
+func (c *compiler) compileParameterArray(payload types.EncodedCompoundIdentifier) []StructMember {
+	var parameters []StructMember
+	for _, v := range c.getPayload(payload).Members {
+		parameters = append(parameters, c.compileStructMember(v))
 	}
-	return Parameter{
-		Type:     t,
-		Name:     name,
-		OffsetV1: offsetV1,
-		Convert:  convert,
-		typeExpr: fmt.Sprintf("$fidl.MemberType<%s>(%s, %s)", t.Decl, typeStr, offsetStr),
-	}
-}
-
-func (c *compiler) compileParameterArray(val []types.Parameter) []Parameter {
-	r := []Parameter{}
-	for _, v := range val {
-		r = append(r, c.compileParameter(v.Name, v.Type, v.FieldShapeV1.Offset))
-	}
-	return r
+	return parameters
 }
 
 func (c *compiler) compileMethodResponse(method types.Method) MethodResponse {
@@ -851,15 +850,16 @@
 		valueType      types.Type
 		isResult       bool
 		isReponseUnion bool
-		parameters     []Parameter
+		parameters     []StructMember
 	)
+	payload := c.getPayload(method.ResponsePayload).Members
 
 	// Method needs to have exactly one response arg
-	if !method.HasResponse || len(method.Response) != 1 {
+	if !method.HasResponse || len(payload) != 1 {
 		goto NotAResult
 	}
 	// That arg must be a non-nullable identifier
-	resultType = method.Response[0].Type
+	resultType = payload[0].Type
 	if resultType.Kind != types.IdentifierType || resultType.Nullable {
 		goto NotAResult
 	}
@@ -895,11 +895,11 @@
 
 	// Turn the struct into a parameter array that will be used for function arguments.
 	for _, v := range valueStruct.Members {
-		parameters = append(parameters, c.compileParameter(v.Name, v.Type, v.FieldShapeV1.Offset))
+		parameters = append(parameters, c.compileStructMember(v))
 	}
 
 	return MethodResponse{
-		WireParameters:   c.compileParameterArray(method.Response),
+		WireParameters:   c.compileParameterArray(method.ResponsePayload),
 		MethodParameters: parameters,
 		HasError:         true,
 		ResultType:       c.compileXUnion(resultUnion),
@@ -908,7 +908,7 @@
 	}
 
 NotAResult:
-	response := c.compileParameterArray(method.Response)
+	response := c.compileParameterArray(method.ResponsePayload)
 	return MethodResponse{
 		WireParameters:   response,
 		MethodParameters: response,
@@ -918,11 +918,18 @@
 func (c *compiler) compileMethod(val types.Method, protocol Interface, fidlProtocol types.Interface) Method {
 	var (
 		name               = c.compileLowerCamelIdentifier(val.Name, methodContext)
-		request            = c.compileParameterArray(val.Request)
-		response           = c.compileMethodResponse(val)
+		request            []StructMember
+		response           MethodResponse
 		asyncResponseClass string
 		asyncResponseType  string
 	)
+	if val.HasRequest && val.RequestPayload != "" {
+		request = c.compileParameterArray(val.RequestPayload)
+	}
+	if val.HasResponse && val.ResponsePayload != "" {
+		response = c.compileMethodResponse(val)
+	}
+
 	if len(response.MethodParameters) > 1 {
 		asyncResponseClass = fmt.Sprintf("%s$%s$Response", protocol.Name, val.Name)
 	}
@@ -935,9 +942,9 @@
 			asyncResponseType = responseType.Decl
 		default:
 			asyncResponseType = asyncResponseClass
-
 		}
 	}
+
 	_, transitional := val.LookupAttribute("Transitional")
 	return Method{
 		Ordinals: types.NewOrdinalsStep7(
@@ -954,7 +961,7 @@
 		AsyncResponseType:  asyncResponseType,
 		CallbackType:       fmt.Sprintf("%s%sCallback", protocol.Name, c.compileUpperCamelIdentifier(val.Name, methodContext)),
 		TypeSymbol:         fmt.Sprintf("_k%s_%s_Type", protocol.Name, val.Name),
-		TypeExpr:           typeExprForMethod(val, request, response.WireParameters, fmt.Sprintf("%s.%s", protocol.Name, val.Name)),
+		TypeExpr:           c.typeExprForMethod(val, request, response.WireParameters, fmt.Sprintf("%s.%s", protocol.Name, val.Name)),
 		Transitional:       transitional,
 		Documented:         docString(val),
 	}
@@ -1130,9 +1137,10 @@
 func Compile(r types.Root) Root {
 	root := Root{}
 	c := compiler{
-		decls:     r.DeclsWithDependencies(),
-		library:   types.ParseLibraryName(r.Name),
-		typesRoot: r,
+		decls:                  r.DeclsWithDependencies(),
+		library:                types.ParseLibraryName(r.Name),
+		typesRoot:              r,
+		requestResponsePayload: map[types.EncodedCompoundIdentifier]types.Struct{},
 	}
 
 	root.LibraryName = fmt.Sprintf("fidl_%s", formatLibraryName(c.library))
@@ -1149,16 +1157,12 @@
 		root.Bits = append(root.Bits, c.compileBits(v))
 	}
 
-	for _, v := range r.Interfaces {
-		root.Interfaces = append(root.Interfaces, c.compileInterface(v))
-	}
-
 	for _, v := range r.Structs {
-		// TODO(7704) remove once anonymous structs are supported
 		if v.Anonymous {
-			continue
+			c.requestResponsePayload[v.Name] = v
+		} else {
+			root.Structs = append(root.Structs, c.compileStruct(v))
 		}
-		root.Structs = append(root.Structs, c.compileStruct(v))
 	}
 
 	for _, v := range r.Tables {
@@ -1174,6 +1178,10 @@
 		root.XUnions = append(root.XUnions, c.compileXUnion(v))
 	}
 
+	for _, v := range r.Interfaces {
+		root.Interfaces = append(root.Interfaces, c.compileInterface(v))
+	}
+
 	for _, l := range r.Libraries {
 		if l.Name == r.Name {
 			// We don't need to import our own package.
diff --git a/bin/fidlgen_dart/backend/templates/interface.tmpl.go b/bin/fidlgen_dart/backend/templates/interface.tmpl.go
index dd4bc7c..543760e 100644
--- a/bin/fidlgen_dart/backend/templates/interface.tmpl.go
+++ b/bin/fidlgen_dart/backend/templates/interface.tmpl.go
@@ -12,307 +12,6 @@
   {{- end -}}
 {{ end }}
 
-{{- define "RequestMethodSignature" -}}
-  {{- if .HasResponse -}}
-{{ .Name }}({{ template "Params" .Request }}{{ if .Request }}, {{ end }}void callback({{ template "Params" .Response.WireParameters }}))
-  {{- else -}}
-{{ .Name }}({{ template "Params" .Request }})
-  {{- end -}}
-{{ end -}}
-
-{{- define "ResponseMethodSignature" -}}
-{{ .Name }}({{ template "Params" .Response.WireParameters }})
-{{ end -}}
-
-{{- define "InterfaceDeclaration" -}}
-abstract class {{ .Name }} {
-  static const String $serviceName = {{ .ServiceName }};
-
-{{- range .Methods }}
-  {{- if .HasRequest }}
-  void {{ template "RequestMethodSignature" . }};
-  {{- end }}
-{{- end }}
-}
-
-{{ range .Methods }}
-// {{ .Name }}: {{ if .HasRequest }}({{ template "Params" .Request }}){{ end }}{{ if .HasResponse }} -> ({{ template "Params" .Response.WireParameters }}){{ end }}
-  {{- range .Ordinals.Reads }}
-const int {{ .Name }} = {{ .Ordinal }};
-  {{- end }}
-const $fidl.MethodType {{ .TypeSymbol }} = {{ .TypeExpr }};
-{{- end }}
-
-{{ range .Methods }}
-  {{- if not .HasRequest }}
-    {{- if .HasResponse }}
-typedef void {{ .CallbackType }}({{ template "Params" .Response.WireParameters }});
-    {{- end }}
-  {{- end }}
-{{- end }}
-
-class {{ .ProxyName }} extends $fidl.Proxy<{{ .Name }}>
-    implements {{ .Name }} {
-
-  {{ .ProxyName }}() : super($fidl.ProxyController<{{ .Name }}>($serviceName: {{ .ServiceName }}, $interfaceName: r'{{ .Name }}')) {
-    ctrl.onResponse = _handleResponse;
-  }
-
-  void _handleEvent($fidl.Message $message) {
-    if (!$message.isCompatible()) {
-      ctrl.proxyError($fidl.FidlError(
-        'Incompatible wire format', $fidl.FidlErrorCode.fidlUnknownMagic
-      ));
-      return;
-    }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
-    switch ($message.ordinal) {
-{{- range .Methods }}
-{{- if not .HasRequest }}
-  {{- if .HasResponse }}
-      {{- range .Ordinals.Reads }}
-      case {{ .Name }}:
-      {{- end }}
-        final String _name = {{ .TypeSymbol }}.name;
-        try {
-          Timeline.startSync(_name);
-          final Function $callback = {{ .Name }};
-          if ($callback == null) {
-            $message.closeHandles();
-            return;
-          }
-          final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response;
-          $decoder.claimMemory({{ .TypeSymbol }}.decodeResponseInlineSize($decoder));
-          $callback(
-      {{- range $index, $response := .Response.WireParameters }}
-            $types[{{ $index }}].decode($decoder, 0),
-      {{- end }}
-          );
-        // ignore: avoid_catches_without_on_clauses
-        } catch(_e) {
-          ctrl.proxyError('Exception handling event $_name: $_e');
-          ctrl.close();
-          rethrow;
-        } finally {
-          Timeline.finishSync();
-        }
-        break;
-  {{- end }}
-{{- end }}
-{{- end }}
-      default:
-        ctrl.proxyError('Unexpected message ordinal: ${$message.ordinal}');
-        ctrl.close();
-        break;
-    }
-  }
-
-  void _handleResponse($fidl.Message $message) {
-    final int $txid = $message.txid;
-    if ($txid == 0) {
-      _handleEvent($message);
-      return;
-    }
-    final Function $callback = ctrl.getCallback($txid);
-    if ($callback == null) {
-      $message.closeHandles();
-      return;
-    }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
-    switch ($message.ordinal) {
-{{- range .Methods }}
-  {{- if .HasRequest }}
-    {{- if .HasResponse }}
-      {{- range .Ordinals.Reads }}
-      case {{ .Name }}:
-      {{- end }}
-        final String _name = {{ .TypeSymbol }}.name;
-        try {
-          Timeline.startSync(_name);
-          final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response;
-          $decoder.claimMemory({{ .TypeSymbol }}.decodeResponseInlineSize($decoder));
-          $callback(
-        {{- range $index, $response := .Response.WireParameters }}
-            $types[{{ $index }}].decode($decoder, 0),
-        {{- end }}
-          );
-        // ignore: avoid_catches_without_on_clauses
-        } catch(_e) {
-          ctrl.proxyError('Exception handling method response $_name: $_e');
-          ctrl.close();
-          rethrow;
-        } finally {
-          Timeline.finishSync();
-        }
-        break;
-    {{- end }}
-  {{- end }}
-{{- end }}
-      default:
-        ctrl.proxyError('Unexpected message ordinal: ${$message.ordinal}');
-        ctrl.close();
-        break;
-    }
-  }
-
-{{- range .Methods }}
-  {{- if .HasRequest }}
-  @override
-  void {{ template "RequestMethodSignature" . }} {
-    if (!ctrl.isBound) {
-      ctrl.proxyError('The proxy is closed.');
-      return;
-    }
-
-    final $fidl.Encoder $encoder = $fidl.Encoder();
-    $encoder.encodeMessageHeader({{ .Ordinals.Write.Name }}, 0);
-    {{- if .Request }}
-    $encoder.alloc({{ .TypeSymbol }}.encodingRequestInlineSize($encoder) - $fidl.kMessageHeaderSize);
-    final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.request;
-    {{- end }}
-    {{- range $index, $request := .Request }}
-    $types[{{ $index }}].encode($encoder, {{ .Name }}, 0);
-    {{- end }}
-
-    {{- if .HasResponse }}
-    Function $zonedCallback;
-    if ((callback == null) || identical(Zone.current, Zone.root)) {
-      $zonedCallback = callback;
-    } else {
-      Zone $z = Zone.current;
-      {{- if .Response.WireParameters }}
-      $zonedCallback = (({{ template "Params" .Response.WireParameters }}) {
-        $z.bindCallback(() {
-          callback(
-        {{- range .Response.WireParameters -}}
-            {{ .Name }},
-        {{- end -}}
-          );
-        })();
-      });
-      {{- else }}
-      $zonedCallback = $z.bindCallback(callback);
-      {{- end }}
-    }
-    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
-    {{- else }}
-    ctrl.sendMessage($encoder.message);
-    {{- end }}
-  }
-  {{- else if .HasResponse }}
-  {{ .CallbackType }} {{ .Name }};
-  {{- end }}
-{{- end }}
-}
-
-{{- if .HasEvents }}
-
-class {{ .EventsName }} {
-  $fidl.Binding<{{ .Name }}> _binding;
-
-{{- range .Methods }}
-  {{- if not .HasRequest }}
-    {{- if .HasResponse }}
-  void {{ template "ResponseMethodSignature" . }} {
-    final $fidl.Encoder $encoder = $fidl.Encoder();
-    $encoder.encodeMessageHeader({{ .Ordinals.Write.Name }}, 0);
-      {{- if .Response.WireParameters }}
-    $encoder.alloc({{ .TypeSymbol }}.encodingResponseInlineSize($encoder) - $fidl.kMessageHeaderSize);
-    final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response;
-      {{- end }}
-      {{- range $index, $response := .Response.WireParameters }}
-    $types[{{ $index }}].encode($encoder, {{ .Name }}, 0);
-      {{- end }}
-    _binding.sendMessage($encoder.message);
-  }
-    {{- end }}
-  {{- end }}
-{{- end }}
-}
-
-{{- end }}
-
-class {{ .BindingName }} extends $fidl.Binding<{{ .Name }}> {
-{{- if .HasEvents }}
-  {{ .BindingName }}() {
-    events._binding = this;
-  }
-
-  final {{ .EventsName }} events = {{ .EventsName }}();
-{{- end }}
-
-{{ range .Methods }}
-  {{- if .HasRequest }}
-    {{- if .HasResponse }}
-  Function _{{ .Name }}Responder($fidl.MessageSink $respond, int $txid) {
-    return ({{ template "Params" .Response.WireParameters }}) {
-      final $fidl.Encoder $encoder = $fidl.Encoder();
-      $encoder.encodeMessageHeader({{ .Ordinals.Write.Name }}, $txid);
-      {{- if .Response.WireParameters }}
-      $encoder.alloc({{ .TypeSymbol }}.encodingResponseInlineSize($encoder) - $fidl.kMessageHeaderSize);
-      final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response;
-      {{- end }}
-      {{- range $index, $response := .Response.WireParameters }}
-      $types[{{ $index }}].encode($encoder, {{ .Name }}, 0);
-      {{- end }}
-      $respond($encoder.message);
-    };
-  }
-    {{- end }}
-  {{- end }}
-{{- end }}
-
-  @override
-  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
-    switch ($message.ordinal) {
-{{- range .Methods }}
-  {{- if .HasRequest }}
-      {{- range .Ordinals.Reads }}
-      case {{ .Name }}:
-      {{- end }}
-        final String _name = {{ .TypeSymbol }}.name;
-        try {
-          Timeline.startSync(_name);
-          final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.request;
-          $decoder.claimMemory({{ .TypeSymbol }}.decodeRequestInlineSize($decoder));
-          impl.{{ .Name }}(
-      {{- range $index, $request := .Request }}
-            $types[{{ $index }}].decode($decoder, 0),
-      {{- end }}
-      {{- if .HasResponse }}
-            _{{ .Name }}Responder($respond, $message.txid),
-      {{- end }}
-          );
-        // ignore: avoid_catches_without_on_clauses
-        } catch(_e) {
-          close();
-          print('Exception handling method call $_name: $_e');
-          rethrow;
-        } finally {
-          Timeline.finishSync();
-        }
-        break;
-  {{- end }}
-{{- end }}
-      default:
-        throw $fidl.FidlError(r'Unexpected message name for {{ .BindingName }}');
-    }
-  }
-}
-
-{{ end }}
-
-
-
-
-{{/*
-
-  New-style Futures-oriented bindings:
-
-*/}}
-
-
 {{/* Generate a parameter list (eg "int foo, String baz") with AsyncDecl types */}}
 {{- define "AsyncParams" -}}
   {{- range $index, $param := . -}}
@@ -320,15 +19,6 @@
   {{- end -}}
 {{ end }}
 
-
-{{/* Generate a parameter list (eg "int foo, String baz") with SyncDecl types */}}
-{{- define "SyncParams" -}}
-  {{- range $index, $param := . -}}
-    {{- if $index }}, {{ end -}}{{ $param.Type.SyncDecl }} {{ $param.Name }}
-  {{- end -}}
-{{ end }}
-
-
 {{- define "AsyncReturn" -}}
 {{- if .HasResponse -}}
 $async.Future<{{ .AsyncResponseType }}>
@@ -341,9 +31,6 @@
 {{ range $index, $param := . }}{{ if $index }}, {{ end }}{{ $param.Name }}{{ end }}
 {{- end -}}
 
-
-
-
 {{/*
   Decode a method response message.
   The current object is the method (ir.Method).
@@ -354,17 +41,17 @@
 */}}
 {{- define "DecodeResponse" -}}
   {{- if .Response.HasError }}
-    $types[0].decode($decoder, 0)
+    $types[0].decode($decoder, $fidl.kMessageHeaderSize)
   {{- else }}
     {{- if .AsyncResponseClass -}}
       {{ .AsyncResponseClass }}(
         {{- range $index, $response := .Response.WireParameters }}
-          $types[{{ $index }}].decode($decoder, 0),
+          $types[{{ $index }}].decode($decoder, $fidl.kMessageHeaderSize),
         {{- end -}}
       )
     {{- else -}}
       {{- if .Response.WireParameters -}}
-        $types[0].decode($decoder, 0)
+        $types[0].decode($decoder, $fidl.kMessageHeaderSize)
       {{- else -}}
         null
       {{- end -}}
@@ -385,11 +72,11 @@
 {{- define "EncodeResponse" -}}
   {{- if (and .AsyncResponseClass (not .Response.HasError)) -}}
     {{- range $index, $response := .Response.WireParameters }}
-      $types[{{ $index }}].encode($encoder, $response.{{ .Name }}, 0);
+      $types[{{ $index }}].encode($encoder, $response.{{ .Name }}, $fidl.kMessageHeaderSize);
     {{- end }}
   {{- else -}}
     {{- if .Response.WireParameters -}}
-      $types[0].encode($encoder, $response, 0);
+      $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
     {{- end -}}
   {{- end -}}
 {{ end -}}
@@ -495,7 +182,8 @@
   $fidl.ServiceData get $serviceData => {{ .ServiceData }}();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
 {{- range .Methods }}
 {{- if not .HasRequest }}
@@ -541,7 +229,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
 {{- range .Methods }}
   {{- if .HasRequest }}
@@ -611,11 +300,11 @@
       final $fidl.Encoder $encoder = $fidl.Encoder();
       $encoder.encodeMessageHeader({{ .Ordinals.Write.Name }}, 0);
       {{- if .Request }}
-        $encoder.alloc({{ .TypeSymbol }}.encodingRequestInlineSize($encoder) - $fidl.kMessageHeaderSize);
+        $encoder.alloc({{ .TypeSymbol }}.encodingRequestInlineSize($encoder));
         final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.request;
       {{- end }}
       {{- range $index, $request := .Request }}
-        $types[{{ $index }}].encode($encoder, {{ .Name }}, 0);
+        $types[{{ $index }}].encode($encoder, {{ .Name }}, $fidl.kMessageHeaderSize);
       {{- end }}
 
       {{- if .HasResponse }}
@@ -656,7 +345,7 @@
             $subscriptions.add(impl.{{ .Name }}.listen(($response) {
               final $fidl.Encoder $encoder = $fidl.Encoder();
               $encoder.encodeMessageHeader({{ .Ordinals.Write.Name }}, 0);
-              $encoder.alloc({{ .TypeSymbol }}.encodingResponseInlineSize($encoder) - $fidl.kMessageHeaderSize);
+              $encoder.alloc({{ .TypeSymbol }}.encodingResponseInlineSize($encoder));
               final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response;
               {{ template "EncodeResponse" . }}
               sendMessage($encoder.message);
@@ -673,7 +362,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
     {{- range .Methods }}
       {{- if .HasRequest }}
@@ -687,7 +377,7 @@
               $decoder.claimMemory({{ .TypeSymbol }}.decodeRequestInlineSize($decoder));
               final {{ template "AsyncReturn" . }} $future = impl.{{ .Name }}(
               {{- range $index, $request := .Request }}
-                $types[{{ $index }}].decode($decoder, 0),
+                $types[{{ $index }}].decode($decoder, $fidl.kMessageHeaderSize),
               {{- end }});
 
               {{- if .HasResponse }}
@@ -721,7 +411,7 @@
                   final $fidl.Encoder $encoder = $fidl.Encoder();
                   $encoder.encodeMessageHeader({{ .Ordinals.Write.Name }}, $message.txid);
                   {{- if .Response.WireParameters }}
-                    $encoder.alloc({{ .TypeSymbol }}.encodingResponseInlineSize($encoder) - $fidl.kMessageHeaderSize);
+                    $encoder.alloc({{ .TypeSymbol }}.encodingResponseInlineSize($encoder));
                     final List<$fidl.MemberType> $types = {{ .TypeSymbol }}.response;
                     {{ template "EncodeResponse" . -}}
                   {{- end }}
diff --git a/bin/fidlgen_dart/goldens/doc_comments.test.fidl.json_async.dart.golden b/bin/fidlgen_dart/goldens/doc_comments.test.fidl.json_async.dart.golden
index e05dea5..27e0a7f 100644
--- a/bin/fidlgen_dart/goldens/doc_comments.test.fidl.json_async.dart.golden
+++ b/bin/fidlgen_dart/goldens/doc_comments.test.fidl.json_async.dart.golden
@@ -313,7 +313,7 @@
   request: null,
   response: null,
   name: r"Interface.Method",
-  requestInlineSize: 16,
+  requestInlineSize: 0,
   responseInlineSize: 0,
 );
 // onEvent:  -> ()
@@ -324,7 +324,7 @@
   response: null,
   name: r"Interface.OnEvent",
   requestInlineSize: 0,
-  responseInlineSize: 16,
+  responseInlineSize: 0,
 );
 
 /// interface comment #1
@@ -377,7 +377,8 @@
   $fidl.ServiceData get $serviceData => InterfaceData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kInterface_OnEvent_Ordinal:
       case _kInterface_OnEvent_GenOrdinal:
@@ -418,7 +419,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -472,8 +474,7 @@
           final $fidl.Encoder $encoder = $fidl.Encoder();
           $encoder.encodeMessageHeader(_kInterface_OnEvent_GenOrdinal, 0);
           $encoder.alloc(
-              _kInterface_OnEvent_Type.encodingResponseInlineSize($encoder) -
-                  $fidl.kMessageHeaderSize);
+              _kInterface_OnEvent_Type.encodingResponseInlineSize($encoder));
           final List<$fidl.MemberType> $types =
               _kInterface_OnEvent_Type.response;
 
@@ -486,7 +487,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kInterface_Method_Ordinal:
       case _kInterface_Method_GenOrdinal:
diff --git a/bin/fidlgen_dart/goldens/handles.test.fidl.json b/bin/fidlgen_dart/goldens/handles.test.fidl.json
index 073bbc1..8532e6a 100644
--- a/bin/fidlgen_dart/goldens/handles.test.fidl.json
+++ b/bin/fidlgen_dart/goldens/handles.test.fidl.json
@@ -5,14 +5,49 @@
   "bits_declarations": [],
   "const_declarations": [],
   "enum_declarations": [],
-  "interface_declarations": [],
+  "interface_declarations": [
+    {
+      "name": "test.name/SomeProtocol",
+      "location": {
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
+        "line": 3,
+        "column": 10
+      },
+      "methods": [
+        {
+          "ordinal": 1898969890996355072,
+          "generated_ordinal": 8577712332834451230,
+          "name": "SomeMethod",
+          "location": {
+            "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
+            "line": 4,
+            "column": 5
+          },
+          "has_request": true,
+          "maybe_request": [],
+          "maybe_request_type_shape_v1": {
+            "inline_size": 16,
+            "alignment": 8,
+            "depth": 0,
+            "max_handles": 0,
+            "max_out_of_line": 0,
+            "has_padding": false,
+            "has_flexible_envelope": false,
+            "contains_union": false
+          },
+          "has_response": false,
+          "is_composed": false
+        }
+      ]
+    }
+  ],
   "service_declarations": [],
   "struct_declarations": [
     {
       "name": "test.name/Handles",
       "location": {
         "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-        "line": 3,
+        "line": 7,
         "column": 8
       },
       "anonymous": false,
@@ -21,14 +56,13 @@
           "type": {
             "kind": "handle",
             "subtype": "handle",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "plain_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 4,
+            "line": 8,
             "column": 12
           },
           "field_shape_v1": {
@@ -40,14 +74,13 @@
           "type": {
             "kind": "handle",
             "subtype": "bti",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "bti_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 6,
+            "line": 10,
             "column": 17
           },
           "field_shape_v1": {
@@ -59,14 +92,13 @@
           "type": {
             "kind": "handle",
             "subtype": "channel",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "channel_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 7,
+            "line": 11,
             "column": 21
           },
           "field_shape_v1": {
@@ -78,14 +110,13 @@
           "type": {
             "kind": "handle",
             "subtype": "debuglog",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "debuglog_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 8,
+            "line": 12,
             "column": 22
           },
           "field_shape_v1": {
@@ -97,14 +128,13 @@
           "type": {
             "kind": "handle",
             "subtype": "event",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "event_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 9,
+            "line": 13,
             "column": 19
           },
           "field_shape_v1": {
@@ -116,14 +146,13 @@
           "type": {
             "kind": "handle",
             "subtype": "eventpair",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "eventpair_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 10,
+            "line": 14,
             "column": 23
           },
           "field_shape_v1": {
@@ -135,14 +164,13 @@
           "type": {
             "kind": "handle",
             "subtype": "exception",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "exception_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 11,
+            "line": 15,
             "column": 23
           },
           "field_shape_v1": {
@@ -154,14 +182,13 @@
           "type": {
             "kind": "handle",
             "subtype": "fifo",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "fifo_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 12,
+            "line": 16,
             "column": 18
           },
           "field_shape_v1": {
@@ -173,14 +200,13 @@
           "type": {
             "kind": "handle",
             "subtype": "guest",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "guest_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 13,
+            "line": 17,
             "column": 19
           },
           "field_shape_v1": {
@@ -192,14 +218,13 @@
           "type": {
             "kind": "handle",
             "subtype": "interrupt",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "interrupt_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 14,
+            "line": 18,
             "column": 23
           },
           "field_shape_v1": {
@@ -211,14 +236,13 @@
           "type": {
             "kind": "handle",
             "subtype": "iommu",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "iommu_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 15,
+            "line": 19,
             "column": 19
           },
           "field_shape_v1": {
@@ -230,14 +254,13 @@
           "type": {
             "kind": "handle",
             "subtype": "job",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "job_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 16,
+            "line": 20,
             "column": 17
           },
           "field_shape_v1": {
@@ -249,14 +272,13 @@
           "type": {
             "kind": "handle",
             "subtype": "pager",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "pager_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 17,
+            "line": 21,
             "column": 19
           },
           "field_shape_v1": {
@@ -268,14 +290,13 @@
           "type": {
             "kind": "handle",
             "subtype": "pcidevice",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "pcidevice_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 18,
+            "line": 22,
             "column": 23
           },
           "field_shape_v1": {
@@ -287,14 +308,13 @@
           "type": {
             "kind": "handle",
             "subtype": "pmt",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "pmt_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 19,
+            "line": 23,
             "column": 17
           },
           "field_shape_v1": {
@@ -306,14 +326,13 @@
           "type": {
             "kind": "handle",
             "subtype": "port",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "port_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 20,
+            "line": 24,
             "column": 18
           },
           "field_shape_v1": {
@@ -325,14 +344,13 @@
           "type": {
             "kind": "handle",
             "subtype": "process",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "process_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 21,
+            "line": 25,
             "column": 21
           },
           "field_shape_v1": {
@@ -344,14 +362,13 @@
           "type": {
             "kind": "handle",
             "subtype": "profile",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "profile_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 22,
+            "line": 26,
             "column": 21
           },
           "field_shape_v1": {
@@ -363,14 +380,13 @@
           "type": {
             "kind": "handle",
             "subtype": "resource",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "resource_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 23,
+            "line": 27,
             "column": 22
           },
           "field_shape_v1": {
@@ -382,14 +398,13 @@
           "type": {
             "kind": "handle",
             "subtype": "socket",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "socket_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 24,
+            "line": 28,
             "column": 20
           },
           "field_shape_v1": {
@@ -401,14 +416,13 @@
           "type": {
             "kind": "handle",
             "subtype": "suspendtoken",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "suspendtoken_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 25,
+            "line": 29,
             "column": 26
           },
           "field_shape_v1": {
@@ -420,14 +434,13 @@
           "type": {
             "kind": "handle",
             "subtype": "thread",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "thread_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 26,
+            "line": 30,
             "column": 20
           },
           "field_shape_v1": {
@@ -439,14 +452,13 @@
           "type": {
             "kind": "handle",
             "subtype": "timer",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "timer_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 27,
+            "line": 31,
             "column": 19
           },
           "field_shape_v1": {
@@ -458,14 +470,13 @@
           "type": {
             "kind": "handle",
             "subtype": "vcpu",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "vcpu_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 28,
+            "line": 32,
             "column": 18
           },
           "field_shape_v1": {
@@ -477,14 +488,13 @@
           "type": {
             "kind": "handle",
             "subtype": "vmar",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "vmar_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 29,
+            "line": 33,
             "column": 18
           },
           "field_shape_v1": {
@@ -496,27 +506,60 @@
           "type": {
             "kind": "handle",
             "subtype": "vmo",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "vmo_handle",
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
-            "line": 30,
+            "line": 34,
             "column": 17
           },
           "field_shape_v1": {
             "offset": 100,
             "padding": 0
           }
+        },
+        {
+          "type": {
+            "kind": "identifier",
+            "identifier": "test.name/SomeProtocol",
+            "nullable": false
+          },
+          "name": "some_protocol",
+          "location": {
+            "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
+            "line": 36,
+            "column": 18
+          },
+          "field_shape_v1": {
+            "offset": 104,
+            "padding": 0
+          }
+        },
+        {
+          "type": {
+            "kind": "request",
+            "subtype": "test.name/SomeProtocol",
+            "nullable": false
+          },
+          "name": "request_some_protocol",
+          "location": {
+            "filename": "garnet/go/src/fidl/compiler/backend/typestest/handles.test.fidl",
+            "line": 37,
+            "column": 27
+          },
+          "field_shape_v1": {
+            "offset": 108,
+            "padding": 0
+          }
         }
       ],
       "type_shape_v1": {
-        "inline_size": 104,
+        "inline_size": 112,
         "alignment": 4,
         "depth": 0,
-        "max_handles": 26,
+        "max_handles": 28,
         "max_out_of_line": 0,
         "has_padding": false,
         "has_flexible_envelope": false,
@@ -529,9 +572,12 @@
   "xunion_declarations": [],
   "type_alias_declarations": [],
   "declaration_order": [
+    "test.name/SomeProtocol",
     "test.name/Handles"
   ],
   "declarations": {
+    "test.name/SomeProtocol": "interface",
+    "test.name/SomeLongAnonymousPrefix0": "struct",
     "test.name/Handles": "struct"
   }
 }
diff --git a/bin/fidlgen_dart/goldens/handles.test.fidl.json_async.dart.golden b/bin/fidlgen_dart/goldens/handles.test.fidl.json_async.dart.golden
index 500612f..19499c9 100644
--- a/bin/fidlgen_dart/goldens/handles.test.fidl.json_async.dart.golden
+++ b/bin/fidlgen_dart/goldens/handles.test.fidl.json_async.dart.golden
@@ -64,6 +64,8 @@
     @required this.vcpuHandle,
     @required this.vmarHandle,
     @required this.vmoHandle,
+    @required this.someProtocol,
+    @required this.requestSomeProtocol,
   });
   Handles.clone(
     Handles $orig, {
@@ -93,6 +95,8 @@
     $zx.Handle vcpuHandle,
     $zx.Handle vmarHandle,
     $zx.Vmo vmoHandle,
+    $fidl.InterfaceHandle<SomeProtocol> someProtocol,
+    $fidl.InterfaceRequest<SomeProtocol> requestSomeProtocol,
   }) : this(
           plainHandle: plainHandle ?? $orig.plainHandle,
           btiHandle: btiHandle ?? $orig.btiHandle,
@@ -120,6 +124,8 @@
           vcpuHandle: vcpuHandle ?? $orig.vcpuHandle,
           vmarHandle: vmarHandle ?? $orig.vmarHandle,
           vmoHandle: vmoHandle ?? $orig.vmoHandle,
+          someProtocol: someProtocol ?? $orig.someProtocol,
+          requestSomeProtocol: requestSomeProtocol ?? $orig.requestSomeProtocol,
         );
 
   Handles._(List<Object> argv)
@@ -148,7 +154,9 @@
         timerHandle = argv[22],
         vcpuHandle = argv[23],
         vmarHandle = argv[24],
-        vmoHandle = argv[25];
+        vmoHandle = argv[25],
+        someProtocol = argv[26],
+        requestSomeProtocol = argv[27];
   final $zx.Handle plainHandle;
   final $zx.Handle btiHandle;
   final $zx.Channel channelHandle;
@@ -175,6 +183,8 @@
   final $zx.Handle vcpuHandle;
   final $zx.Handle vmarHandle;
   final $zx.Vmo vmoHandle;
+  final $fidl.InterfaceHandle<SomeProtocol> someProtocol;
+  final $fidl.InterfaceRequest<SomeProtocol> requestSomeProtocol;
 
   @override
   List<Object> get $fields {
@@ -205,6 +215,8 @@
       vcpuHandle,
       vmarHandle,
       vmoHandle,
+      someProtocol,
+      requestSomeProtocol,
     ];
   }
 
@@ -263,6 +275,10 @@
         vmarHandle.toString() +
         r', vmoHandle: ' +
         vmoHandle.toString() +
+        r', someProtocol: ' +
+        someProtocol.toString() +
+        r', requestSomeProtocol: ' +
+        requestSomeProtocol.toString() +
         r')';
   }
 
@@ -272,7 +288,7 @@
 // See FIDL-308:
 // ignore: recursive_compile_time_constant
 const $fidl.StructType<Handles> kHandles_Type = $fidl.StructType<Handles>(
-  inlineSize: 104,
+  inlineSize: 112,
   members: <$fidl.MemberType>[
     $fidl.MemberType<$zx.Handle>(
         type: $fidl.HandleType(nullable: false), offset: 0),
@@ -326,9 +342,142 @@
         type: $fidl.HandleType(nullable: false), offset: 96),
     $fidl.MemberType<$zx.Vmo>(
         type: $fidl.VmoType(nullable: false), offset: 100),
+    $fidl.MemberType<$fidl.InterfaceHandle<SomeProtocol>>(
+        type: $fidl.InterfaceHandleType<SomeProtocol>(nullable: false),
+        offset: 104),
+    $fidl.MemberType<$fidl.InterfaceRequest<SomeProtocol>>(
+        type: $fidl.InterfaceRequestType<SomeProtocol>(nullable: false),
+        offset: 108),
   ],
   ctor: Handles._ctor,
 );
 
 // ignore: unused_element, avoid_private_typedef_functions
 typedef _VoidCallback = void Function();
+
+// someMethod: ()
+const int _kSomeProtocol_SomeMethod_Ordinal = 0x1a5a7f0e00000000;
+const int _kSomeProtocol_SomeMethod_GenOrdinal = 0x770a27eb8815af1e;
+const $fidl.MethodType _kSomeProtocol_SomeMethod_Type = $fidl.MethodType(
+  request: null,
+  response: null,
+  name: r"SomeProtocol.SomeMethod",
+  requestInlineSize: 0,
+  responseInlineSize: 0,
+);
+
+abstract class SomeProtocol extends $fidl.Service {
+  static const String $serviceName = null;
+  @override
+  $fidl.ServiceData get $serviceData => SomeProtocolData();
+  $async.Future<void> someMethod();
+}
+
+class SomeProtocolData implements $fidl.ServiceData<SomeProtocol> {
+  const SomeProtocolData();
+
+  @override
+  String getName() {
+    return SomeProtocol.$serviceName;
+  }
+
+  @override
+  $fidl.AsyncBinding getBinding() {
+    return SomeProtocolBinding();
+  }
+}
+
+class SomeProtocolProxy extends $fidl.AsyncProxy<SomeProtocol>
+    implements SomeProtocol {
+  SomeProtocolProxy()
+      : super($fidl.AsyncProxyController<SomeProtocol>(
+            $serviceName: null, $interfaceName: r'SomeProtocol')) {
+    ctrl.onResponse = _handleResponse;
+  }
+
+  @override
+  $fidl.ServiceData get $serviceData => SomeProtocolData();
+
+  void _handleEvent($fidl.Message $message) {
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
+    switch ($message.ordinal) {
+      default:
+        ctrl.proxyError(
+            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
+        ctrl.close();
+        break;
+    }
+  }
+
+  void _handleResponse($fidl.Message $message) {
+    final int $txid = $message.txid;
+    if ($txid == 0) {
+      _handleEvent($message);
+      return;
+    }
+    final $async.Completer $completer = ctrl.getCompleter($txid);
+    if ($completer == null) {
+      $message.closeHandles();
+      return;
+    }
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
+    switch ($message.ordinal) {
+      default:
+        ctrl.proxyError(
+            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
+        ctrl.close();
+        break;
+    }
+  }
+
+  @override
+  $async.Future<void> someMethod() async {
+    if (!ctrl.isBound) {
+      return $async.Future.error(
+          $fidl.FidlStateException('Proxy<${ctrl.$interfaceName}> is closed.'),
+          StackTrace.current);
+    }
+
+    final $fidl.Encoder $encoder = $fidl.Encoder();
+    $encoder.encodeMessageHeader(_kSomeProtocol_SomeMethod_GenOrdinal, 0);
+    return $async.Future.sync(() {
+      ctrl.sendMessage($encoder.message);
+    });
+  }
+}
+
+class SomeProtocolBinding extends $fidl.AsyncBinding<SomeProtocol> {
+  SomeProtocolBinding() : super(r"SomeProtocol");
+
+  @override
+  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
+    switch ($message.ordinal) {
+      case _kSomeProtocol_SomeMethod_Ordinal:
+      case _kSomeProtocol_SomeMethod_GenOrdinal:
+        final String _name = _kSomeProtocol_SomeMethod_Type.name;
+        try {
+          Timeline.startSync(_name);
+          final List<$fidl.MemberType> $types =
+              _kSomeProtocol_SomeMethod_Type.request;
+          $decoder.claimMemory(
+              _kSomeProtocol_SomeMethod_Type.decodeRequestInlineSize($decoder));
+          final $async.Future<void> $future = impl.someMethod();
+          // ignore: avoid_catches_without_on_clauses
+        } catch (_e) {
+          close();
+          print('Exception handling method call $_name: $_e');
+          rethrow;
+        } finally {
+          Timeline.finishSync();
+        }
+        break;
+      default:
+        throw $fidl.FidlError(
+            r'Unexpected message name for SomeProtocolBinding');
+    }
+  }
+}
diff --git a/bin/fidlgen_dart/goldens/handles.test.fidl.json_test.dart.golden b/bin/fidlgen_dart/goldens/handles.test.fidl.json_test.dart.golden
index a3eabaa..0248a5d 100644
--- a/bin/fidlgen_dart/goldens/handles.test.fidl.json_test.dart.golden
+++ b/bin/fidlgen_dart/goldens/handles.test.fidl.json_test.dart.golden
@@ -19,3 +19,10 @@
 // ignore_for_file: unused_import
 // ignore_for_file: library_prefixes
 // ignore_for_file: unused_shown_name
+
+class SomeProtocol$TestBase extends SomeProtocol {
+  @override
+  $async.Future<void> someMethod() {
+    return $async.Future.error(UnimplementedError());
+  }
+}
diff --git a/bin/fidlgen_dart/goldens/ordinal_switch.test.fidl.json_async.dart.golden b/bin/fidlgen_dart/goldens/ordinal_switch.test.fidl.json_async.dart.golden
index 176735e..3c0adec 100644
--- a/bin/fidlgen_dart/goldens/ordinal_switch.test.fidl.json_async.dart.golden
+++ b/bin/fidlgen_dart/goldens/ordinal_switch.test.fidl.json_async.dart.golden
@@ -46,7 +46,7 @@
   request: null,
   response: null,
   name: r"SwitchingOrdinals.OrdinalFive",
-  requestInlineSize: 16,
+  requestInlineSize: 0,
   responseInlineSize: 0,
 );
 // onlyGeneratedOrdinal: ()
@@ -58,7 +58,7 @@
   request: null,
   response: null,
   name: r"SwitchingOrdinals.OnlyGeneratedOrdinal",
-  requestInlineSize: 16,
+  requestInlineSize: 0,
   responseInlineSize: 0,
 );
 // eventOrdinalFifteen:  -> ()
@@ -71,7 +71,7 @@
   response: null,
   name: r"SwitchingOrdinals.EventOrdinalFifteen",
   requestInlineSize: 0,
-  responseInlineSize: 16,
+  responseInlineSize: 0,
 );
 // eventOnlyGeneratedOrdinal:  -> ()
 const int _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Ordinal =
@@ -84,7 +84,7 @@
   response: null,
   name: r"SwitchingOrdinals.EventOnlyGeneratedOrdinal",
   requestInlineSize: 0,
-  responseInlineSize: 16,
+  responseInlineSize: 0,
 );
 
 abstract class SwitchingOrdinals extends $fidl.Service {
@@ -127,7 +127,8 @@
   $fidl.ServiceData get $serviceData => SwitchingOrdinalsData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kSwitchingOrdinals_EventOrdinalFifteen_Ordinal:
       case _kSwitchingOrdinals_EventOrdinalFifteen_GenOrdinal:
@@ -190,7 +191,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -261,8 +263,7 @@
           $encoder.encodeMessageHeader(
               _kSwitchingOrdinals_EventOrdinalFifteen_GenOrdinal, 0);
           $encoder.alloc(_kSwitchingOrdinals_EventOrdinalFifteen_Type
-                  .encodingResponseInlineSize($encoder) -
-              $fidl.kMessageHeaderSize);
+              .encodingResponseInlineSize($encoder));
           final List<$fidl.MemberType> $types =
               _kSwitchingOrdinals_EventOrdinalFifteen_Type.response;
 
@@ -275,8 +276,7 @@
           $encoder.encodeMessageHeader(
               _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_GenOrdinal, 0);
           $encoder.alloc(_kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Type
-                  .encodingResponseInlineSize($encoder) -
-              $fidl.kMessageHeaderSize);
+              .encodingResponseInlineSize($encoder));
           final List<$fidl.MemberType> $types =
               _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Type.response;
 
@@ -289,7 +289,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kSwitchingOrdinals_OrdinalFive_Ordinal:
       case _kSwitchingOrdinals_OrdinalFive_GenOrdinal:
diff --git a/bin/fidlgen_dart/goldens/protocol_request.test.fidl.json b/bin/fidlgen_dart/goldens/protocol_request.test.fidl.json
index 8249ac5..95c8ff0 100644
--- a/bin/fidlgen_dart/goldens/protocol_request.test.fidl.json
+++ b/bin/fidlgen_dart/goldens/protocol_request.test.fidl.json
@@ -225,9 +225,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix1",
       "location": {
-        "filename": "generated",
-        "line": 2,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocol_request.test.fidl",
+        "line": 7,
+        "column": 19
       },
       "anonymous": true,
       "members": [
@@ -263,9 +263,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix3",
       "location": {
-        "filename": "generated",
-        "line": 4,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocol_request.test.fidl",
+        "line": 8,
+        "column": 26
       },
       "anonymous": true,
       "members": [
@@ -301,9 +301,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix4",
       "location": {
-        "filename": "generated",
-        "line": 5,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocol_request.test.fidl",
+        "line": 9,
+        "column": 14
       },
       "anonymous": true,
       "members": [
@@ -339,9 +339,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix5",
       "location": {
-        "filename": "generated",
-        "line": 6,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocol_request.test.fidl",
+        "line": 10,
+        "column": 21
       },
       "anonymous": true,
       "members": [
diff --git a/bin/fidlgen_dart/goldens/protocol_request.test.fidl.json_async.dart.golden b/bin/fidlgen_dart/goldens/protocol_request.test.fidl.json_async.dart.golden
index 8e5ccac..60d25cf 100644
--- a/bin/fidlgen_dart/goldens/protocol_request.test.fidl.json_async.dart.golden
+++ b/bin/fidlgen_dart/goldens/protocol_request.test.fidl.json_async.dart.golden
@@ -70,7 +70,8 @@
   $fidl.ServiceData get $serviceData => ChildData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -91,7 +92,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -107,7 +109,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         throw $fidl.FidlError(r'Unexpected message name for ChildBinding');
@@ -122,11 +125,11 @@
   request: null,
   response: <$fidl.MemberType>[
     $fidl.MemberType<$fidl.InterfaceHandle<Child>>(
-        type: $fidl.InterfaceHandleType<Child>(nullable: false), offset: 16),
+        type: $fidl.InterfaceHandleType<Child>(nullable: false), offset: 0),
   ],
   name: r"Parent.GetChild",
-  requestInlineSize: 16,
-  responseInlineSize: 24,
+  requestInlineSize: 0,
+  responseInlineSize: 8,
 );
 // getChildRequest: () -> ($fidl.InterfaceRequest<Child> r)
 const int _kParent_GetChildRequest_Ordinal = 0x3faacc7e00000000;
@@ -135,11 +138,11 @@
   request: null,
   response: <$fidl.MemberType>[
     $fidl.MemberType<$fidl.InterfaceRequest<Child>>(
-        type: $fidl.InterfaceRequestType<Child>(nullable: false), offset: 16),
+        type: $fidl.InterfaceRequestType<Child>(nullable: false), offset: 0),
   ],
   name: r"Parent.GetChildRequest",
-  requestInlineSize: 16,
-  responseInlineSize: 24,
+  requestInlineSize: 0,
+  responseInlineSize: 8,
 );
 // takeChild: ($fidl.InterfaceHandle<Child> c)
 const int _kParent_TakeChild_Ordinal = 0x4c0642f900000000;
@@ -147,11 +150,11 @@
 const $fidl.MethodType _kParent_TakeChild_Type = $fidl.MethodType(
   request: <$fidl.MemberType>[
     $fidl.MemberType<$fidl.InterfaceHandle<Child>>(
-        type: $fidl.InterfaceHandleType<Child>(nullable: false), offset: 16),
+        type: $fidl.InterfaceHandleType<Child>(nullable: false), offset: 0),
   ],
   response: null,
   name: r"Parent.TakeChild",
-  requestInlineSize: 24,
+  requestInlineSize: 8,
   responseInlineSize: 0,
 );
 // takeChildRequest: ($fidl.InterfaceRequest<Child> r)
@@ -160,11 +163,11 @@
 const $fidl.MethodType _kParent_TakeChildRequest_Type = $fidl.MethodType(
   request: <$fidl.MemberType>[
     $fidl.MemberType<$fidl.InterfaceRequest<Child>>(
-        type: $fidl.InterfaceRequestType<Child>(nullable: false), offset: 16),
+        type: $fidl.InterfaceRequestType<Child>(nullable: false), offset: 0),
   ],
   response: null,
   name: r"Parent.TakeChildRequest",
-  requestInlineSize: 24,
+  requestInlineSize: 8,
   responseInlineSize: 0,
 );
 
@@ -203,7 +206,8 @@
   $fidl.ServiceData get $serviceData => ParentData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -224,7 +228,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kParent_GetChild_Ordinal:
       case _kParent_GetChild_GenOrdinal:
@@ -235,7 +240,8 @@
           $decoder.claimMemory(
               _kParent_GetChild_Type.decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           $completer.complete($response);
 
@@ -259,7 +265,8 @@
           $decoder.claimMemory(
               _kParent_GetChildRequest_Type.decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           $completer.complete($response);
 
@@ -321,10 +328,9 @@
 
     final $fidl.Encoder $encoder = $fidl.Encoder();
     $encoder.encodeMessageHeader(_kParent_TakeChild_GenOrdinal, 0);
-    $encoder.alloc(_kParent_TakeChild_Type.encodingRequestInlineSize($encoder) -
-        $fidl.kMessageHeaderSize);
+    $encoder.alloc(_kParent_TakeChild_Type.encodingRequestInlineSize($encoder));
     final List<$fidl.MemberType> $types = _kParent_TakeChild_Type.request;
-    $types[0].encode($encoder, c, 0);
+    $types[0].encode($encoder, c, $fidl.kMessageHeaderSize);
     return $async.Future.sync(() {
       ctrl.sendMessage($encoder.message);
     });
@@ -341,11 +347,10 @@
     final $fidl.Encoder $encoder = $fidl.Encoder();
     $encoder.encodeMessageHeader(_kParent_TakeChildRequest_GenOrdinal, 0);
     $encoder.alloc(
-        _kParent_TakeChildRequest_Type.encodingRequestInlineSize($encoder) -
-            $fidl.kMessageHeaderSize);
+        _kParent_TakeChildRequest_Type.encodingRequestInlineSize($encoder));
     final List<$fidl.MemberType> $types =
         _kParent_TakeChildRequest_Type.request;
-    $types[0].encode($encoder, r, 0);
+    $types[0].encode($encoder, r, $fidl.kMessageHeaderSize);
     return $async.Future.sync(() {
       ctrl.sendMessage($encoder.message);
     });
@@ -357,7 +362,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kParent_GetChild_Ordinal:
       case _kParent_GetChild_GenOrdinal:
@@ -374,11 +380,10 @@
             $encoder.encodeMessageHeader(
                 _kParent_GetChild_GenOrdinal, $message.txid);
             $encoder.alloc(
-                _kParent_GetChild_Type.encodingResponseInlineSize($encoder) -
-                    $fidl.kMessageHeaderSize);
+                _kParent_GetChild_Type.encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kParent_GetChild_Type.response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
@@ -409,11 +414,10 @@
             $encoder.encodeMessageHeader(
                 _kParent_GetChildRequest_GenOrdinal, $message.txid);
             $encoder.alloc(_kParent_GetChildRequest_Type
-                    .encodingResponseInlineSize($encoder) -
-                $fidl.kMessageHeaderSize);
+                .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kParent_GetChildRequest_Type.response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
@@ -437,7 +441,7 @@
           $decoder.claimMemory(
               _kParent_TakeChild_Type.decodeRequestInlineSize($decoder));
           final $async.Future<void> $future = impl.takeChild(
-            $types[0].decode($decoder, 0),
+            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
           );
           // ignore: avoid_catches_without_on_clauses
         } catch (_e) {
@@ -458,7 +462,7 @@
           $decoder.claimMemory(
               _kParent_TakeChildRequest_Type.decodeRequestInlineSize($decoder));
           final $async.Future<void> $future = impl.takeChildRequest(
-            $types[0].decode($decoder, 0),
+            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
           );
           // ignore: avoid_catches_without_on_clauses
         } catch (_e) {
diff --git a/bin/fidlgen_dart/goldens/protocols.test.fidl.json b/bin/fidlgen_dart/goldens/protocols.test.fidl.json
index d9e36a0..a9dad12 100644
--- a/bin/fidlgen_dart/goldens/protocols.test.fidl.json
+++ b/bin/fidlgen_dart/goldens/protocols.test.fidl.json
@@ -449,7 +449,7 @@
               "name": "result",
               "location": {
                 "filename": "generated",
-                "line": 18,
+                "line": 3,
                 "column": 1
               },
               "field_shape_v1": {
@@ -503,7 +503,7 @@
               "name": "result",
               "location": {
                 "filename": "generated",
-                "line": 25,
+                "line": 6,
                 "column": 1
               },
               "field_shape_v1": {
@@ -557,7 +557,7 @@
               "name": "result",
               "location": {
                 "filename": "generated",
-                "line": 32,
+                "line": 9,
                 "column": 1
               },
               "field_shape_v1": {
@@ -813,8 +813,7 @@
               "type": {
                 "kind": "handle",
                 "subtype": "socket",
-                "required_rights": 0,
-                "optional_rights": 4294967295,
+                "rights": 2147483648,
                 "nullable": false
               },
               "name": "a",
@@ -846,8 +845,7 @@
               "type": {
                 "kind": "handle",
                 "subtype": "socket",
-                "required_rights": 0,
-                "optional_rights": 4294967295,
+                "rights": 2147483648,
                 "nullable": false
               },
               "name": "b",
@@ -883,9 +881,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix4",
       "location": {
-        "filename": "generated",
-        "line": 5,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 6,
+        "column": 32
       },
       "anonymous": true,
       "members": [
@@ -920,9 +918,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix5",
       "location": {
-        "filename": "generated",
-        "line": 6,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 7,
+        "column": 26
       },
       "anonymous": true,
       "members": [
@@ -957,9 +955,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix6",
       "location": {
-        "filename": "generated",
-        "line": 7,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 8,
+        "column": 29
       },
       "anonymous": true,
       "members": [
@@ -994,9 +992,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix8",
       "location": {
-        "filename": "generated",
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
         "line": 9,
-        "column": 1
+        "column": 28
       },
       "anonymous": true,
       "members": [
@@ -1031,9 +1029,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix9",
       "location": {
-        "filename": "generated",
-        "line": 10,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 9,
+        "column": 44
       },
       "anonymous": true,
       "members": [
@@ -1068,9 +1066,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix11",
       "location": {
-        "filename": "generated",
-        "line": 12,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 11,
+        "column": 22
       },
       "anonymous": true,
       "members": [
@@ -1105,9 +1103,9 @@
     {
       "name": "test.name/WithErrorSyntax_ResponseAsStruct_Response",
       "location": {
-        "filename": "generated",
-        "line": 14,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 20,
+        "column": 27
       },
       "anonymous": false,
       "members": [
@@ -1174,9 +1172,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix13",
       "location": {
-        "filename": "generated",
-        "line": 19,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 20,
+        "column": 27
       },
       "anonymous": true,
       "members": [
@@ -1189,7 +1187,7 @@
           "name": "result",
           "location": {
             "filename": "generated",
-            "line": 18,
+            "line": 3,
             "column": 1
           },
           "field_shape_v1": {
@@ -1212,9 +1210,9 @@
     {
       "name": "test.name/WithErrorSyntax_ErrorAsPrimitive_Response",
       "location": {
-        "filename": "generated",
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
         "line": 21,
-        "column": 1
+        "column": 27
       },
       "anonymous": false,
       "members": [],
@@ -1232,9 +1230,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix15",
       "location": {
-        "filename": "generated",
-        "line": 26,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 21,
+        "column": 27
       },
       "anonymous": true,
       "members": [
@@ -1247,7 +1245,7 @@
           "name": "result",
           "location": {
             "filename": "generated",
-            "line": 25,
+            "line": 6,
             "column": 1
           },
           "field_shape_v1": {
@@ -1270,9 +1268,9 @@
     {
       "name": "test.name/WithErrorSyntax_ErrorAsEnum_Response",
       "location": {
-        "filename": "generated",
-        "line": 28,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 22,
+        "column": 22
       },
       "anonymous": false,
       "members": [],
@@ -1290,9 +1288,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix17",
       "location": {
-        "filename": "generated",
-        "line": 33,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 22,
+        "column": 22
       },
       "anonymous": true,
       "members": [
@@ -1305,7 +1303,7 @@
           "name": "result",
           "location": {
             "filename": "generated",
-            "line": 32,
+            "line": 9,
             "column": 1
           },
           "field_shape_v1": {
@@ -1328,9 +1326,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix18",
       "location": {
-        "filename": "generated",
-        "line": 34,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 27,
+        "column": 12
       },
       "anonymous": true,
       "members": [
@@ -1381,9 +1379,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix19",
       "location": {
-        "filename": "generated",
-        "line": 35,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 28,
+        "column": 14
       },
       "anonymous": true,
       "members": [
@@ -1434,9 +1432,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix20",
       "location": {
-        "filename": "generated",
-        "line": 36,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 29,
+        "column": 12
       },
       "anonymous": true,
       "members": [
@@ -1487,9 +1485,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix21",
       "location": {
-        "filename": "generated",
-        "line": 37,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 29,
+        "column": 34
       },
       "anonymous": true,
       "members": [
@@ -1524,9 +1522,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix22",
       "location": {
-        "filename": "generated",
-        "line": 38,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 30,
+        "column": 17
       },
       "anonymous": true,
       "members": [
@@ -1534,8 +1532,7 @@
           "type": {
             "kind": "handle",
             "subtype": "socket",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "a",
@@ -1564,9 +1561,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix23",
       "location": {
-        "filename": "generated",
-        "line": 39,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 30,
+        "column": 39
       },
       "anonymous": true,
       "members": [
@@ -1574,8 +1571,7 @@
           "type": {
             "kind": "handle",
             "subtype": "socket",
-            "required_rights": 0,
-            "optional_rights": 4294967295,
+            "rights": 2147483648,
             "nullable": false
           },
           "name": "b",
@@ -1607,9 +1603,9 @@
     {
       "name": "test.name/WithErrorSyntax_ResponseAsStruct_Result",
       "location": {
-        "filename": "generated",
-        "line": 15,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 20,
+        "column": 27
       },
       "maybe_attributes": [
         {
@@ -1629,7 +1625,7 @@
           },
           "location": {
             "filename": "generated",
-            "line": 16,
+            "line": 1,
             "column": 1
           }
         },
@@ -1643,7 +1639,7 @@
           },
           "location": {
             "filename": "generated",
-            "line": 17,
+            "line": 2,
             "column": 1
           }
         }
@@ -1663,9 +1659,9 @@
     {
       "name": "test.name/WithErrorSyntax_ErrorAsPrimitive_Result",
       "location": {
-        "filename": "generated",
-        "line": 22,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 21,
+        "column": 27
       },
       "maybe_attributes": [
         {
@@ -1685,7 +1681,7 @@
           },
           "location": {
             "filename": "generated",
-            "line": 23,
+            "line": 4,
             "column": 1
           }
         },
@@ -1699,7 +1695,7 @@
           },
           "location": {
             "filename": "generated",
-            "line": 24,
+            "line": 5,
             "column": 1
           }
         }
@@ -1719,9 +1715,9 @@
     {
       "name": "test.name/WithErrorSyntax_ErrorAsEnum_Result",
       "location": {
-        "filename": "generated",
-        "line": 29,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/protocols.test.fidl",
+        "line": 22,
+        "column": 22
       },
       "maybe_attributes": [
         {
@@ -1741,7 +1737,7 @@
           },
           "location": {
             "filename": "generated",
-            "line": 30,
+            "line": 7,
             "column": 1
           }
         },
@@ -1756,7 +1752,7 @@
           },
           "location": {
             "filename": "generated",
-            "line": 31,
+            "line": 8,
             "column": 1
           }
         }
diff --git a/bin/fidlgen_dart/goldens/protocols.test.fidl.json_async.dart.golden b/bin/fidlgen_dart/goldens/protocols.test.fidl.json_async.dart.golden
index 511a3e1..d472663 100644
--- a/bin/fidlgen_dart/goldens/protocols.test.fidl.json_async.dart.golden
+++ b/bin/fidlgen_dart/goldens/protocols.test.fidl.json_async.dart.golden
@@ -541,7 +541,7 @@
   request: null,
   response: null,
   name: r"WithAndWithoutRequestResponse.NoRequestNoResponse",
-  requestInlineSize: 16,
+  requestInlineSize: 0,
   responseInlineSize: 0,
 );
 // noRequestEmptyResponse: () -> ()
@@ -555,8 +555,8 @@
   request: null,
   response: null,
   name: r"WithAndWithoutRequestResponse.NoRequestEmptyResponse",
-  requestInlineSize: 16,
-  responseInlineSize: 16,
+  requestInlineSize: 0,
+  responseInlineSize: 0,
 );
 // noRequestWithResponse: () -> (String ret)
 const int _kWithAndWithoutRequestResponse_NoRequestWithResponse_Ordinal =
@@ -570,11 +570,11 @@
   response: <$fidl.MemberType>[
     $fidl.MemberType<String>(
         type: $fidl.StringType(maybeElementCount: null, nullable: false),
-        offset: 16),
+        offset: 0),
   ],
   name: r"WithAndWithoutRequestResponse.NoRequestWithResponse",
-  requestInlineSize: 16,
-  responseInlineSize: 32,
+  requestInlineSize: 0,
+  responseInlineSize: 16,
 );
 // withRequestNoResponse: (String arg)
 const int _kWithAndWithoutRequestResponse_WithRequestNoResponse_Ordinal =
@@ -587,11 +587,11 @@
   request: <$fidl.MemberType>[
     $fidl.MemberType<String>(
         type: $fidl.StringType(maybeElementCount: null, nullable: false),
-        offset: 16),
+        offset: 0),
   ],
   response: null,
   name: r"WithAndWithoutRequestResponse.WithRequestNoResponse",
-  requestInlineSize: 32,
+  requestInlineSize: 16,
   responseInlineSize: 0,
 );
 // withRequestEmptyResponse: (String arg) -> ()
@@ -605,12 +605,12 @@
   request: <$fidl.MemberType>[
     $fidl.MemberType<String>(
         type: $fidl.StringType(maybeElementCount: null, nullable: false),
-        offset: 16),
+        offset: 0),
   ],
   response: null,
   name: r"WithAndWithoutRequestResponse.WithRequestEmptyResponse",
-  requestInlineSize: 32,
-  responseInlineSize: 16,
+  requestInlineSize: 16,
+  responseInlineSize: 0,
 );
 // withRequestWithResponse: (String arg) -> (String ret)
 const int _kWithAndWithoutRequestResponse_WithRequestWithResponse_Ordinal =
@@ -623,16 +623,16 @@
   request: <$fidl.MemberType>[
     $fidl.MemberType<String>(
         type: $fidl.StringType(maybeElementCount: null, nullable: false),
-        offset: 16),
+        offset: 0),
   ],
   response: <$fidl.MemberType>[
     $fidl.MemberType<String>(
         type: $fidl.StringType(maybeElementCount: null, nullable: false),
-        offset: 16),
+        offset: 0),
   ],
   name: r"WithAndWithoutRequestResponse.WithRequestWithResponse",
-  requestInlineSize: 32,
-  responseInlineSize: 32,
+  requestInlineSize: 16,
+  responseInlineSize: 16,
 );
 // onEmptyResponse:  -> ()
 const int _kWithAndWithoutRequestResponse_OnEmptyResponse_Ordinal =
@@ -645,7 +645,7 @@
   response: null,
   name: r"WithAndWithoutRequestResponse.OnEmptyResponse",
   requestInlineSize: 0,
-  responseInlineSize: 16,
+  responseInlineSize: 0,
 );
 // onWithResponse:  -> (String ret)
 const int _kWithAndWithoutRequestResponse_OnWithResponse_Ordinal =
@@ -658,11 +658,11 @@
   response: <$fidl.MemberType>[
     $fidl.MemberType<String>(
         type: $fidl.StringType(maybeElementCount: null, nullable: false),
-        offset: 16),
+        offset: 0),
   ],
   name: r"WithAndWithoutRequestResponse.OnWithResponse",
   requestInlineSize: 0,
-  responseInlineSize: 32,
+  responseInlineSize: 16,
 );
 
 abstract class WithAndWithoutRequestResponse extends $fidl.Service {
@@ -712,7 +712,8 @@
   $fidl.ServiceData get $serviceData => WithAndWithoutRequestResponseData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kWithAndWithoutRequestResponse_OnEmptyResponse_Ordinal:
       case _kWithAndWithoutRequestResponse_OnEmptyResponse_GenOrdinal:
@@ -748,7 +749,7 @@
               _kWithAndWithoutRequestResponse_OnWithResponse_Type
                   .decodeResponseInlineSize($decoder));
           _onWithResponseEventStreamController
-              .add($types[0].decode($decoder, 0));
+              .add($types[0].decode($decoder, $fidl.kMessageHeaderSize));
           // ignore: avoid_catches_without_on_clauses
         } catch (_e) {
           ctrl.proxyError(
@@ -778,7 +779,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Ordinal:
       case _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_GenOrdinal:
@@ -820,7 +822,8 @@
               _kWithAndWithoutRequestResponse_NoRequestWithResponse_Type
                   .decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           $completer.complete($response);
 
@@ -874,7 +877,8 @@
               _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type
                   .decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           $completer.complete($response);
 
@@ -956,11 +960,10 @@
     $encoder.encodeMessageHeader(
         _kWithAndWithoutRequestResponse_WithRequestNoResponse_GenOrdinal, 0);
     $encoder.alloc(_kWithAndWithoutRequestResponse_WithRequestNoResponse_Type
-            .encodingRequestInlineSize($encoder) -
-        $fidl.kMessageHeaderSize);
+        .encodingRequestInlineSize($encoder));
     final List<$fidl.MemberType> $types =
         _kWithAndWithoutRequestResponse_WithRequestNoResponse_Type.request;
-    $types[0].encode($encoder, arg, 0);
+    $types[0].encode($encoder, arg, $fidl.kMessageHeaderSize);
     return $async.Future.sync(() {
       ctrl.sendMessage($encoder.message);
     });
@@ -978,11 +981,10 @@
     $encoder.encodeMessageHeader(
         _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_GenOrdinal, 0);
     $encoder.alloc(_kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Type
-            .encodingRequestInlineSize($encoder) -
-        $fidl.kMessageHeaderSize);
+        .encodingRequestInlineSize($encoder));
     final List<$fidl.MemberType> $types =
         _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Type.request;
-    $types[0].encode($encoder, arg, 0);
+    $types[0].encode($encoder, arg, $fidl.kMessageHeaderSize);
     final $completer = $async.Completer<void>();
     ctrl.sendMessageWithResponse($encoder.message, $completer);
     return $completer.future;
@@ -1000,11 +1002,10 @@
     $encoder.encodeMessageHeader(
         _kWithAndWithoutRequestResponse_WithRequestWithResponse_GenOrdinal, 0);
     $encoder.alloc(_kWithAndWithoutRequestResponse_WithRequestWithResponse_Type
-            .encodingRequestInlineSize($encoder) -
-        $fidl.kMessageHeaderSize);
+        .encodingRequestInlineSize($encoder));
     final List<$fidl.MemberType> $types =
         _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type.request;
-    $types[0].encode($encoder, arg, 0);
+    $types[0].encode($encoder, arg, $fidl.kMessageHeaderSize);
     final $completer = $async.Completer<String>();
     ctrl.sendMessageWithResponse($encoder.message, $completer);
     return $completer.future;
@@ -1042,8 +1043,7 @@
           $encoder.encodeMessageHeader(
               _kWithAndWithoutRequestResponse_OnEmptyResponse_GenOrdinal, 0);
           $encoder.alloc(_kWithAndWithoutRequestResponse_OnEmptyResponse_Type
-                  .encodingResponseInlineSize($encoder) -
-              $fidl.kMessageHeaderSize);
+              .encodingResponseInlineSize($encoder));
           final List<$fidl.MemberType> $types =
               _kWithAndWithoutRequestResponse_OnEmptyResponse_Type.response;
 
@@ -1056,11 +1056,10 @@
           $encoder.encodeMessageHeader(
               _kWithAndWithoutRequestResponse_OnWithResponse_GenOrdinal, 0);
           $encoder.alloc(_kWithAndWithoutRequestResponse_OnWithResponse_Type
-                  .encodingResponseInlineSize($encoder) -
-              $fidl.kMessageHeaderSize);
+              .encodingResponseInlineSize($encoder));
           final List<$fidl.MemberType> $types =
               _kWithAndWithoutRequestResponse_OnWithResponse_Type.response;
-          $types[0].encode($encoder, $response, 0);
+          $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
           sendMessage($encoder.message);
         }));
       }
@@ -1070,7 +1069,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kWithAndWithoutRequestResponse_NoRequestNoResponse_Ordinal:
       case _kWithAndWithoutRequestResponse_NoRequestNoResponse_GenOrdinal:
@@ -1145,12 +1145,11 @@
                 $message.txid);
             $encoder.alloc(
                 _kWithAndWithoutRequestResponse_NoRequestWithResponse_Type
-                        .encodingResponseInlineSize($encoder) -
-                    $fidl.kMessageHeaderSize);
+                    .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kWithAndWithoutRequestResponse_NoRequestWithResponse_Type
                     .response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
@@ -1178,7 +1177,7 @@
               _kWithAndWithoutRequestResponse_WithRequestNoResponse_Type
                   .decodeRequestInlineSize($decoder));
           final $async.Future<void> $future = impl.withRequestNoResponse(
-            $types[0].decode($decoder, 0),
+            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
           );
           // ignore: avoid_catches_without_on_clauses
         } catch (_e) {
@@ -1202,7 +1201,7 @@
               _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Type
                   .decodeRequestInlineSize($decoder));
           final $async.Future<void> $future = impl.withRequestEmptyResponse(
-            $types[0].decode($decoder, 0),
+            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
           );
           $future.then(($response) {
             final $fidl.Encoder $encoder = $fidl.Encoder();
@@ -1236,7 +1235,7 @@
               _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type
                   .decodeRequestInlineSize($decoder));
           final $async.Future<String> $future = impl.withRequestWithResponse(
-            $types[0].decode($decoder, 0),
+            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
           );
           $future.then(($response) {
             final $fidl.Encoder $encoder = $fidl.Encoder();
@@ -1245,12 +1244,11 @@
                 $message.txid);
             $encoder.alloc(
                 _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type
-                        .encodingResponseInlineSize($encoder) -
-                    $fidl.kMessageHeaderSize);
+                    .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type
                     .response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
@@ -1280,11 +1278,11 @@
   request: null,
   response: <$fidl.MemberType>[
     $fidl.MemberType<WithErrorSyntaxResponseAsStructResult>(
-        type: kWithErrorSyntax_ResponseAsStruct_Result_Type, offset: 16),
+        type: kWithErrorSyntax_ResponseAsStruct_Result_Type, offset: 0),
   ],
   name: r"WithErrorSyntax.ResponseAsStruct",
-  requestInlineSize: 16,
-  responseInlineSize: 40,
+  requestInlineSize: 0,
+  responseInlineSize: 24,
 );
 // errorAsPrimitive: () -> ()
 const int _kWithErrorSyntax_ErrorAsPrimitive_Ordinal = 0x7b58113900000000;
@@ -1294,11 +1292,11 @@
   request: null,
   response: <$fidl.MemberType>[
     $fidl.MemberType<WithErrorSyntaxErrorAsPrimitiveResult>(
-        type: kWithErrorSyntax_ErrorAsPrimitive_Result_Type, offset: 16),
+        type: kWithErrorSyntax_ErrorAsPrimitive_Result_Type, offset: 0),
   ],
   name: r"WithErrorSyntax.ErrorAsPrimitive",
-  requestInlineSize: 16,
-  responseInlineSize: 40,
+  requestInlineSize: 0,
+  responseInlineSize: 24,
 );
 // errorAsEnum: () -> ()
 const int _kWithErrorSyntax_ErrorAsEnum_Ordinal = 0x4c95de1f00000000;
@@ -1307,11 +1305,11 @@
   request: null,
   response: <$fidl.MemberType>[
     $fidl.MemberType<WithErrorSyntaxErrorAsEnumResult>(
-        type: kWithErrorSyntax_ErrorAsEnum_Result_Type, offset: 16),
+        type: kWithErrorSyntax_ErrorAsEnum_Result_Type, offset: 0),
   ],
   name: r"WithErrorSyntax.ErrorAsEnum",
-  requestInlineSize: 16,
-  responseInlineSize: 40,
+  requestInlineSize: 0,
+  responseInlineSize: 24,
 );
 
 class WithErrorSyntax$ResponseAsStruct$Response {
@@ -1360,7 +1358,8 @@
   $fidl.ServiceData get $serviceData => WithErrorSyntaxData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -1381,7 +1380,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kWithErrorSyntax_ResponseAsStruct_Ordinal:
       case _kWithErrorSyntax_ResponseAsStruct_GenOrdinal:
@@ -1393,7 +1393,8 @@
           $decoder.claimMemory(_kWithErrorSyntax_ResponseAsStruct_Type
               .decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           if ($response.$tag ==
               WithErrorSyntaxResponseAsStructResultTag.response) {
@@ -1426,7 +1427,8 @@
           $decoder.claimMemory(_kWithErrorSyntax_ErrorAsPrimitive_Type
               .decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           if ($response.$tag ==
               WithErrorSyntaxErrorAsPrimitiveResultTag.response) {
@@ -1455,7 +1457,8 @@
           $decoder.claimMemory(_kWithErrorSyntax_ErrorAsEnum_Type
               .decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           if ($response.$tag == WithErrorSyntaxErrorAsEnumResultTag.response) {
             $completer.complete(null);
@@ -1536,7 +1539,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kWithErrorSyntax_ResponseAsStruct_Ordinal:
       case _kWithErrorSyntax_ResponseAsStruct_GenOrdinal:
@@ -1568,11 +1572,10 @@
             $encoder.encodeMessageHeader(
                 _kWithErrorSyntax_ResponseAsStruct_GenOrdinal, $message.txid);
             $encoder.alloc(_kWithErrorSyntax_ResponseAsStruct_Type
-                    .encodingResponseInlineSize($encoder) -
-                $fidl.kMessageHeaderSize);
+                .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kWithErrorSyntax_ResponseAsStruct_Type.response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
@@ -1612,11 +1615,10 @@
             $encoder.encodeMessageHeader(
                 _kWithErrorSyntax_ErrorAsPrimitive_GenOrdinal, $message.txid);
             $encoder.alloc(_kWithErrorSyntax_ErrorAsPrimitive_Type
-                    .encodingResponseInlineSize($encoder) -
-                $fidl.kMessageHeaderSize);
+                .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kWithErrorSyntax_ErrorAsPrimitive_Type.response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
@@ -1655,11 +1657,10 @@
             $encoder.encodeMessageHeader(
                 _kWithErrorSyntax_ErrorAsEnum_GenOrdinal, $message.txid);
             $encoder.alloc(_kWithErrorSyntax_ErrorAsEnum_Type
-                    .encodingResponseInlineSize($encoder) -
-                $fidl.kMessageHeaderSize);
+                .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kWithErrorSyntax_ErrorAsEnum_Type.response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
@@ -1686,12 +1687,12 @@
 const int _kChannelProtocol_MethodA_GenOrdinal = 0x1b1e059b3f02bffc;
 const $fidl.MethodType _kChannelProtocol_MethodA_Type = $fidl.MethodType(
   request: <$fidl.MemberType>[
-    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
-    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
+    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 0),
+    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 8),
   ],
   response: null,
   name: r"ChannelProtocol.MethodA",
-  requestInlineSize: 32,
+  requestInlineSize: 16,
   responseInlineSize: 0,
 );
 // eventA:  -> (int a, int b)
@@ -1700,27 +1701,27 @@
 const $fidl.MethodType _kChannelProtocol_EventA_Type = $fidl.MethodType(
   request: null,
   response: <$fidl.MemberType>[
-    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
-    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
+    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 0),
+    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 8),
   ],
   name: r"ChannelProtocol.EventA",
   requestInlineSize: 0,
-  responseInlineSize: 32,
+  responseInlineSize: 16,
 );
 // methodB: (int a, int b) -> (int result)
 const int _kChannelProtocol_MethodB_Ordinal = 0xac6551b00000000;
 const int _kChannelProtocol_MethodB_GenOrdinal = 0x5db17a61464744a3;
 const $fidl.MethodType _kChannelProtocol_MethodB_Type = $fidl.MethodType(
   request: <$fidl.MemberType>[
-    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
-    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
+    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 0),
+    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 8),
   ],
   response: <$fidl.MemberType>[
-    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
+    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 0),
   ],
   name: r"ChannelProtocol.MethodB",
-  requestInlineSize: 32,
-  responseInlineSize: 24,
+  requestInlineSize: 16,
+  responseInlineSize: 8,
 );
 // mutateSocket: ($zx.Socket a) -> ($zx.Socket b)
 const int _kChannelProtocol_MutateSocket_Ordinal = 0x4b02e28600000000;
@@ -1728,15 +1729,15 @@
 const $fidl.MethodType _kChannelProtocol_MutateSocket_Type = $fidl.MethodType(
   request: <$fidl.MemberType>[
     $fidl.MemberType<$zx.Socket>(
-        type: $fidl.SocketType(nullable: false), offset: 16),
+        type: $fidl.SocketType(nullable: false), offset: 0),
   ],
   response: <$fidl.MemberType>[
     $fidl.MemberType<$zx.Socket>(
-        type: $fidl.SocketType(nullable: false), offset: 16),
+        type: $fidl.SocketType(nullable: false), offset: 0),
   ],
   name: r"ChannelProtocol.MutateSocket",
-  requestInlineSize: 24,
-  responseInlineSize: 24,
+  requestInlineSize: 8,
+  responseInlineSize: 8,
 );
 
 class ChannelProtocol$EventA$Response {
@@ -1787,7 +1788,8 @@
   $fidl.ServiceData get $serviceData => ChannelProtocolData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kChannelProtocol_EventA_Ordinal:
       case _kChannelProtocol_EventA_GenOrdinal:
@@ -1799,8 +1801,8 @@
           $decoder.claimMemory(
               _kChannelProtocol_EventA_Type.decodeResponseInlineSize($decoder));
           _eventAEventStreamController.add(ChannelProtocol$EventA$Response(
-            $types[0].decode($decoder, 0),
-            $types[1].decode($decoder, 0),
+            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
+            $types[1].decode($decoder, $fidl.kMessageHeaderSize),
           ));
           // ignore: avoid_catches_without_on_clauses
         } catch (_e) {
@@ -1831,7 +1833,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kChannelProtocol_MethodB_Ordinal:
       case _kChannelProtocol_MethodB_GenOrdinal:
@@ -1843,7 +1846,8 @@
           $decoder.claimMemory(_kChannelProtocol_MethodB_Type
               .decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           $completer.complete($response);
 
@@ -1867,7 +1871,8 @@
           $decoder.claimMemory(_kChannelProtocol_MutateSocket_Type
               .decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           $completer.complete($response);
 
@@ -1900,12 +1905,11 @@
     final $fidl.Encoder $encoder = $fidl.Encoder();
     $encoder.encodeMessageHeader(_kChannelProtocol_MethodA_GenOrdinal, 0);
     $encoder.alloc(
-        _kChannelProtocol_MethodA_Type.encodingRequestInlineSize($encoder) -
-            $fidl.kMessageHeaderSize);
+        _kChannelProtocol_MethodA_Type.encodingRequestInlineSize($encoder));
     final List<$fidl.MemberType> $types =
         _kChannelProtocol_MethodA_Type.request;
-    $types[0].encode($encoder, a, 0);
-    $types[1].encode($encoder, b, 0);
+    $types[0].encode($encoder, a, $fidl.kMessageHeaderSize);
+    $types[1].encode($encoder, b, $fidl.kMessageHeaderSize);
     return $async.Future.sync(() {
       ctrl.sendMessage($encoder.message);
     });
@@ -1928,12 +1932,11 @@
     final $fidl.Encoder $encoder = $fidl.Encoder();
     $encoder.encodeMessageHeader(_kChannelProtocol_MethodB_GenOrdinal, 0);
     $encoder.alloc(
-        _kChannelProtocol_MethodB_Type.encodingRequestInlineSize($encoder) -
-            $fidl.kMessageHeaderSize);
+        _kChannelProtocol_MethodB_Type.encodingRequestInlineSize($encoder));
     final List<$fidl.MemberType> $types =
         _kChannelProtocol_MethodB_Type.request;
-    $types[0].encode($encoder, a, 0);
-    $types[1].encode($encoder, b, 0);
+    $types[0].encode($encoder, a, $fidl.kMessageHeaderSize);
+    $types[1].encode($encoder, b, $fidl.kMessageHeaderSize);
     final $completer = $async.Completer<int>();
     ctrl.sendMessageWithResponse($encoder.message, $completer);
     return $completer.future;
@@ -1950,11 +1953,10 @@
     final $fidl.Encoder $encoder = $fidl.Encoder();
     $encoder.encodeMessageHeader(_kChannelProtocol_MutateSocket_GenOrdinal, 0);
     $encoder.alloc(_kChannelProtocol_MutateSocket_Type
-            .encodingRequestInlineSize($encoder) -
-        $fidl.kMessageHeaderSize);
+        .encodingRequestInlineSize($encoder));
     final List<$fidl.MemberType> $types =
         _kChannelProtocol_MutateSocket_Type.request;
-    $types[0].encode($encoder, a, 0);
+    $types[0].encode($encoder, a, $fidl.kMessageHeaderSize);
     final $completer = $async.Completer<$zx.Socket>();
     ctrl.sendMessageWithResponse($encoder.message, $completer);
     return $completer.future;
@@ -1977,13 +1979,12 @@
           final $fidl.Encoder $encoder = $fidl.Encoder();
           $encoder.encodeMessageHeader(_kChannelProtocol_EventA_GenOrdinal, 0);
           $encoder.alloc(_kChannelProtocol_EventA_Type
-                  .encodingResponseInlineSize($encoder) -
-              $fidl.kMessageHeaderSize);
+              .encodingResponseInlineSize($encoder));
           final List<$fidl.MemberType> $types =
               _kChannelProtocol_EventA_Type.response;
 
-          $types[0].encode($encoder, $response.a, 0);
-          $types[1].encode($encoder, $response.b, 0);
+          $types[0].encode($encoder, $response.a, $fidl.kMessageHeaderSize);
+          $types[1].encode($encoder, $response.b, $fidl.kMessageHeaderSize);
           sendMessage($encoder.message);
         }));
       }
@@ -1993,7 +1994,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kChannelProtocol_MethodA_Ordinal:
       case _kChannelProtocol_MethodA_GenOrdinal:
@@ -2005,8 +2007,8 @@
           $decoder.claimMemory(
               _kChannelProtocol_MethodA_Type.decodeRequestInlineSize($decoder));
           final $async.Future<void> $future = impl.methodA(
-            $types[0].decode($decoder, 0),
-            $types[1].decode($decoder, 0),
+            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
+            $types[1].decode($decoder, $fidl.kMessageHeaderSize),
           );
           // ignore: avoid_catches_without_on_clauses
         } catch (_e) {
@@ -2027,19 +2029,18 @@
           $decoder.claimMemory(
               _kChannelProtocol_MethodB_Type.decodeRequestInlineSize($decoder));
           final $async.Future<int> $future = impl.methodB(
-            $types[0].decode($decoder, 0),
-            $types[1].decode($decoder, 0),
+            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
+            $types[1].decode($decoder, $fidl.kMessageHeaderSize),
           );
           $future.then(($response) {
             final $fidl.Encoder $encoder = $fidl.Encoder();
             $encoder.encodeMessageHeader(
                 _kChannelProtocol_MethodB_GenOrdinal, $message.txid);
             $encoder.alloc(_kChannelProtocol_MethodB_Type
-                    .encodingResponseInlineSize($encoder) -
-                $fidl.kMessageHeaderSize);
+                .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kChannelProtocol_MethodB_Type.response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
@@ -2064,18 +2065,17 @@
           $decoder.claimMemory(_kChannelProtocol_MutateSocket_Type
               .decodeRequestInlineSize($decoder));
           final $async.Future<$zx.Socket> $future = impl.mutateSocket(
-            $types[0].decode($decoder, 0),
+            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
           );
           $future.then(($response) {
             final $fidl.Encoder $encoder = $fidl.Encoder();
             $encoder.encodeMessageHeader(
                 _kChannelProtocol_MutateSocket_GenOrdinal, $message.txid);
             $encoder.alloc(_kChannelProtocol_MutateSocket_Type
-                    .encodingResponseInlineSize($encoder) -
-                $fidl.kMessageHeaderSize);
+                .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kChannelProtocol_MutateSocket_Type.response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
diff --git a/bin/fidlgen_dart/goldens/service.test.fidl.json_async.dart.golden b/bin/fidlgen_dart/goldens/service.test.fidl.json_async.dart.golden
index 6649fdf..4efe8e3 100644
--- a/bin/fidlgen_dart/goldens/service.test.fidl.json_async.dart.golden
+++ b/bin/fidlgen_dart/goldens/service.test.fidl.json_async.dart.golden
@@ -46,7 +46,7 @@
   request: null,
   response: null,
   name: r"FirstProtocol.MethodOnFirst",
-  requestInlineSize: 16,
+  requestInlineSize: 0,
   responseInlineSize: 0,
 );
 
@@ -83,7 +83,8 @@
   $fidl.ServiceData get $serviceData => FirstProtocolData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -104,7 +105,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -135,7 +137,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kFirstProtocol_MethodOnFirst_Ordinal:
       case _kFirstProtocol_MethodOnFirst_GenOrdinal:
@@ -170,7 +173,7 @@
   request: null,
   response: null,
   name: r"SecondProtocol.MethodOnSecond",
-  requestInlineSize: 16,
+  requestInlineSize: 0,
   responseInlineSize: 0,
 );
 
@@ -207,7 +210,8 @@
   $fidl.ServiceData get $serviceData => SecondProtocolData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -228,7 +232,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -259,7 +264,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kSecondProtocol_MethodOnSecond_Ordinal:
       case _kSecondProtocol_MethodOnSecond_GenOrdinal:
diff --git a/bin/fidlgen_dart/goldens/xunion.test.fidl.json b/bin/fidlgen_dart/goldens/xunion.test.fidl.json
index 83034b8..8f9972a 100644
--- a/bin/fidlgen_dart/goldens/xunion.test.fidl.json
+++ b/bin/fidlgen_dart/goldens/xunion.test.fidl.json
@@ -130,9 +130,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix1",
       "location": {
-        "filename": "generated",
-        "line": 2,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/xunion.test.fidl",
+        "line": 39,
+        "column": 55
       },
       "anonymous": true,
       "members": [
@@ -168,9 +168,9 @@
     {
       "name": "test.name/SomeLongAnonymousPrefix3",
       "location": {
-        "filename": "generated",
-        "line": 4,
-        "column": 1
+        "filename": "garnet/go/src/fidl/compiler/backend/typestest/xunion.test.fidl",
+        "line": 40,
+        "column": 57
       },
       "anonymous": true,
       "members": [
@@ -275,6 +275,8 @@
       "members": [
         {
           "ordinal": 1,
+          "explicit_ordinal": 1,
+          "hashed_ordinal": 1026732503,
           "reserved": false,
           "name": "i",
           "type": {
@@ -289,6 +291,8 @@
         },
         {
           "ordinal": 2,
+          "explicit_ordinal": 2,
+          "hashed_ordinal": 1362546558,
           "reserved": false,
           "name": "f",
           "type": {
@@ -324,6 +328,8 @@
       "members": [
         {
           "ordinal": 1,
+          "explicit_ordinal": 1,
+          "hashed_ordinal": 693944286,
           "reserved": false,
           "name": "i",
           "type": {
@@ -338,6 +344,8 @@
         },
         {
           "ordinal": 2,
+          "explicit_ordinal": 2,
+          "hashed_ordinal": 473666119,
           "reserved": false,
           "name": "s",
           "type": {
@@ -352,6 +360,8 @@
         },
         {
           "ordinal": 3,
+          "explicit_ordinal": 3,
+          "hashed_ordinal": 1815655055,
           "reserved": false,
           "name": "v",
           "type": {
@@ -391,6 +401,8 @@
       "members": [
         {
           "ordinal": 1,
+          "explicit_ordinal": 1,
+          "hashed_ordinal": 1851697276,
           "reserved": false,
           "name": "i",
           "type": {
@@ -405,6 +417,8 @@
         },
         {
           "ordinal": 2,
+          "explicit_ordinal": 2,
+          "hashed_ordinal": 855207063,
           "reserved": false,
           "name": "f",
           "type": {
@@ -419,6 +433,8 @@
         },
         {
           "ordinal": 3,
+          "explicit_ordinal": 3,
+          "hashed_ordinal": 850602487,
           "reserved": false,
           "name": "s",
           "type": {
@@ -454,6 +470,8 @@
       "members": [
         {
           "ordinal": 1,
+          "explicit_ordinal": 1,
+          "hashed_ordinal": 424858069,
           "reserved": false,
           "name": "empty",
           "type": {
@@ -490,6 +508,8 @@
       "members": [
         {
           "ordinal": 1,
+          "explicit_ordinal": 1,
+          "hashed_ordinal": 2024555624,
           "reserved": false,
           "name": "v",
           "type": {
@@ -530,6 +550,7 @@
       "members": [
         {
           "ordinal": 3,
+          "explicit_ordinal": 3,
           "reserved": true,
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/xunion.test.fidl",
@@ -539,6 +560,7 @@
         },
         {
           "ordinal": 2,
+          "explicit_ordinal": 2,
           "reserved": true,
           "location": {
             "filename": "garnet/go/src/fidl/compiler/backend/typestest/xunion.test.fidl",
@@ -548,6 +570,8 @@
         },
         {
           "ordinal": 1,
+          "explicit_ordinal": 1,
+          "hashed_ordinal": 625512649,
           "reserved": false,
           "name": "i",
           "type": {
@@ -562,6 +586,8 @@
         },
         {
           "ordinal": 4,
+          "explicit_ordinal": 4,
+          "hashed_ordinal": 182552961,
           "reserved": false,
           "name": "f",
           "type": {
diff --git a/bin/fidlgen_dart/goldens/xunion.test.fidl.json_async.dart.golden b/bin/fidlgen_dart/goldens/xunion.test.fidl.json_async.dart.golden
index 3cb0f81..b4c5f26 100644
--- a/bin/fidlgen_dart/goldens/xunion.test.fidl.json_async.dart.golden
+++ b/bin/fidlgen_dart/goldens/xunion.test.fidl.json_async.dart.golden
@@ -709,11 +709,11 @@
   request: null,
   response: <$fidl.MemberType>[
     $fidl.MemberType<StrictBoundedXUnion>(
-        type: kStrictBoundedXUnion_Type, offset: 16),
+        type: kStrictBoundedXUnion_Type, offset: 0),
   ],
   name: r"TestProtocol.StrictXUnionHenceResponseMayBeStackAllocated",
-  requestInlineSize: 16,
-  responseInlineSize: 40,
+  requestInlineSize: 0,
+  responseInlineSize: 24,
 );
 // flexibleXUnionHenceResponseMustBeHeapAllocated: () -> (OlderSimpleUnion xu)
 const int
@@ -727,12 +727,11 @@
     $fidl.MethodType(
   request: null,
   response: <$fidl.MemberType>[
-    $fidl.MemberType<OlderSimpleUnion>(
-        type: kOlderSimpleUnion_Type, offset: 16),
+    $fidl.MemberType<OlderSimpleUnion>(type: kOlderSimpleUnion_Type, offset: 0),
   ],
   name: r"TestProtocol.FlexibleXUnionHenceResponseMustBeHeapAllocated",
-  requestInlineSize: 16,
-  responseInlineSize: 40,
+  requestInlineSize: 0,
+  responseInlineSize: 24,
 );
 
 abstract class TestProtocol extends $fidl.Service {
@@ -771,7 +770,8 @@
   $fidl.ServiceData get $serviceData => TestProtocolData();
 
   void _handleEvent($fidl.Message $message) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       default:
         ctrl.proxyError(
@@ -792,7 +792,8 @@
       $message.closeHandles();
       return;
     }
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Ordinal:
       case _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_GenOrdinal:
@@ -808,7 +809,8 @@
               _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type
                   .decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           $completer.complete($response);
 
@@ -836,7 +838,8 @@
               _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type
                   .decodeResponseInlineSize($decoder));
           // ignore: prefer_const_declarations
-          final $response = $types[0].decode($decoder, 0);
+          final $response =
+              $types[0].decode($decoder, $fidl.kMessageHeaderSize);
 
           $completer.complete($response);
 
@@ -900,7 +903,8 @@
 
   @override
   void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
-    final $fidl.Decoder $decoder = $fidl.Decoder($message);
+    final $fidl.Decoder $decoder = $fidl.Decoder($message)
+      ..claimMemory($fidl.kMessageHeaderSize);
     switch ($message.ordinal) {
       case _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Ordinal:
       case _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_GenOrdinal:
@@ -924,12 +928,11 @@
                 $message.txid);
             $encoder.alloc(
                 _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type
-                        .encodingResponseInlineSize($encoder) -
-                    $fidl.kMessageHeaderSize);
+                    .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type
                     .response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();
@@ -966,12 +969,11 @@
                 $message.txid);
             $encoder.alloc(
                 _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type
-                        .encodingResponseInlineSize($encoder) -
-                    $fidl.kMessageHeaderSize);
+                    .encodingResponseInlineSize($encoder));
             final List<$fidl.MemberType> $types =
                 _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type
                     .response;
-            $types[0].encode($encoder, $response, 0);
+            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
             $respond($encoder.message);
           }, onError: (_e) {
             close();