PB.Schema behaviour (PB v0.1.0)

Copy Markdown View Source

Embeds a compiled PB schema into a module at compile time.

This is the compile-time counterpart to the runtime flow of reading a descriptor set, calling PB.decode_descriptor_set/1, and then PB.compile/1. Runtime schema maps remain fully supported; use this module when a schema is stable enough to travel with the compiled BEAM code.

Descriptor file

defmodule MyApp.Schema do
  use PB.Schema, descriptor: "priv/proto/schema.binpb"
end

The descriptor file must be a binary google.protobuf.FileDescriptorSet, such as one produced by:

protoc --descriptor_set_out=priv/proto/schema.binpb --include_imports your.proto

Relative descriptor paths are resolved from the compiler working directory (the Mix project root during normal Mix compilation). The generated module is marked with @external_resource, so Mix recompiles it when the descriptor file changes.

Add :projections to attach message-level adapters and structural term representations to the embedded schema:

defmodule MyApp.Schema do
  use PB.Schema,
    descriptor: "priv/proto/schema.binpb",
    projections: [
      {:"google.protobuf.Timestamp", adapter: MyApp.Timestamp.adapter()},
      {:"my.app.User", struct: MyApp.User},
      {:"my.app.Wrapper", unwrap: :value, preserved_unknown_fields: :reject},
      {:"my.app.Event", oneofs: [data: [representation: :identity]]}
    ]
end

Structural projections can also be declared in proto source with the elixir.pb.v1 custom options. Use compile-time :projections only when attaching adapters or compiling overrides for third-party schemas or generated descriptor sets you do not own.

Descriptor set map

For hand-authored schemas or tests, pass the decoded descriptor set map directly:

defmodule MyApp.Schema do
  use PB.Schema,
    descriptor_set: %{
      file: [
        %{
          name: "greeter.proto",
          package: :greeter,
          syntax: :proto3,
          message_type: [
            %{
              name: :HelloRequest,
              field: [
                %{name: :name, number: 1, type: :TYPE_STRING, label: :LABEL_OPTIONAL}
              ]
            }
          ]
        }
      ]
    }
end

Generated API

A schema module exposes:

The top-level PB, PB.Validate, and PB.JSON entry points accept the schema module directly in place of a compiled schema map.

Introspection

This module also exposes lookup helpers that return public PB.Schema.Info structs — use these instead of reading the compiled-schema map directly:

Every lookup accepts either a compiled schema map or a use PB.Schema module. The bang variants raise PB.SchemaError (with kind: :unknown_* and operation: :introspect) on miss; the fetch_* variants return {:ok, info} | :error. The returned Info structs are the public stable surface — the compiled-schema internals may change without notice.

Summary

Functions

Looks up an enum by fully-qualified name, raising PB.SchemaError with kind: :unknown_enum if the enum is not in the schema.

Looks up an extension by fully-qualified name, raising PB.SchemaError with kind: :unknown_extension if the extension is not in the schema.

Looks up an enum by fully-qualified name, returning {:ok, %PB.Schema.Info.Enum{}} or :error.

Looks up an extension by fully-qualified name, returning {:ok, %PB.Schema.Info.Field{}} or :error.

Looks up a message by fully-qualified name, returning {:ok, %PB.Schema.Info.Message{}} or :error.

Looks up a service by fully-qualified name, returning {:ok, %PB.Schema.Info.Service{}} or :error.

Returns the fully-qualified names of every enum in schema_source, sorted alphabetically.

Returns the fully-qualified names of every extension in schema_source, sorted alphabetically.

Returns the fully-qualified names of every message in schema_source, sorted alphabetically.

Returns the fully-qualified names of every service in schema_source, sorted alphabetically.

Looks up a message by fully-qualified name, raising PB.SchemaError with kind: :unknown_message if the message is not in the schema.

Looks up a service by fully-qualified name, raising PB.SchemaError with kind: :unknown_service if the service is not in the schema.

Functions

enum!(schema_source, name)

Looks up an enum by fully-qualified name, raising PB.SchemaError with kind: :unknown_enum if the enum is not in the schema.

extension!(schema_source, name)

Looks up an extension by fully-qualified name, raising PB.SchemaError with kind: :unknown_extension if the extension is not in the schema.

fetch_enum(schema_source, name)

@spec fetch_enum(PB.schema_source(), PB.enum_name()) ::
  {:ok, PB.Schema.Info.Enum.t()} | :error

Looks up an enum by fully-qualified name, returning {:ok, %PB.Schema.Info.Enum{}} or :error.

fetch_extension(schema_source, name)

@spec fetch_extension(PB.schema_source(), PB.extension_name()) ::
  {:ok, PB.Schema.Info.Field.t()} | :error

Looks up an extension by fully-qualified name, returning {:ok, %PB.Schema.Info.Field{}} or :error.

fetch_message(schema_source, name)

@spec fetch_message(PB.schema_source(), PB.message_name()) ::
  {:ok, PB.Schema.Info.Message.t()} | :error

Looks up a message by fully-qualified name, returning {:ok, %PB.Schema.Info.Message{}} or :error.

fetch_service(schema_source, name)

@spec fetch_service(PB.schema_source(), PB.service_name()) ::
  {:ok, PB.Schema.Info.Service.t()} | :error

Looks up a service by fully-qualified name, returning {:ok, %PB.Schema.Info.Service{}} or :error.

list_enums(schema_source)

@spec list_enums(PB.schema_source()) :: [PB.enum_name()]

Returns the fully-qualified names of every enum in schema_source, sorted alphabetically.

list_extensions(schema_source)

@spec list_extensions(PB.schema_source()) :: [PB.extension_name()]

Returns the fully-qualified names of every extension in schema_source, sorted alphabetically.

list_messages(schema_source)

@spec list_messages(PB.schema_source()) :: [PB.message_name()]

Returns the fully-qualified names of every message in schema_source, sorted alphabetically.

schema_source is either a compiled schema map or a module that use PB.Schema.

list_services(schema_source)

@spec list_services(PB.schema_source()) :: [PB.service_name()]

Returns the fully-qualified names of every service in schema_source, sorted alphabetically.

message!(schema_source, name)

Looks up a message by fully-qualified name, raising PB.SchemaError with kind: :unknown_message if the message is not in the schema.

service!(schema_source, name)

Looks up a service by fully-qualified name, raising PB.SchemaError with kind: :unknown_service if the service is not in the schema.