-- Hand-built descriptors for the subset of google.protobuf.descriptor needed
-- to decode FileDescriptorSet wire bytes back into AST form. Used by
-- pb.from_pb (see runtime/pb/fileset.lua).
--
-- We model FieldDescriptorProto.type and .label as int32 scalars instead of
-- enums; the codec returns the wire integer either way and the translator
-- maps it to a proto3 type-name string by hand.
local codec = require('pb.codec')
local M = {}
local function finalize(desc)
local fbi, fbn = {}, {}
for _, f in ipairs(desc.fields) do
fbi[f.id] = f
fbn[f.name] = f
end
desc.field_by_id = fbi
desc.field_by_name = fbn
codec.compile_writers(desc)
codec.compile_readers(desc)
return desc
end
-- FieldOptions: subset.
M.FieldOptions = {
name = 'google.protobuf.FieldOptions',
fields = {
{name = 'packed', id = 2, kind = 'scalar', proto_type = 'bool'},
},
}
-- MessageOptions: subset.
M.MessageOptions = {
name = 'google.protobuf.MessageOptions',
fields = {
{name = 'map_entry', id = 7, kind = 'scalar', proto_type = 'bool'},
},
}
-- FieldDescriptorProto.
M.FieldDescriptorProto = {
name = 'google.protobuf.FieldDescriptorProto',
fields = {
{name = 'name', id = 1, kind = 'scalar', proto_type = 'string'},
{name = 'extendee', id = 2, kind = 'scalar', proto_type = 'string'},
{name = 'number', id = 3, kind = 'scalar', proto_type = 'int32'},
{name = 'label', id = 4, kind = 'scalar', proto_type = 'int32'},
{name = 'type', id = 5, kind = 'scalar', proto_type = 'int32'},
{name = 'type_name', id = 6, kind = 'scalar', proto_type = 'string'},
{name = 'default_value', id = 7, kind = 'scalar', proto_type = 'string'},
{name = 'options', id = 8, kind = 'message', message = M.FieldOptions},
{name = 'oneof_index', id = 9, kind = 'scalar', proto_type = 'int32'},
{name = 'json_name', id = 10, kind = 'scalar', proto_type = 'string'},
{name = 'proto3_optional', id = 17, kind = 'scalar', proto_type = 'bool'},
},
}
M.OneofDescriptorProto = {
name = 'google.protobuf.OneofDescriptorProto',
fields = {
{name = 'name', id = 1, kind = 'scalar', proto_type = 'string'},
},
}
M.EnumValueDescriptorProto = {
name = 'google.protobuf.EnumValueDescriptorProto',
fields = {
{name = 'name', id = 1, kind = 'scalar', proto_type = 'string'},
{name = 'number', id = 2, kind = 'scalar', proto_type = 'int32'},
},
}
M.EnumDescriptorProto = {
name = 'google.protobuf.EnumDescriptorProto',
fields = {
{name = 'name', id = 1, kind = 'scalar', proto_type = 'string'},
{name = 'value', id = 2, kind = 'message',
message = M.EnumValueDescriptorProto, repeated = true},
},
}
M.MethodDescriptorProto = {
name = 'google.protobuf.MethodDescriptorProto',
fields = {
{name = 'name', id = 1, kind = 'scalar', proto_type = 'string'},
{name = 'input_type', id = 2, kind = 'scalar', proto_type = 'string'},
{name = 'output_type', id = 3, kind = 'scalar', proto_type = 'string'},
{name = 'client_streaming', id = 5, kind = 'scalar', proto_type = 'bool'},
{name = 'server_streaming', id = 6, kind = 'scalar', proto_type = 'bool'},
},
}
M.ServiceDescriptorProto = {
name = 'google.protobuf.ServiceDescriptorProto',
fields = {
{name = 'name', id = 1, kind = 'scalar', proto_type = 'string'},
{name = 'method', id = 2, kind = 'message',
message = M.MethodDescriptorProto, repeated = true},
},
}
-- DescriptorProto recurses through nested_type. We pre-declare the table,
-- then patch in the recursive reference.
M.DescriptorProto = {name = 'google.protobuf.DescriptorProto'}
M.DescriptorProto.fields = {
{name = 'name', id = 1, kind = 'scalar', proto_type = 'string'},
{name = 'field', id = 2, kind = 'message', message = M.FieldDescriptorProto, repeated = true},
{name = 'nested_type', id = 3, kind = 'message', message = M.DescriptorProto, repeated = true},
{name = 'enum_type', id = 4, kind = 'message', message = M.EnumDescriptorProto, repeated = true},
{name = 'options', id = 7, kind = 'message', message = M.MessageOptions},
{name = 'oneof_decl', id = 8, kind = 'message', message = M.OneofDescriptorProto, repeated = true},
}
M.FileDescriptorProto = {
name = 'google.protobuf.FileDescriptorProto',
fields = {
{name = 'name', id = 1, kind = 'scalar', proto_type = 'string'},
{name = 'package', id = 2, kind = 'scalar', proto_type = 'string'},
{name = 'dependency', id = 3, kind = 'scalar', proto_type = 'string', repeated = true, packed = false},
{name = 'message_type', id = 4, kind = 'message', message = M.DescriptorProto, repeated = true},
{name = 'enum_type', id = 5, kind = 'message', message = M.EnumDescriptorProto, repeated = true},
{name = 'service', id = 6, kind = 'message', message = M.ServiceDescriptorProto, repeated = true},
{name = 'syntax', id = 12, kind = 'scalar', proto_type = 'string'},
},
}
M.FileDescriptorSet = {
name = 'google.protobuf.FileDescriptorSet',
fields = {
{name = 'file', id = 1, kind = 'message',
message = M.FileDescriptorProto, repeated = true},
},
}
-- Finalize bottom-up. Order matters only in that we should finalize a
-- descriptor before any descriptor that references it as a message field;
-- the codec's compile_readers walks field.message at compile time.
finalize(M.FieldOptions)
finalize(M.MessageOptions)
finalize(M.FieldDescriptorProto)
finalize(M.OneofDescriptorProto)
finalize(M.EnumValueDescriptorProto)
finalize(M.EnumDescriptorProto)
finalize(M.MethodDescriptorProto)
finalize(M.ServiceDescriptorProto)
finalize(M.DescriptorProto)
finalize(M.FileDescriptorProto)
finalize(M.FileDescriptorSet)
return M