You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: protobuf.go
    path of file: ./repos/goa/grpc/codegen
    
    the code of the file until where you have to start completion: package codegen

import (
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"goa.design/goa/v3/expr"

	"goa.design/goa/v3/codegen"
)

type (
	// protoBufScope is the scope for protocol buffer attribute types.
	protoBufScope struct {
		scope *codegen.NameScope
	}
)

// Name returns the protocol buffer type name.
func (p *protoBufScope) Name(att *expr.AttributeExpr, pkg string, _, _ bool) string {
	return protoBufGoFullTypeName(att, pkg, p.scope)
}

// Ref returns the protocol buffer type reference.
func (p *protoBufScope) Ref(att *expr.AttributeExpr, pkg string) string {
	return protoBufGoFullTypeRef(att, pkg, p.scope)
}

// Field returns the field name as generated by protocol buffer compiler.
// NOTE: protoc does not care about common
    
func makeProtoBufMessageR(att *expr.AttributeExpr, tname *string, sd *ServiceData, seen map[string]struct{}) {
	ut, isut := att.Type.(expr.UserType)

	// handle infinite recursions
	if isut {
		if _, ok := seen[ut.ID()]; ok {
			return
		}
		seen[ut.ID()] = struct{}{}
	}

	wrap := func(att *expr.AttributeExpr, tname string) {
		switch {
		case expr.IsArray(att.Type):
			wrapAttr(att, "ArrayOf"+tname+
				protoBufify(protoBufMessageDef(expr.AsArray(att.Type).ElemType, sd), true, true), true, sd)
		case expr.IsMap(att.Type):
			m := expr.AsMap(att.Type)
			wrapAttr(att, tname+"MapOf"+
				protoBufify(protoBufMessageDef(m.KeyType, sd), true, true)+
				protoBufify(protoBufMessageDef(m.ElemType, sd), true, true), true, sd)
		}
	}

	switch {
	case expr.IsPrimitive(att.Type):
		return
	case isut:
		if expr.IsArray(ut) {
			wrapAttr(ut.Attribute(), ut.Name(), false, sd)
		}
		makeProtoBufMessageR(ut.Attribute(), tname, sd, seen)
	case expr.IsArray(att.Type):
		ar := expr.AsArray(att.Type)
		makeProtoBufMessageR(ar.ElemType, tname, sd, seen)
		wrap(ar.ElemType, *tname)
	case expr.IsMap(att.Type):
		m := expr.AsMap(att.Type)
		makeProtoBufMessageR(m.ElemType, tname, sd, seen)
		wrap(m.ElemType, *tname)
	case expr.IsUnion(att.Type):
		for _, nat := range expr.AsUnion(att.Type).Values {
			makeProtoBufMessageR(nat.Attribute, tname, sd, seen)
		}
	case expr.IsObject(att.Type):
		for _, nat := range *(expr.AsObject(att.Type)) {
			makeProtoBufMessageR(nat.Attribute, tname, sd, seen)
		}
	}
}