== contract.go ==
// Code generated by go-jsonrpc-codegen. DO NOT EDIT.

package echo

import (
	json "encoding/json"
	rpc "example.com/echo/rpc"
)

func pointer[T any](value T) *T { return &value }

// Contract returns a fresh prepared runtime contract.
func Contract() rpc.Contract {
	return rpc.Contract{
		Peers: []rpc.PeerContract{
			{Name: "client", Methods: []rpc.MethodContract{
			}},
			{Name: "server", Methods: []rpc.MethodContract{
				{Name: "echo", Kind: "request", Params: "named", Positional: []string{}, NullResult: false,
					RefersToCall: nil,
					ValidateParams: func(data json.RawMessage) error { _, err := decodeValue[Input](data); return err },
					ValidateResult: func(data json.RawMessage) error { _, err := decodeValue[Input](data); return err },
					Errors: []rpc.ErrorContract{
					},
				},
			}},
		},
	}
}
== errors.go ==
// Code generated by go-jsonrpc-codegen. DO NOT EDIT.

package echo

== peer.go ==
// Code generated by go-jsonrpc-codegen. DO NOT EDIT.

package echo

import (
	context "context"
	json "encoding/json"
	rpc "example.com/echo/rpc"
)

// Peer accepts local handlers and calls the other peer.
type Peer struct { *rpc.Peer }

// Handlers holds the typed functions that this peer accepts.
type Handlers struct {
}

func NewPeer(handlers Handlers, options rpc.Options) (*Peer, error) {
	runtime, err := rpc.NewPeer(Contract(), "client", options)
	if err != nil { return nil, err }
	peer := &Peer{Peer: runtime}
	return peer, nil
}

func (peer *Peer) EchoValue(ctx context.Context, input Input) (Input, error) {
	params := input
	var raw json.RawMessage
	err := peer.Peer.Call(ctx, "echo", params, &raw)
	if err != nil { var zero Input; return zero, decodeEchoValueError(err) }
	return decodeValue[Input](raw)
}

func decodeEchoValueError(err error) error {
	return err
}
== types.go ==
// Code generated by go-jsonrpc-codegen. DO NOT EDIT.

package echo

import (
	bytes "bytes"
	json "encoding/json"
	fmt "fmt"
)

func decodeValue[T any](data []byte) (T, error) {
	var value T
	if bytes.Equal(bytes.TrimSpace(data), []byte("null")) {
		if _, document := any(value).(json.RawMessage); !document { return value, fmt.Errorf("I expected a non-null value for construct `%T`.", value) }
	}
	if err := json.Unmarshal(data, &value); err != nil { return value, err }
	return value, nil
}

func decodeObject(data []byte, construct string) (map[string]json.RawMessage, error) {
	var raw map[string]json.RawMessage
	if err := json.Unmarshal(data, &raw); err != nil { return nil, err }
	if raw == nil { return nil, fmt.Errorf("I expected an object for construct `%s`.", construct) }
	return raw, nil
}

type Input struct {
	Text string `json:"text"`
}

func (value *Input) UnmarshalJSON(data []byte) error {
	raw, err := decodeObject(data, "example#Input")
	if err != nil { return err }
	var decoded Input
	if data, ok := raw["text"]; ok {
		member, err := decodeValue[string](data)
		if err != nil { return fmt.Errorf("I could not read member `example#Input$text`: %w", err) }
		decoded.Text = member
	} else { return fmt.Errorf("I expected required member `example#Input$text`.") }
	*value = decoded
	return nil
}
