// Generated by scripts/jsonrpc-go-runtime.mbtx. Do not edit.
///|
fn runtime_files() -> Map[String, String] {
{
"contract.go": "// Package rpc runs generated Smithy JSON-RPC peers.\npackage rpc\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n)\n\n// Contract holds the prepared two-peer protocol.\ntype Contract struct {\n\tPeers []PeerContract\n\tSession *SessionContract\n}\n\ntype PeerContract struct {\n\tName string\n\tMethods []MethodContract\n}\n\ntype MethodContract struct {\n\tName string\n\tKind string // request, notification, or either\n\tParams string // named, positional, or either\n\tPositional []string // Member wire names in parameter order.\n\tNullResult bool\n\tRefersToCall *CallReference\n\tErrors []ErrorContract\n\tValidateParams func(json.RawMessage) error\n\tValidateResult func(json.RawMessage) error\n}\n\ntype ErrorContract struct {\n\tCode int64\n\tDataRequired bool\n\tDataAbsent bool\n\tValidateData func(json.RawMessage) error\n}\n\ntype CallReference struct {\n\tWireName string\n\tPosition *int\n\tCode *int64\n}\n\ntype SessionContract struct {\n\tStates []string // The first state is the initial state.\n\tCapabilities []CapabilityContract\n\tMethods []MethodRule\n\tRefusals []StateRefusal\n\tCapabilityRefusal *int64\n}\n\ntype CapabilityContract struct {\n\tName string\n\tMethod string\n\tPointer string\n}\n\ntype MethodRule struct {\n\tReceiver string\n\tMethod string\n\tAllowed []string // nil permits every state.\n\tOnCall string\n\tOnSuccess string\n\tOnError string\n\tRequires []string\n\tCancels *CallReference\n}\n\ntype StateRefusal struct {\n\tState string\n\tCode int64\n}\n\n// Handler returns the wire result or an error. It can call the other peer.\ntype Handler func(context.Context, json.RawMessage) (any, error)\n\n// Bind decodes typed parameters. Unknown members are ignored.\nfunc Bind[I, O any](handler func(context.Context, I) (O, error)) Handler {\n\treturn func(ctx context.Context, params json.RawMessage) (any, error) {\n\t\tvar input I\n\t\tif len(params) == 0 {\n\t\t\tparams = json.RawMessage(`{}`)\n\t\t}\n\t\tif err := Decode(params, &input); err != nil {\n\t\t\treturn nil, NewError(-32602, \"I expected valid RPC parameters\", nil)\n\t\t}\n\t\treturn handler(ctx, input)\n\t}\n}\n",
"error.go": "package rpc\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"go.lsp.dev/jsonrpc2\"\n)\n\n// Error is a JSON-RPC error with exact, optional data.\ntype Error struct {\n\tCode int64 `json:\"code\"`\n\tMessage string `json:\"message\"`\n\tData json.RawMessage `json:\"data,omitempty\"`\n}\n\nfunc (e *Error) Error() string { return e.Message }\nfunc NewError(code int64, message string, data any) *Error {\n\te := &Error{Code: code, Message: message}\n\tif data != nil {\n\t\traw, err := json.Marshal(data)\n\t\tif err != nil {\n\t\t\treturn &Error{Code: -32603, Message: \"I could not encode the RPC error data\"}\n\t\t}\n\t\te.Data = raw\n\t}\n\treturn e\n}\nfunc wireError(err error) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\terr = modeledError(err)\n\tvar e *Error\n\tif errors.As(err, &e) {\n\t\treturn &jsonrpc2.Error{Code: jsonrpc2.Code(e.Code), Message: e.Message, Data: jsonrpc2.RawMessage(e.Data)}\n\t}\n\tvar upstream *jsonrpc2.Error\n\tif errors.As(err, &upstream) {\n\t\treturn upstream\n\t}\n\treturn &jsonrpc2.Error{Code: -32603, Message: \"I could not complete the RPC request\"}\n}\nfunc localError(err error) error {\n\tvar e *jsonrpc2.Error\n\tif errors.As(err, &e) {\n\t\treturn &Error{Code: int64(e.Code), Message: e.Message, Data: json.RawMessage(e.Data)}\n\t}\n\treturn err\n}\n\nfunc modeledError(err error) error {\n\tvar modeled interface{ RPCError() *Error }\n\tif errors.As(err, &modeled) {\n\t\tif rpcError := modeled.RPCError(); rpcError != nil {\n\t\t\treturn rpcError\n\t\t}\n\t}\n\treturn err\n}\n\n// UnmarshalJSON requires an integer code and a string message.\nfunc (e *Error) UnmarshalJSON(raw []byte) error {\n\tvar fields struct {\n\t\tCode Integer `json:\"code\"`\n\t\tMessage *string `json:\"message\"`\n\t\tData json.RawMessage `json:\"data\"`\n\t}\n\tif err := json.Unmarshal(raw, &fields); err != nil {\n\t\treturn err\n\t}\n\tif fields.Code == \"\" || fields.Message == nil {\n\t\treturn errors.New(\"I expected an RPC error code and message\")\n\t}\n\tcoefficient, exponent, ok := integerParts(string(fields.Code))\n\tif !ok || exponent.Cmp(big.NewInt(19)) > 0 {\n\t\treturn errors.New(\"I expected an RPC error code within int64\")\n\t}\n\tcount := int(exponent.Int64())\n\tif len(strings.TrimPrefix(coefficient, \"-\"))+count > 19 {\n\t\treturn errors.New(\"I expected an RPC error code within int64\")\n\t}\n\tcode, err := strconv.ParseInt(coefficient+strings.Repeat(\"0\", count), 10, 64)\n\tif err != nil {\n\t\treturn errors.New(\"I expected an RPC error code within int64\")\n\t}\n\t*e = Error{Code: code, Message: *fields.Message, Data: fields.Data}\n\treturn nil\n}\n",
"go.mod": "module github.com/moonrockz/smithy/runtimes/go\n\ngo 1.26\n\nrequire go.lsp.dev/jsonrpc2 v1.0.1\n\nrequire (\n\tgithub.com/coder/websocket v1.8.14\n\tgithub.com/go-json-experiment/json v0.0.0-20260601182631-00ed12fed2a6 // indirect\n)\n",
"go.sum": "github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=\ngithub.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=\ngithub.com/go-json-experiment/json v0.0.0-20260601182631-00ed12fed2a6 h1:nxP4pPoyqOAgX8lYDFCfl3DyKeXErCvSvhcyzwGV9CE=\ngithub.com/go-json-experiment/json v0.0.0-20260601182631-00ed12fed2a6/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\ngo.lsp.dev/jsonrpc2 v1.0.1 h1:JZAchpm6RcOuwEOnZ7kF3kA1EpEjdJZ/6rMSfOF3+F4=\ngo.lsp.dev/jsonrpc2 v1.0.1/go.mod h1:WN+TesqrPumBmUdsuWyn9DHq3zl4i85L/qG0NLdj8qg=\n",
"http.go": "package rpc\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/rand\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"mime\"\n\t\"net/http\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n)\n\nconst SessionHeader = \"Smithy-Session-Id\"\nconst HTTPPath = \"/rpc\"\nconst WebSocketPath = \"/ws\"\nconst maxMessageBytes = 1 << 20\nconst maxQueuedHTTPMessages = 32\n\n// PeerFactory creates a peer and registers its handlers for one session.\ntype PeerFactory func() (*Peer, error)\n\ntype httpMessage struct {\n\traw []byte\n\tfinal bool\n}\ntype httpExchange struct {\n\torder uint64\n\tfinal bool\n\tmessages chan httpMessage\n\tdone chan struct{}\n}\ntype httpSession struct {\n\twriteMu sync.Mutex\n\tnextExchange uint64\n\tpending []httpMessage\n\tpeer *Peer\n\tmu sync.Mutex\n\tinput chan []byte\n\tdone chan struct{}\n\texchanges map[string]*httpExchange\n\tonce sync.Once\n}\n\nfunc newHTTPSession(peer *Peer) *httpSession {\n\treturn &httpSession{peer: peer, input: make(chan []byte, 32), done: make(chan struct{}), exchanges: map[string]*httpExchange{}}\n}\nfunc (s *httpSession) ReadFrame(ctx context.Context) ([]byte, error) {\n\tselect {\n\tcase raw := <-s.input:\n\t\treturn raw, nil\n\tcase <-s.done:\n\t\treturn nil, io.EOF\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\t}\n}\nfunc (s *httpSession) WriteFrame(ctx context.Context, raw []byte) error {\n\ts.writeMu.Lock()\n\tdefer s.writeMu.Unlock()\n\tif err := ctx.Err(); err != nil {\n\t\treturn err\n\t}\n\tif len(raw) > maxMessageBytes {\n\t\treturn errors.New(\"I received an oversized HTTP message\")\n\t}\n\tvar fields map[string]json.RawMessage\n\tif err := json.Unmarshal(raw, &fields); err != nil {\n\t\treturn err\n\t}\n\t_, request := fields[\"method\"]\n\tvar id ID\n\tif request {\n\t\tid, _ = RequestID(ctx)\n\t} else {\n\t\t_ = json.Unmarshal(fields[\"id\"], &id)\n\t}\n\tmessage := httpMessage{raw: append([]byte(nil), raw...), final: !request}\n\ts.mu.Lock()\n\tselect {\n\tcase <-s.done:\n\t\ts.mu.Unlock()\n\t\treturn io.ErrClosedPipe\n\tdefault:\n\t}\n\texchange := s.exchanges[id.key()]\n\tif request && (exchange == nil || exchange.final) {\n\t\texchange = nil\n\t\tfor _, candidate := range s.exchanges {\n\t\t\tif !candidate.final && (exchange == nil || candidate.order > exchange.order) {\n\t\t\t\texchange = candidate\n\t\t\t}\n\t\t}\n\t\tif exchange == nil {\n\t\t\tif len(s.pending) >= maxQueuedHTTPMessages {\n\t\t\t\ts.mu.Unlock()\n\t\t\t\treturn errors.New(\"I reached the queued HTTP message limit\")\n\t\t\t}\n\t\t\ts.pending = append(s.pending, message)\n\t\t\ts.mu.Unlock()\n\t\t\treturn nil\n\t\t}\n\t}\n\tif exchange == nil || exchange.final {\n\t\ts.mu.Unlock()\n\t\treturn errors.New(\"I found no open HTTP request for the response\")\n\t}\n\tif message.final {\n\t\texchange.final = true\n\t}\n\ts.mu.Unlock()\n\tselect {\n\tcase exchange.messages <- message:\n\t\treturn nil\n\tcase <-exchange.done:\n\t\treturn errors.New(\"I found a closed HTTP request\")\n\tcase <-s.done:\n\t\treturn io.ErrClosedPipe\n\tcase <-ctx.Done():\n\t\treturn ctx.Err()\n\t}\n}\n\n// The new request stream receives queued messages before it enters dispatch.\nfunc (s *httpSession) openExchange(id ID) (*httpExchange, bool) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tkey := id.key()\n\tif s.exchanges[key] != nil {\n\t\treturn nil, false\n\t}\n\ts.nextExchange++\n\texchange := &httpExchange{order: s.nextExchange, messages: make(chan httpMessage, maxQueuedHTTPMessages), done: make(chan struct{})}\n\tfor _, message := range s.pending {\n\t\texchange.messages <- message\n\t}\n\ts.pending = nil\n\ts.exchanges[key] = exchange\n\treturn exchange, true\n}\nfunc (s *httpSession) Close() error {\n\ts.once.Do(func() { s.mu.Lock(); close(s.done); s.pending = nil; s.mu.Unlock() })\n\treturn nil\n}\nfunc (s *httpSession) submit(ctx context.Context, raw []byte) error {\n\tselect {\n\tcase s.input <- raw:\n\t\treturn nil\n\tcase <-s.done:\n\t\treturn io.ErrClosedPipe\n\tcase <-ctx.Done():\n\t\treturn ctx.Err()\n\t}\n}\n\n// HTTPServer keeps protocol state across Streamable HTTP POSTs.\n// Close releases all sessions. Mount it at HTTPPath.\ntype HTTPServer struct {\n\tmu sync.Mutex\n\tfactory PeerFactory\n\tsessions map[string]*httpSession\n\tclosed bool\n\t// MaxSessions bounds retained sessions. Zero uses 1024.\n\tMaxSessions int\n}\n\nfunc NewHTTPHandler(factory PeerFactory) *HTTPServer {\n\treturn &HTTPServer{factory: factory, sessions: map[string]*httpSession{}}\n}\nfunc (h *HTTPServer) Close() error {\n\th.mu.Lock()\n\tdefer h.mu.Unlock()\n\th.closed = true\n\tfor id, session := range h.sessions {\n\t\t_ = session.Close()\n\t\tdelete(h.sessions, id)\n\t}\n\treturn nil\n}\nfunc (h *HTTPServer) session(id string) (string, *httpSession, int) {\n\th.mu.Lock()\n\tdefer h.mu.Unlock()\n\tif h.closed {\n\t\treturn \"\", nil, http.StatusServiceUnavailable\n\t}\n\tif id != \"\" {\n\t\tsession := h.sessions[id]\n\t\tif session == nil {\n\t\t\treturn \"\", nil, http.StatusNotFound\n\t\t}\n\t\treturn id, session, 0\n\t}\n\tlimit := h.MaxSessions\n\tif limit == 0 {\n\t\tlimit = 1024\n\t}\n\tif len(h.sessions) >= limit {\n\t\treturn \"\", nil, http.StatusServiceUnavailable\n\t}\n\tif h.factory == nil {\n\t\treturn \"\", nil, http.StatusInternalServerError\n\t}\n\tpeer, err := h.factory()\n\tif err != nil || peer == nil {\n\t\treturn \"\", nil, http.StatusInternalServerError\n\t}\n\tvar token [24]byte\n\tif _, err := rand.Read(token[:]); err != nil {\n\t\treturn \"\", nil, http.StatusInternalServerError\n\t}\n\tid = hex.EncodeToString(token[:])\n\tsession := newHTTPSession(peer)\n\th.sessions[id] = session\n\tgo func() {\n\t\t_ = peer.Serve(context.Background(), session)\n\t\t_ = session.Close()\n\t\th.mu.Lock()\n\t\tdelete(h.sessions, id)\n\t\th.mu.Unlock()\n\t}()\n\treturn id, session, 0\n}\nfunc (h *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tif r.Method != http.MethodPost {\n\t\tw.Header().Set(\"Allow\", http.MethodPost)\n\t\thttp.Error(w, \"I require POST for JSON-RPC\", http.StatusMethodNotAllowed)\n\t\treturn\n\t}\n\tmedia, _, err := mime.ParseMediaType(r.Header.Get(\"Content-Type\"))\n\tif err != nil || media != \"application/json\" {\n\t\thttp.Error(w, \"I require application/json\", http.StatusUnsupportedMediaType)\n\t\treturn\n\t}\n\taccept := r.Header.Get(\"Accept\")\n\tif accept != \"\" && !strings.Contains(accept, \"text/event-stream\") && !strings.Contains(accept, \"application/json\") && !strings.Contains(accept, \"*/*\") {\n\t\thttp.Error(w, \"I require a JSON or SSE response type\", http.StatusNotAcceptable)\n\t\treturn\n\t}\n\tid, session, status := h.session(r.Header.Get(SessionHeader))\n\tif status != 0 {\n\t\thttp.Error(w, \"I cannot find or create the session\", status)\n\t\treturn\n\t}\n\tw.Header().Set(SessionHeader, id)\n\traw, err := io.ReadAll(http.MaxBytesReader(w, r.Body, maxMessageBytes))\n\tif err != nil {\n\t\thttp.Error(w, \"I cannot read the JSON-RPC message\", http.StatusRequestEntityTooLarge)\n\t\treturn\n\t}\n\tfields, problem := envelope(raw)\n\tif problem != nil {\n\t\tsession.rejectHTTP(w, raw, ID{}, problem)\n\t\treturn\n\t}\n\t_, request := fields[\"method\"]\n\tidRaw, hasID := fields[\"id\"]\n\tif !request || !hasID {\n\t\tif session.submit(r.Context(), raw) != nil {\n\t\t\thttp.Error(w, \"I cannot deliver the message\", http.StatusGone)\n\t\t\treturn\n\t\t}\n\t\tw.WriteHeader(http.StatusAccepted)\n\t\treturn\n\t}\n\tvar requestID ID\n\tif json.Unmarshal(idRaw, &requestID) != nil {\n\t\tsession.rejectHTTP(w, raw, ID{}, NewError(-32600, \"I require a string or integer request ID\", nil))\n\t\treturn\n\t}\n\tkey := requestID.key()\n\texchange, opened := session.openExchange(requestID)\n\tif !opened {\n\t\tsession.rejectHTTP(w, raw, requestID, NewError(-32600, \"I found an active RPC request with this ID\", nil))\n\t\treturn\n\t}\n\tdefer func() { session.mu.Lock(); delete(session.exchanges, key); session.mu.Unlock(); close(exchange.done) }()\n\tif err := session.submit(r.Context(), raw); err != nil {\n\t\thttp.Error(w, \"I cannot deliver the request\", http.StatusGone)\n\t\treturn\n\t}\n\tflusher, canFlush := w.(http.Flusher)\n\tif !canFlush {\n\t\thttp.Error(w, \"I cannot stream the response\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\tw.Header().Set(\"Content-Type\", \"text/event-stream\")\n\tw.Header().Set(\"Cache-Control\", \"no-cache\")\n\tw.WriteHeader(http.StatusOK)\n\tif _, err := io.WriteString(w, \": open\\n\\n\"); err != nil {\n\t\treturn\n\t}\n\tflusher.Flush()\n\tfor {\n\t\tselect {\n\t\tcase message := <-exchange.messages:\n\t\t\tif _, err := fmt.Fprintf(w, \"event: message\\ndata: %s\\n\\n\", message.raw); err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tflusher.Flush()\n\t\t\tif message.final {\n\t\t\t\treturn\n\t\t\t}\n\t\tcase <-r.Context().Done():\n\t\t\treturn\n\t\tcase <-session.done:\n\t\t\treturn\n\t\t}\n\t}\n}\n\ntype httpInboundFrame struct {\n\traw []byte\n\tprocessed chan struct{}\n}\n\n// HTTPTransport posts each outgoing message and reads JSON or SSE responses.\ntype HTTPTransport struct {\n\treadAck chan struct{}\n\tfailure error\n\tmu sync.Mutex\n\tfirst sync.Mutex\n\tclient *http.Client\n\tendpoint string\n\tsessionID string\n\tinput chan httpInboundFrame\n\tdone chan struct{}\n\tonce sync.Once\n\tctx context.Context\n\tcancel context.CancelFunc\n}\n\nfunc NewHTTPTransport(endpoint string, client *http.Client) *HTTPTransport {\n\tif client == nil {\n\t\tclient = http.DefaultClient\n\t}\n\tctx, cancel := context.WithCancel(context.Background())\n\treturn &HTTPTransport{client: client, endpoint: endpoint, input: make(chan httpInboundFrame, 32), done: make(chan struct{}), ctx: ctx, cancel: cancel}\n}\nfunc (t *HTTPTransport) SessionID() string { t.mu.Lock(); defer t.mu.Unlock(); return t.sessionID }\nfunc (t *HTTPTransport) ReadFrame(ctx context.Context) ([]byte, error) {\n\t// Reaching the next read proves the dispatcher processed the last frame.\n\t// Invalid requests, including batches, are answered before this point.\n\tt.mu.Lock()\n\tif t.readAck != nil {\n\t\tclose(t.readAck)\n\t\tt.readAck = nil\n\t}\n\tt.mu.Unlock()\n\tselect {\n\tcase frame := <-t.input:\n\t\tt.mu.Lock()\n\t\tt.readAck = frame.processed\n\t\tt.mu.Unlock()\n\t\treturn frame.raw, nil\n\tcase <-t.done:\n\t\tt.mu.Lock()\n\t\tfailure := t.failure\n\t\tt.mu.Unlock()\n\t\tif failure != nil {\n\t\t\treturn nil, failure\n\t\t}\n\t\treturn nil, io.EOF\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\t}\n}\nfunc (t *HTTPTransport) Close() error { t.once.Do(func() { t.cancel(); close(t.done) }); return nil }\nfunc (t *HTTPTransport) WriteFrame(ctx context.Context, raw []byte) error {\n\tvar fields map[string]json.RawMessage\n\tif err := json.Unmarshal(raw, &fields); err != nil {\n\t\treturn err\n\t}\n\tvar expected ID\n\tif _, request := fields[\"method\"]; request {\n\t\tif id, call := fields[\"id\"]; call {\n\t\t\tif err := json.Unmarshal(id, &expected); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\tt.first.Lock()\n\tt.mu.Lock()\n\tsession := t.sessionID\n\tt.mu.Unlock()\n\tif session != \"\" {\n\t\tt.first.Unlock()\n\t}\n\t// The transport context keeps an SSE call alive after its caller cancels.\n\trequestCtx, cancelRequest := context.WithCancel(t.ctx)\n\tstopCancel := context.AfterFunc(ctx, cancelRequest)\n\trequest, err := http.NewRequestWithContext(requestCtx, http.MethodPost, t.endpoint, bytes.NewReader(raw))\n\tif err != nil {\n\t\tstopCancel()\n\t\tcancelRequest()\n\t\tif session == \"\" {\n\t\t\tt.first.Unlock()\n\t\t}\n\t\treturn err\n\t}\n\tif err := ctx.Err(); err != nil {\n\t\tstopCancel()\n\t\tcancelRequest()\n\t\tif session == \"\" {\n\t\t\tt.first.Unlock()\n\t\t}\n\t\treturn err\n\t}\n\trequest.Header.Set(\"Content-Type\", \"application/json\")\n\trequest.Header.Set(\"Accept\", \"application/json, text/event-stream\")\n\tif session != \"\" {\n\t\trequest.Header.Set(SessionHeader, session)\n\t}\n\tresponse, err := t.client.Do(request)\n\tstopCancel()\n\tif err != nil {\n\t\tstopCancel()\n\t\tcancelRequest()\n\t\tif session == \"\" {\n\t\t\tt.first.Unlock()\n\t\t}\n\t\treturn err\n\t}\n\tnext := response.Header.Get(SessionHeader)\n\tt.mu.Lock()\n\tif next != \"\" {\n\t\tt.sessionID = next\n\t}\n\tt.mu.Unlock()\n\tif session == \"\" {\n\t\tt.first.Unlock()\n\t}\n\tif response.StatusCode == http.StatusAccepted {\n\t\tdefer cancelRequest()\n\t\t_ = response.Body.Close()\n\t\tif expected.IsValid() {\n\t\t\terr := missingHTTPReply(expected)\n\t\t\tt.fail(err)\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t}\n\tif response.StatusCode != http.StatusOK {\n\t\tdefer cancelRequest()\n\t\t_ = response.Body.Close()\n\t\treturn fmt.Errorf(\"I received HTTP status %d\", response.StatusCode)\n\t}\n\tgo func() {\n\t\tdefer cancelRequest()\n\t\tdefer response.Body.Close()\n\t\tif err := t.readResponse(response, expected); err != nil {\n\t\t\tt.fail(err)\n\t\t}\n\t}()\n\treturn nil\n}\nfunc (t *HTTPTransport) fail(err error) {\n\tt.mu.Lock()\n\tif t.failure == nil {\n\t\tt.failure = err\n\t}\n\tt.mu.Unlock()\n\t_ = t.Close()\n}\nfunc (t *HTTPTransport) deliver(raw []byte) (<-chan struct{}, error) {\n\tframe := httpInboundFrame{raw: append([]byte(nil), raw...), processed: make(chan struct{})}\n\tselect {\n\tcase t.input <- frame:\n\t\treturn frame.processed, nil\n\tcase <-t.done:\n\t\treturn nil, io.ErrClosedPipe\n\t}\n}\nfunc (t *HTTPTransport) readResponse(response *http.Response, expected ID) error {\n\tvar processed <-chan struct{}\n\tdeliver := func(raw []byte) error {\n\t\tvar err error\n\t\tprocessed, err = t.deliver(raw)\n\t\treturn err\n\t}\n\tincomplete := func() error {\n\t\tif processed != nil {\n\t\t\t// A peer can withhold headers for a rejection POST. It must not keep\n\t\t\t// the original call pending after its response stream has ended.\n\t\t\ttimer := time.NewTimer(5 * time.Second)\n\t\t\tdefer timer.Stop()\n\t\t\tselect {\n\t\t\tcase <-processed:\n\t\t\tcase <-t.done:\n\t\t\t\treturn io.ErrClosedPipe\n\t\t\tcase <-timer.C:\n\t\t\t}\n\t\t}\n\t\treturn missingHTTPReply(expected)\n\t}\n\tmedia, _, err := mime.ParseMediaType(response.Header.Get(\"Content-Type\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\tif media == \"application/json\" {\n\t\traw, err := io.ReadAll(io.LimitReader(response.Body, maxMessageBytes+1))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(raw) > maxMessageBytes {\n\t\t\treturn errors.New(\"I received an oversized JSON message\")\n\t\t}\n\t\tif err := deliver(raw); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !finalHTTPReply(raw, expected) {\n\t\t\treturn incomplete()\n\t\t}\n\t\treturn nil\n\t}\n\tif media != \"text/event-stream\" {\n\t\treturn errors.New(\"I received an unsupported response type\")\n\t}\n\tscanner := bufio.NewScanner(response.Body)\n\t// The line limit includes the data field prefix and CRLF framing.\n\tscanner.Buffer(make([]byte, 4096), maxMessageBytes+len(\"data: \")+len(\"\\r\\n\"))\n\tvar data []byte\n\thasData := false\n\tfinal := false\n\tflush := func() error {\n\t\tif !hasData {\n\t\t\treturn nil\n\t\t}\n\t\traw := data\n\t\tdata = nil\n\t\thasData = false\n\t\tfinal = finalHTTPReply(raw, expected)\n\t\tfields, problem := envelope(raw)\n\t\tif problem == nil {\n\t\t\tif _, request := fields[\"method\"]; !request && !final {\n\t\t\t\treturn missingHTTPReply(expected)\n\t\t\t}\n\t\t}\n\t\treturn deliver(raw)\n\t}\n\tfor scanner.Scan() {\n\t\tline := scanner.Text()\n\t\tif line == \"\" {\n\t\t\tif err := flush(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif final {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasPrefix(line, \"data:\") {\n\t\t\tvalue := strings.TrimPrefix(line, \"data:\")\n\t\t\tvalue = strings.TrimPrefix(value, \" \")\n\t\t\tadditional := len(value)\n\t\t\tif hasData {\n\t\t\t\tadditional++\n\t\t\t}\n\t\t\tif additional > maxMessageBytes-len(data) {\n\t\t\t\treturn errors.New(\"I received an oversized SSE message\")\n\t\t\t}\n\t\t\tif hasData {\n\t\t\t\tdata = append(data, '\\n')\n\t\t\t}\n\t\t\tdata = append(data, value...)\n\t\t\thasData = true\n\t\t}\n\t}\n\tif err := scanner.Err(); err != nil {\n\t\treturn err\n\t}\n\tif err := flush(); err != nil {\n\t\treturn err\n\t}\n\tif final {\n\t\treturn nil\n\t}\n\treturn incomplete()\n}\n\nfunc finalHTTPReply(raw []byte, expected ID) bool {\n\tif !expected.IsValid() {\n\t\treturn false\n\t}\n\tfields, problem := envelope(raw)\n\tif problem != nil {\n\t\treturn false\n\t}\n\tif _, request := fields[\"method\"]; request {\n\t\treturn false\n\t}\n\tvar id ID\n\treturn json.Unmarshal(fields[\"id\"], &id) == nil && id.key() == expected.key()\n}\nfunc missingHTTPReply(id ID) error {\n\treturn fmt.Errorf(\"I expected the final HTTP response for request %s\", id.String())\n}\n\n// Adapter-level rejections keep the same JSONL record shape as dispatch.\nfunc (s *httpSession) rejectHTTP(w http.ResponseWriter, received []byte, id ID, problem *Error) {\n\traw, _ := json.Marshal(struct {\n\t\tVersion string `json:\"jsonrpc\"`\n\t\tID ID `json:\"id\"`\n\t\tError *Error `json:\"error\"`\n\t}{\"2.0\", id, problem})\n\tif err := s.peer.log(\"recv\", received); err != nil {\n\t\thttp.Error(w, \"I could not write the RPC log\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\tif err := s.peer.log(\"send\", raw); err != nil {\n\t\thttp.Error(w, \"I could not write the RPC log\", http.StatusInternalServerError)\n\t\treturn\n\t}\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\t_, _ = w.Write(raw)\n}\n",
"number.go": "package rpc\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"math/big\"\n\t\"regexp\"\n\t\"strings\"\n)\n\nvar numberSyntax = regexp.MustCompile(`^-?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][+-]?[0-9]+)?$`)\n\n// Number keeps the exact JSON text of a Smithy bigDecimal.\ntype Number string\n\nfunc NewNumber(text string) (Number, error) {\n\tif !numberSyntax.MatchString(text) {\n\t\treturn \"\", errors.New(\"I expected a JSON number\")\n\t}\n\treturn Number(text), nil\n}\nfunc (n Number) MarshalJSON() ([]byte, error) { v, err := NewNumber(string(n)); return []byte(v), err }\nfunc (n *Number) UnmarshalJSON(data []byte) error {\n\tv, err := NewNumber(string(bytes.TrimSpace(data)))\n\tif err == nil {\n\t\t*n = v\n\t}\n\treturn err\n}\n\n// Integer keeps the exact JSON text of a Smithy bigInteger.\ntype Integer string\n\nfunc NewInteger(text string) (Integer, error) {\n\tif _, _, valid := integerParts(text); !valid {\n\t\treturn \"\", errors.New(\"I expected an exact integer JSON number\")\n\t}\n\treturn Integer(text), nil\n}\nfunc (n Integer) MarshalJSON() ([]byte, error) {\n\tv, err := NewInteger(string(n))\n\treturn []byte(v), err\n}\nfunc (n *Integer) UnmarshalJSON(data []byte) error {\n\tv, err := NewInteger(string(bytes.TrimSpace(data)))\n\tif err == nil {\n\t\t*n = v\n\t}\n\treturn err\n}\n\n// Decode keeps numbers in document values as json.Number.\nfunc Decode(data []byte, target any) error {\n\tdecoder := json.NewDecoder(bytes.NewReader(data))\n\tdecoder.UseNumber()\n\tif err := decoder.Decode(target); err != nil {\n\t\treturn err\n\t}\n\tvar extra any\n\tif err := decoder.Decode(&extra); err != io.EOF {\n\t\treturn errors.New(\"I expected one JSON value\")\n\t}\n\treturn nil\n}\n\n// ID is a string or an integer of any size. Its JSON text is retained.\ntype ID struct{ text string }\n\nfunc StringID(text string) ID { data, _ := json.Marshal(text); return ID{text: string(data)} }\nfunc IntegerID(text string) (ID, error) {\n\tif _, err := NewInteger(text); err != nil {\n\t\treturn ID{}, err\n\t}\n\treturn ID{text: text}, nil\n}\nfunc (id ID) MarshalJSON() ([]byte, error) {\n\tif id.text == \"\" {\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn []byte(id.text), nil\n}\nfunc (id *ID) UnmarshalJSON(data []byte) error {\n\tdata = bytes.TrimSpace(data)\n\tif len(data) > 0 && data[0] == '\"' {\n\t\tvar text string\n\t\tif err := json.Unmarshal(data, &text); err != nil {\n\t\t\treturn err\n\t\t}\n\t\t*id = StringID(text)\n\t\treturn nil\n\t}\n\tvalue, err := IntegerID(string(data))\n\tif err == nil {\n\t\t*id = value\n\t}\n\treturn err\n}\nfunc (id ID) String() string { return id.text }\nfunc (id ID) IsValid() bool { return id.text != \"\" }\nfunc (id ID) key() string {\n\tif id.text == \"\" || id.text[0] == '\"' {\n\t\treturn id.text\n\t}\n\tcoefficient, exponent, _ := integerParts(id.text)\n\treturn coefficient + \"e\" + exponent.String()\n}\n\n// integerParts proves integrality without expanding a decimal exponent.\nfunc integerParts(text string) (string, *big.Int, bool) {\n\tif !numberSyntax.MatchString(text) {\n\t\treturn \"\", nil, false\n\t}\n\tnegative := strings.HasPrefix(text, \"-\")\n\tunsigned := strings.TrimPrefix(text, \"-\")\n\texponent := new(big.Int)\n\tif at := strings.IndexAny(unsigned, \"eE\"); at >= 0 {\n\t\texponent.SetString(strings.TrimPrefix(unsigned[at+1:], \"+\"), 10)\n\t\tunsigned = unsigned[:at]\n\t}\n\tif at := strings.IndexByte(unsigned, '.'); at >= 0 {\n\t\texponent.Sub(exponent, big.NewInt(int64(len(unsigned)-at-1)))\n\t\tunsigned = unsigned[:at] + unsigned[at+1:]\n\t}\n\tcoefficient := strings.TrimLeft(unsigned, \"0\")\n\tif coefficient == \"\" {\n\t\treturn \"0\", new(big.Int), true\n\t}\n\ttrimmed := strings.TrimRight(coefficient, \"0\")\n\texponent.Add(exponent, big.NewInt(int64(len(coefficient)-len(trimmed))))\n\tif exponent.Sign() < 0 {\n\t\treturn \"\", nil, false\n\t}\n\tif negative {\n\t\ttrimmed = \"-\" + trimmed\n\t}\n\treturn trimmed, exponent, true\n}\n",
"peer.go": "package rpc\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"sync\"\n\t\"time\"\n\n\t\"go.lsp.dev/jsonrpc2\"\n)\n\n// Options sets bounds and optional JSONL logging. Log must not be stdout.\ntype Options struct {\n\tLog io.Writer\n\tMaxActiveCalls int\n}\n\ntype pendingCall struct {\n\tresponseError *Error\n\ttracker *callTracker\n\trefusalCode *int64\n\tid ID\n\tmethod MethodContract\n\treceiver string\n\tincoming bool\n\tcancel context.CancelFunc\n\tcancelCode *int64\n\taccepted bool\n\trefused bool\n}\n\n// Peer shares one dispatcher and one session across a transport.\ntype Peer struct {\n\toutgoing map[string]jsonrpc2.ID\n\tmu sync.Mutex\n\tlogMu sync.Mutex\n\tlocal, remote string\n\tcontract Contract\n\tmethods map[string]map[string]MethodContract\n\trules map[string]MethodRule\n\thandlers map[string]Handler\n\tactive map[string]*pendingCall\n\tincoming map[jsonrpc2.ID]*pendingCall\n\tstate string\n\tcapabilities map[string]bool\n\toptions Options\n\tconn jsonrpc2.Conn\n\ttransport Transport\n\tserving bool\n\tready chan struct{}\n}\n\nfunc NewPeer(contract Contract, localPeer string, options Options) (*Peer, error) {\n\tif len(contract.Peers) != 2 {\n\t\treturn nil, errors.New(\"I expected two peers in the RPC contract\")\n\t}\n\tif options.Log == os.Stdout {\n\t\treturn nil, errors.New(\"I cannot write RPC logs to stdout\")\n\t}\n\tif options.MaxActiveCalls < 0 {\n\t\treturn nil, errors.New(\"I expected a positive active call limit\")\n\t}\n\tif options.MaxActiveCalls == 0 {\n\t\toptions.MaxActiveCalls = 1024\n\t}\n\tp := &Peer{outgoing: map[string]jsonrpc2.ID{}, local: localPeer, contract: contract, options: options, methods: map[string]map[string]MethodContract{}, rules: map[string]MethodRule{}, handlers: map[string]Handler{}, active: map[string]*pendingCall{}, incoming: map[jsonrpc2.ID]*pendingCall{}, capabilities: map[string]bool{}, ready: make(chan struct{})}\n\tfor _, peer := range contract.Peers {\n\t\tif peer.Name == \"\" || p.methods[peer.Name] != nil {\n\t\t\treturn nil, errors.New(\"I expected distinct nonempty RPC peer names\")\n\t\t}\n\t\tmethods := map[string]MethodContract{}\n\t\tfor _, m := range peer.Methods {\n\t\t\tif m.Name == \"\" {\n\t\t\t\treturn nil, errors.New(\"I expected a nonempty RPC method name\")\n\t\t\t}\n\t\t\tif _, ok := methods[m.Name]; ok {\n\t\t\t\treturn nil, errors.New(\"I expected distinct RPC method names\")\n\t\t\t}\n\t\t\tif m.Kind == \"\" {\n\t\t\t\tm.Kind = \"either\"\n\t\t\t}\n\t\t\tif m.Params == \"\" {\n\t\t\t\tm.Params = \"named\"\n\t\t\t}\n\t\t\tif m.Kind != \"request\" && m.Kind != \"notification\" && m.Kind != \"either\" {\n\t\t\t\treturn nil, errors.New(\"I expected a valid RPC method kind\")\n\t\t\t}\n\t\t\tif m.Params != \"named\" && m.Params != \"positional\" && m.Params != \"either\" {\n\t\t\t\treturn nil, errors.New(\"I expected a valid RPC parameter mode\")\n\t\t\t}\n\t\t\tmethods[m.Name] = m\n\t\t}\n\t\tp.methods[peer.Name] = methods\n\t\tif peer.Name != localPeer {\n\t\t\tp.remote = peer.Name\n\t\t}\n\t}\n\tif p.methods[localPeer] == nil {\n\t\treturn nil, errors.New(\"I expected the local peer in the RPC contract\")\n\t}\n\tif session := contract.Session; session != nil {\n\t\tif len(session.States) == 0 {\n\t\t\treturn nil, errors.New(\"I expected session states\")\n\t\t}\n\t\tstates := map[string]bool{}\n\t\tfor _, state := range session.States {\n\t\t\tif state == \"\" || states[state] {\n\t\t\t\treturn nil, errors.New(\"I expected distinct nonempty session states\")\n\t\t\t}\n\t\t\tstates[state] = true\n\t\t}\n\t\tp.state = session.States[0]\n\t\tfor _, rule := range session.Methods {\n\t\t\tif _, ok := p.methods[rule.Receiver][rule.Method]; !ok {\n\t\t\t\treturn nil, errors.New(\"I expected the session rule to name a known RPC method\")\n\t\t\t}\n\t\t\tkey := rule.Receiver + \"\\x00\" + rule.Method\n\t\t\tif _, ok := p.rules[key]; ok {\n\t\t\t\treturn nil, errors.New(\"I expected one session rule for each RPC method\")\n\t\t\t}\n\t\t\tfor _, state := range append(append([]string{}, rule.Allowed...), rule.OnCall, rule.OnSuccess, rule.OnError) {\n\t\t\t\tif state != \"\" && !states[state] {\n\t\t\t\t\treturn nil, errors.New(\"I expected the session rule to name a known state\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.rules[key] = rule\n\t\t}\n\t}\n\treturn p, nil\n}\n\nfunc (p *Peer) Register(method string, handler Handler) error {\n\tp.mu.Lock()\n\tdefer p.mu.Unlock()\n\tif _, ok := p.methods[p.local][method]; !ok {\n\t\treturn errors.New(\"I expected a known local RPC method\")\n\t}\n\tif handler == nil {\n\t\treturn errors.New(\"I expected an RPC handler\")\n\t}\n\tif p.handlers[method] != nil {\n\t\treturn errors.New(\"I found an RPC handler for this method\")\n\t}\n\tp.handlers[method] = handler\n\treturn nil\n}\n\nfunc (p *Peer) State() string { p.mu.Lock(); defer p.mu.Unlock(); return p.state }\nfunc (p *Peer) HasCapability(name string) bool {\n\tp.mu.Lock()\n\tdefer p.mu.Unlock()\n\treturn p.capabilities[name]\n}\n\n// Ready closes when Serve has started its dispatcher.\nfunc (p *Peer) Ready() <-chan struct{} { return p.ready }\n\n// Serve runs until the transport ends or ctx is canceled. It can run once.\nfunc (p *Peer) Serve(ctx context.Context, transport Transport) error {\n\tp.mu.Lock()\n\tif p.serving {\n\t\tp.mu.Unlock()\n\t\treturn errors.New(\"I started this RPC peer already\")\n\t}\n\tp.serving = true\n\tstream := &peerStream{peer: p, transport: transport}\n\tp.transport = transport\n\tp.conn = jsonrpc2.NewConn(stream, jsonrpc2.WithCodec(exactCodec{}))\n\tconn := p.conn\n\tp.mu.Unlock()\n\tconn.Go(ctx, p.handle)\n\tclose(p.ready)\n\tselect {\n\tcase <-ctx.Done():\n\t\tp.cancelAll()\n\t\t_ = transport.Close()\n\t\t_ = conn.Close()\n\tcase <-conn.Done():\n\t}\n\tp.cancelAll()\n\tif ctx.Err() != nil {\n\t\treturn ctx.Err()\n\t}\n\treturn conn.Err()\n}\n\nfunc (p *Peer) Close() error {\n\tp.mu.Lock()\n\tconn := p.conn\n\ttransport := p.transport\n\tp.mu.Unlock()\n\tp.cancelAll()\n\tif conn == nil {\n\t\treturn nil\n\t}\n\t// Close the transport before waiting for handlers that need a response.\n\tif transport != nil {\n\t\t_ = transport.Close()\n\t}\n\treturn conn.Close()\n}\n\nfunc (p *Peer) cancelAll() {\n\tp.mu.Lock()\n\tdefer p.mu.Unlock()\n\tfor _, call := range p.active {\n\t\tif call.cancel != nil {\n\t\t\tcall.cancel()\n\t\t}\n\t}\n}\n\ntype callTracker struct {\n\tmu sync.Mutex\n\tfailure *Error\n}\ntype callTrackerKey struct{}\ntype admissionCancelKey struct{}\ntype uncheckedKey struct{}\ntype callerIDKey struct{}\n\n// CallUnchecked sends a call without local state or capability checks.\n// Use it to test a receiver's refusal rules.\nfunc (p *Peer) CallUnchecked(ctx context.Context, method string, params, result any) error {\n\treturn p.Call(context.WithValue(ctx, uncheckedKey{}, true), method, params, result)\n}\n\n// CallWithID uses the supplied exact string or integer ID.\nfunc (p *Peer) CallWithID(ctx context.Context, id ID, method string, params, result any) error {\n\tif !id.IsValid() {\n\t\treturn NewError(-32600, \"I require a string or integer request ID\", nil)\n\t}\n\treturn p.Call(context.WithValue(ctx, callerIDKey{}, id), method, params, result)\n}\n\nfunc (p *Peer) Call(ctx context.Context, method string, params, result any) error {\n\traw, err := json.Marshal(params)\n\tif params == nil {\n\t\traw = nil\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.mu.Lock()\n\tm, ok := p.methods[p.remote][method]\n\tif !ok {\n\t\tp.mu.Unlock()\n\t\treturn NewError(-32601, \"I found no RPC method with this name\", nil)\n\t}\n\tif custom, ok := ctx.Value(callerIDKey{}).(ID); ok && p.active[activeKey(false, custom)] != nil {\n\t\tp.mu.Unlock()\n\t\treturn NewError(-32600, \"I found an active RPC request with this ID\", nil)\n\t}\n\t_, err = p.checkLocked(false, m, true, raw, ctx.Value(uncheckedKey{}) != true)\n\tconn := p.conn\n\tp.mu.Unlock()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif conn == nil {\n\t\treturn errors.New(\"I have not started this RPC peer\")\n\t}\n\tcallerCtx := ctx\n\twriteCtx, writeCancel := context.WithCancel(ctx)\n\tdefer writeCancel()\n\tctx = context.WithValue(writeCtx, admissionCancelKey{}, writeCancel)\n\ttracker := &callTracker{}\n\tctx = context.WithValue(ctx, callTrackerKey{}, tracker)\n\tvar payload any\n\tif len(raw) != 0 {\n\t\tpayload = json.RawMessage(raw)\n\t}\n\tid, err := conn.Call(ctx, method, payload, result)\n\tif callerCtx.Err() != nil && id.IsValid() {\n\t\tp.sendCancellation(callerCtx, id)\n\t}\n\ttracker.mu.Lock()\n\tfailure := tracker.failure\n\ttracker.mu.Unlock()\n\tif failure != nil {\n\t\treturn failure\n\t}\n\treturn localError(err)\n}\n\nfunc (p *Peer) Notify(ctx context.Context, method string, params any) error {\n\traw, err := json.Marshal(params)\n\tif params == nil {\n\t\traw = nil\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\tp.mu.Lock()\n\tm, ok := p.methods[p.remote][method]\n\tif !ok {\n\t\tp.mu.Unlock()\n\t\treturn NewError(-32601, \"I found no RPC method with this name\", nil)\n\t}\n\t_, err = p.checkLocked(false, m, false, raw, true)\n\tconn := p.conn\n\tp.mu.Unlock()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif conn == nil {\n\t\treturn errors.New(\"I have not started this RPC peer\")\n\t}\n\tvar payload any\n\tif len(raw) != 0 {\n\t\tpayload = json.RawMessage(raw)\n\t}\n\twriteCtx, cancel := context.WithCancel(ctx)\n\tdefer cancel()\n\twriteCtx = context.WithValue(writeCtx, admissionCancelKey{}, cancel)\n\treturn localError(conn.Notify(writeCtx, method, payload))\n}\n\nfunc (p *Peer) sendCancellation(ctx context.Context, wireID jsonrpc2.ID) {\n\tp.mu.Lock()\n\tvar method string\n\tvar rule CallReference\n\tfor _, r := range p.rules {\n\t\tif r.Receiver == p.remote && r.Cancels != nil {\n\t\t\tmethod, rule = r.Method, *r.Cancels\n\t\t\tbreak\n\t\t}\n\t}\n\tp.mu.Unlock()\n\tif method == \"\" {\n\t\treturn\n\t}\n\tid := upstreamID(wireID)\n\tif custom, ok := ctx.Value(callerIDKey{}).(ID); ok {\n\t\tid = custom\n\t}\n\tcancelCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\tdefer cancel()\n\t_ = p.Notify(cancelCtx, method, map[string]any{rule.WireName: id})\n}\n\ntype requestContextKey struct{}\ntype peerContextKey struct{}\n\nfunc RequestID(ctx context.Context) (ID, bool) {\n\tid, ok := ctx.Value(requestContextKey{}).(ID)\n\treturn id, ok\n}\nfunc PeerFromContext(ctx context.Context) *Peer {\n\tp, _ := ctx.Value(peerContextKey{}).(*Peer)\n\treturn p\n}\n\nfunc (p *Peer) handle(ctx context.Context, request *jsonrpc2.Request) (result any, err error) {\n\tdefer func() {\n\t\terr = localError(modeledError(err))\n\t\tvar failure *Error\n\t\tif request.IsCall() && errors.As(err, &failure) {\n\t\t\tp.mu.Lock()\n\t\t\tif call := p.incoming[request.ID()]; call != nil {\n\t\t\t\tcall.responseError = failure\n\t\t\t}\n\t\t\tp.mu.Unlock()\n\t\t}\n\t\terr = wireError(err)\n\t}()\n\tdispatchCtx := ctx\n\tp.mu.Lock()\n\tmethod, ok := p.methods[p.local][request.Method()]\n\tif !ok {\n\t\tp.mu.Unlock()\n\t\tif !request.IsCall() {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, NewError(-32601, \"I found no RPC method with this name\", nil)\n\t}\n\tparams := json.RawMessage(request.Params())\n\tnormalized, err := p.checkLocked(true, method, request.IsCall(), params, true)\n\tvar call *pendingCall\n\tif request.IsCall() {\n\t\tcall = p.incoming[request.ID()]\n\t}\n\tif err == nil {\n\t\tvar cancel context.CancelFunc\n\t\t// The upstream request context can be pooled after a refused call.\n\t\t// A child cancellation watcher must use the connection context.\n\t\tctx, cancel = context.WithCancel(jsonrpc2.DetachContext(dispatchCtx))\n\t\tif call == nil {\n\t\t\tcall = &pendingCall{method: method, receiver: p.local, incoming: true}\n\t\t}\n\t\terr = p.beginLocked(call, request.IsCall(), normalized, cancel)\n\t\tif err != nil {\n\t\t\tcancel()\n\t\t}\n\t}\n\thandler := p.handlers[request.Method()]\n\tp.mu.Unlock()\n\tif err != nil {\n\t\tif !request.IsCall() {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\t// Admission and state changes run in wire order before the read loop continues.\n\tjsonrpc2.Async(dispatchCtx)\n\tif call.cancel != nil {\n\t\tdefer call.cancel()\n\t}\n\tctx = context.WithValue(ctx, peerContextKey{}, p)\n\tif request.IsCall() {\n\t\tctx = context.WithValue(ctx, requestContextKey{}, call.id)\n\t}\n\tif handler == nil {\n\t\t// Cancellation works without an application handler.\n\t\tp.mu.Lock()\n\t\trule := p.rules[p.local+\"\\x00\"+method.Name]\n\t\tp.mu.Unlock()\n\t\tif rule.Cancels != nil {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, NewError(-32601, \"I found no RPC method with this name\", nil)\n\t}\n\tresult, err = handler(ctx, normalized)\n\tif errors.Is(err, context.Canceled) {\n\t\tp.mu.Lock()\n\t\tcode := call.cancelCode\n\t\tp.mu.Unlock()\n\t\tif code != nil {\n\t\t\terr = NewError(*code, \"I cancelled the RPC request\", nil)\n\t\t}\n\t}\n\tif !request.IsCall() {\n\t\treturn nil, nil\n\t}\n\tif err == nil {\n\t\tif method.NullResult {\n\t\t\tresult = nil\n\t\t}\n\t\traw, encodeErr := json.Marshal(result)\n\t\tif encodeErr != nil {\n\t\t\treturn nil, NewError(-32603, \"I could not produce a valid RPC result\", nil)\n\t\t}\n\t\tif method.ValidateResult != nil && method.ValidateResult(raw) != nil {\n\t\t\treturn nil, NewError(-32603, \"I could not produce a valid RPC result\", nil)\n\t\t}\n\t}\n\tif err != nil {\n\t\terr = p.validateError(call, err)\n\t}\n\treturn result, err\n}\n\ntype exactCodec struct{}\n\nfunc (exactCodec) Marshal(value any) ([]byte, error) { return json.Marshal(value) }\nfunc (exactCodec) Unmarshal(data []byte, value any) error { return Decode(data, value) }\n\nfunc activeKey(incoming bool, id ID) string { return fmt.Sprintf(\"%t:%s\", incoming, id.key()) }\n",
"session.go": "package rpc\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nfunc contains(values []string, value string) bool {\n\tfor _, found := range values {\n\t\tif found == value {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// normalizeParams converts positional wire parameters to member names.\nfunc normalizeParams(method MethodContract, raw json.RawMessage) (json.RawMessage, error) {\n\traw = bytes.TrimSpace(raw)\n\tif len(raw) == 0 {\n\t\treturn json.RawMessage(`{}`), nil\n\t}\n\tswitch raw[0] {\n\tcase '{':\n\t\tif method.Params == \"positional\" {\n\t\t\treturn nil, NewError(-32602, \"I expected positional RPC parameters\", nil)\n\t\t}\n\t\treturn append(json.RawMessage(nil), raw...), nil\n\tcase '[':\n\t\tif method.Params == \"named\" {\n\t\t\treturn nil, NewError(-32602, \"I expected named RPC parameters\", nil)\n\t\t}\n\t\tvar values []json.RawMessage\n\t\tif err := json.Unmarshal(raw, &values); err != nil {\n\t\t\treturn nil, NewError(-32602, \"I expected valid RPC parameters\", nil)\n\t\t}\n\t\tif len(values) > len(method.Positional) {\n\t\t\treturn nil, NewError(-32602, \"I found too many positional RPC parameters\", nil)\n\t\t}\n\t\tfields := map[string]json.RawMessage{}\n\t\tfor i, value := range values {\n\t\t\tfields[method.Positional[i]] = value\n\t\t}\n\t\treturn json.Marshal(fields)\n\tdefault:\n\t\treturn nil, NewError(-32602, \"I expected object or array RPC parameters\", nil)\n\t}\n}\n\nfunc (p *Peer) checkLocked(incoming bool, method MethodContract, isCall bool, raw json.RawMessage, checkSession bool) (json.RawMessage, error) {\n\tif (method.Kind == \"request\" && !isCall) || (method.Kind == \"notification\" && isCall) {\n\t\treturn nil, NewError(-32600, \"I expected the modeled RPC request kind\", nil)\n\t}\n\tparams, err := normalizeParams(method, raw)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif method.ValidateParams != nil {\n\t\tif err := method.ValidateParams(params); err != nil {\n\t\t\treturn nil, NewError(-32602, \"I expected valid RPC parameters\", nil)\n\t\t}\n\t}\n\treceiver := p.remote\n\tif incoming {\n\t\treceiver = p.local\n\t}\n\trule := p.rules[receiver+\"\\x00\"+method.Name]\n\tif checkSession && rule.Allowed != nil && !contains(rule.Allowed, p.state) {\n\t\tcode := int64(-32600)\n\t\tif p.contract.Session != nil {\n\t\t\tfor _, refusal := range p.contract.Session.Refusals {\n\t\t\t\tif refusal.State == p.state {\n\t\t\t\t\tcode = refusal.Code\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil, NewError(code, \"I cannot accept this RPC method in the current state\", nil)\n\t}\n\tfor _, capability := range rule.Requires {\n\t\tif checkSession && !p.capabilities[capability] {\n\t\t\tcode := int64(-32600)\n\t\t\tif p.contract.Session != nil && p.contract.Session.CapabilityRefusal != nil {\n\t\t\t\tcode = *p.contract.Session.CapabilityRefusal\n\t\t\t}\n\t\t\treturn nil, NewError(code, \"I require an advertised capability for this RPC method\", nil)\n\t\t}\n\t}\n\tif method.RefersToCall != nil {\n\t\tid, err := referenceID(params, *method.RefersToCall)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif p.active[activeKey(!incoming, id)] == nil {\n\t\t\tcode := int64(-32602)\n\t\t\tif method.RefersToCall.Code != nil {\n\t\t\t\tcode = *method.RefersToCall.Code\n\t\t\t}\n\t\t\treturn nil, NewError(code, \"I found no active RPC call for this reference\", nil)\n\t\t}\n\t}\n\tif rule.Cancels != nil {\n\t\tif _, err := referenceID(params, *rule.Cancels); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tif isCall {\n\t\tcount := 0\n\t\tfor _, call := range p.active {\n\t\t\tif call.incoming == incoming {\n\t\t\t\tcount++\n\t\t\t}\n\t\t}\n\t\tif count >= p.options.MaxActiveCalls {\n\t\t\treturn nil, NewError(-32603, \"I reached the active RPC call limit\", nil)\n\t\t}\n\t}\n\treturn params, nil\n}\n\nfunc referenceID(params json.RawMessage, rule CallReference) (ID, error) {\n\tvar fields map[string]json.RawMessage\n\tif err := json.Unmarshal(params, &fields); err != nil {\n\t\treturn ID{}, NewError(-32602, \"I expected a valid active RPC call reference\", nil)\n\t}\n\tvar id ID\n\tif err := json.Unmarshal(fields[rule.WireName], &id); err != nil {\n\t\treturn ID{}, NewError(-32602, \"I expected a valid active RPC call reference\", nil)\n\t}\n\treturn id, nil\n}\n\nfunc (p *Peer) beginLocked(call *pendingCall, isCall bool, params json.RawMessage, cancel context.CancelFunc) error {\n\tkey := activeKey(call.incoming, call.id)\n\tif isCall && p.active[key] != nil {\n\t\treturn NewError(-32600, \"I found an active RPC request with this ID\", nil)\n\t}\n\trule := p.rules[call.receiver+\"\\x00\"+call.method.Name]\n\tif !call.refused && rule.OnCall != \"\" {\n\t\tp.state = rule.OnCall\n\t}\n\tif !call.refused && rule.Cancels != nil {\n\t\tid, _ := referenceID(params, *rule.Cancels)\n\t\tif active := p.active[activeKey(call.incoming, id)]; active != nil {\n\t\t\tactive.cancelCode = rule.Cancels.Code\n\t\t\tif active.cancel != nil {\n\t\t\t\tactive.cancel()\n\t\t\t}\n\t\t}\n\t}\n\tcall.accepted = true\n\tcall.cancel = cancel\n\tif isCall {\n\t\tp.active[key] = call\n\t}\n\treturn nil\n}\n\nfunc (p *Peer) finishLocked(call *pendingCall, result json.RawMessage, failed bool) {\n\tif call == nil || !call.accepted {\n\t\treturn\n\t}\n\tdelete(p.active, activeKey(call.incoming, call.id))\n\tif call.refused {\n\t\treturn\n\t}\n\trule := p.rules[call.receiver+\"\\x00\"+call.method.Name]\n\tnext := rule.OnSuccess\n\tif failed {\n\t\tnext = rule.OnError\n\t}\n\tif next != \"\" {\n\t\tp.state = next\n\t}\n\tif failed || p.contract.Session == nil {\n\t\treturn\n\t}\n\tfor _, capability := range p.contract.Session.Capabilities {\n\t\tif capability.Method != call.method.Name {\n\t\t\tcontinue\n\t\t}\n\t\tvalue := resolvePointer(result, capability.Pointer)\n\t\tif len(value) != 0 && !bytes.Equal(value, []byte(\"false\")) && !bytes.Equal(value, []byte(\"null\")) {\n\t\t\tp.capabilities[capability.Name] = true\n\t\t}\n\t}\n}\n\nfunc resolvePointer(raw json.RawMessage, pointer string) json.RawMessage {\n\tif pointer == \"\" {\n\t\treturn raw\n\t}\n\tif !strings.HasPrefix(pointer, \"/\") {\n\t\treturn nil\n\t}\n\tfor _, token := range strings.Split(pointer[1:], \"/\") {\n\t\ttoken = strings.ReplaceAll(strings.ReplaceAll(token, \"~1\", \"/\"), \"~0\", \"~\")\n\t\traw = bytes.TrimSpace(raw)\n\t\tif len(raw) == 0 {\n\t\t\treturn nil\n\t\t}\n\t\tswitch raw[0] {\n\t\tcase '{':\n\t\t\tvar fields map[string]json.RawMessage\n\t\t\tif json.Unmarshal(raw, &fields) != nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\traw = fields[token]\n\t\tcase '[':\n\t\t\tvar values []json.RawMessage\n\t\t\tif json.Unmarshal(raw, &values) != nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tindex, err := strconv.Atoi(token)\n\t\t\tif err != nil || index < 0 || index >= len(values) || strconv.Itoa(index) != token {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\traw = values[index]\n\t\tdefault:\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn bytes.TrimSpace(raw)\n}\n\nfunc (p *Peer) validateError(call *pendingCall, err error) error {\n\terr = modeledError(err)\n\tvar rpcError *Error\n\tif !errors.As(err, &rpcError) {\n\t\treturn err\n\t}\n\t// Standard errors and the declared cancellation code need no data contract.\n\tif rpcError.Code >= -32768 && rpcError.Code <= -32000 {\n\t\tcode := rpcError.Code\n\t\tif code == -32700 || (code >= -32603 && code <= -32600) || (code >= -32099 && code <= -32000) {\n\t\t\treturn err\n\t\t}\n\t\treturn NewError(-32603, \"I expected a defined RPC protocol error code\", nil)\n\t}\n\tp.mu.Lock()\n\tcancelCode := call.cancelCode\n\tp.mu.Unlock()\n\tif cancelCode != nil && rpcError.Code == *cancelCode {\n\t\treturn err\n\t}\n\tfor _, contract := range call.method.Errors {\n\t\tif contract.Code != rpcError.Code {\n\t\t\tcontinue\n\t\t}\n\t\tpresent := len(rpcError.Data) != 0\n\t\tif (contract.DataRequired && !present) || (contract.DataAbsent && present) {\n\t\t\treturn NewError(-32603, \"I expected the modeled RPC error data\", nil)\n\t\t}\n\t\tif present && contract.ValidateData != nil && contract.ValidateData(rpcError.Data) != nil {\n\t\t\treturn NewError(-32603, \"I expected the modeled RPC error data\", nil)\n\t\t}\n\t\treturn err\n\t}\n\treturn NewError(-32603, \"I expected a modeled RPC application error\", nil)\n}\n",
"stream.go": "package rpc\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"sync\"\n\n\t\"go.lsp.dev/jsonrpc2\"\n)\n\ntype peerStream struct {\n\tpeer *Peer\n\ttransport Transport\n\twriteMu sync.Mutex\n\tsequence uint64\n}\n\nfunc upstreamID(id jsonrpc2.ID) ID {\n\tif text, ok := id.StringValue(); ok {\n\t\treturn StringID(text)\n\t}\n\tif number, ok := id.Number(); ok {\n\t\tresult, _ := IntegerID(strconv.FormatInt(number, 10))\n\t\treturn result\n\t}\n\treturn ID{}\n}\n\nfunc (s *peerStream) Read(ctx context.Context) (jsonrpc2.Message, int64, error) {\n\tfor {\n\t\traw, err := s.transport.ReadFrame(ctx)\n\t\tif err != nil {\n\t\t\ts.peer.cancelAll()\n\t\t\treturn nil, 0, err\n\t\t}\n\t\tif len(raw) > maxMessageBytes {\n\t\t\ts.peer.cancelAll()\n\t\t\treturn nil, 0, errors.New(\"I received an oversized RPC message\")\n\t\t}\n\t\tif err := s.peer.log(\"recv\", raw); err != nil {\n\t\t\treturn nil, 0, err\n\t\t}\n\t\tfields, problem := envelope(raw)\n\t\tif problem != nil {\n\t\t\tif err := s.reject(ctx, ID{}, problem); err != nil {\n\t\t\t\treturn nil, 0, err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif _, request := fields[\"method\"]; request {\n\t\t\tif params, present := fields[\"params\"]; present {\n\t\t\t\tparams = bytes.TrimSpace(params)\n\t\t\t\tif len(params) == 0 || (params[0] != '{' && params[0] != '[') {\n\t\t\t\t\tif idRaw, isCall := fields[\"id\"]; isCall {\n\t\t\t\t\t\tvar id ID\n\t\t\t\t\t\tcode := int64(-32602)\n\t\t\t\t\t\tif json.Unmarshal(idRaw, &id) != nil {\n\t\t\t\t\t\t\tcode = -32600\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif err := s.reject(ctx, id, NewError(code, \"I expected object or array RPC parameters\", nil)); err != nil {\n\t\t\t\t\t\t\treturn nil, 0, err\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tif idRaw, call := fields[\"id\"]; call {\n\t\t\t\tvar id ID\n\t\t\t\tif err := json.Unmarshal(idRaw, &id); err != nil {\n\t\t\t\t\tif err := s.reject(ctx, ID{}, NewError(-32600, \"I expected a string or integer RPC request ID\", nil)); err != nil {\n\t\t\t\t\t\treturn nil, 0, err\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\t// Internal aliases let the upstream dispatcher retain integers beyond int64.\n\t\t\t\ts.sequence++\n\t\t\t\talias := jsonrpc2.NewStringID(fmt.Sprintf(\"smithy:%d\", s.sequence))\n\t\t\t\taliasRaw, _ := json.Marshal(fmt.Sprintf(\"smithy:%d\", s.sequence))\n\t\t\t\tfields[\"id\"] = aliasRaw\n\t\t\t\tadjusted, _ := json.Marshal(fields)\n\t\t\t\tmessage, decodeErr := jsonrpc2.DecodeMessage(adjusted)\n\t\t\t\tif decodeErr != nil {\n\t\t\t\t\tif err := s.reject(ctx, id, NewError(-32600, \"I expected a JSON-RPC request\", nil)); err != nil {\n\t\t\t\t\t\treturn nil, 0, err\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tvar name string\n\t\t\t\t_ = json.Unmarshal(fields[\"method\"], &name)\n\t\t\t\tp := s.peer\n\t\t\t\tp.mu.Lock()\n\t\t\t\tp.incoming[alias] = &pendingCall{id: id, method: p.methods[p.local][name], receiver: p.local, incoming: true}\n\t\t\t\tp.mu.Unlock()\n\t\t\t\treturn message, int64(len(raw)), nil\n\t\t\t}\n\t\t\tmessage, err := jsonrpc2.DecodeMessage(raw)\n\t\t\tif err != nil {\n\t\t\t\tif err := s.reject(ctx, ID{}, NewError(-32600, \"I expected a JSON-RPC request\", nil)); err != nil {\n\t\t\t\t\treturn nil, 0, err\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn message, int64(len(raw)), nil\n\t\t}\n\t\tvar responseID ID\n\t\tif err := json.Unmarshal(fields[\"id\"], &responseID); err != nil {\n\t\t\treturn nil, 0, errors.New(\"I require a response ID\")\n\t\t}\n\t\tp := s.peer\n\t\tp.mu.Lock()\n\t\tinternalID, tracked := p.outgoing[responseID.key()]\n\t\tp.mu.Unlock()\n\t\tif !tracked {\n\t\t\treturn nil, 0, errors.New(\"I found no active call for the response\")\n\t\t}\n\t\tif number, ok := internalID.Number(); ok {\n\t\t\tfields[\"id\"] = json.RawMessage(strconv.FormatInt(number, 10))\n\t\t} else {\n\t\t\ttext, _ := internalID.StringValue()\n\t\t\tfields[\"id\"], _ = json.Marshal(text)\n\t\t}\n\t\tvar remoteError *Error\n\t\tif errorRaw, failed := fields[\"error\"]; failed {\n\t\t\tvar failure Error\n\t\t\tif err := Decode(errorRaw, &failure); err != nil {\n\t\t\t\treturn nil, 0, errors.New(\"I found an invalid response error\")\n\t\t\t}\n\t\t\tremoteError = &failure\n\t\t\tfields[\"error\"], _ = json.Marshal(&Error{Code: -32603, Message: failure.Message, Data: failure.Data})\n\t\t}\n\t\tadjusted, _ := json.Marshal(fields)\n\t\tmessage, err := jsonrpc2.DecodeMessage(adjusted)\n\t\tif err != nil {\n\t\t\treturn nil, 0, errors.New(\"I expected a valid JSON-RPC response\")\n\t\t}\n\t\tresponse, ok := message.(*jsonrpc2.Response)\n\t\tif !ok {\n\t\t\treturn nil, 0, errors.New(\"I expected a JSON-RPC response\")\n\t\t}\n\t\tp.mu.Lock()\n\t\tcall := p.active[activeKey(false, responseID)]\n\t\tif call == nil {\n\t\t\tp.mu.Unlock()\n\t\t\treturn nil, 0, errors.New(\"I found no active call for this RPC response\")\n\t\t}\n\t\tif response.Err() == nil {\n\t\t\tif call.method.NullResult && !bytes.Equal(bytes.TrimSpace(response.Result()), []byte(\"null\")) {\n\t\t\t\tp.mu.Unlock()\n\t\t\t\treturn nil, 0, errors.New(\"I expected a null RPC result\")\n\t\t\t}\n\t\t\tif call.method.ValidateResult != nil && call.method.ValidateResult(json.RawMessage(response.Result())) != nil {\n\t\t\t\tp.mu.Unlock()\n\t\t\t\treturn nil, 0, errors.New(\"I expected a valid RPC result\")\n\t\t\t}\n\t\t}\n\t\tif remoteError != nil && !call.refused {\n\t\t\tp.mu.Unlock()\n\t\t\tchecked := p.validateError(call, remoteError)\n\t\t\tif checked != remoteError {\n\t\t\t\treturn nil, 0, errors.New(\"I expected a modeled RPC response error\")\n\t\t\t}\n\t\t\tp.mu.Lock()\n\t\t}\n\t\tif call.refused && (remoteError == nil || (call.refusalCode != nil && remoteError.Code != *call.refusalCode)) {\n\t\t\tp.mu.Unlock()\n\t\t\treturn nil, 0, errors.New(\"I expected the modeled refusal error\")\n\t\t}\n\t\tif call.tracker != nil && remoteError != nil {\n\t\t\tcall.tracker.mu.Lock()\n\t\t\tcall.tracker.failure = remoteError\n\t\t\tcall.tracker.mu.Unlock()\n\t\t}\n\t\tp.finishLocked(call, json.RawMessage(response.Result()), response.Err() != nil)\n\t\tdelete(p.outgoing, responseID.key())\n\t\tp.mu.Unlock()\n\t\treturn message, int64(len(raw)), nil\n\t}\n}\n\nfunc (s *peerStream) Write(ctx context.Context, message jsonrpc2.Message) (int64, error) {\n\tif err := ctx.Err(); err != nil {\n\t\treturn 0, err\n\t}\n\ts.writeMu.Lock()\n\tdefer s.writeMu.Unlock()\n\traw, err := jsonrpc2.EncodeMessage(message)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tvar fields map[string]json.RawMessage\n\tif err := json.Unmarshal(raw, &fields); err != nil {\n\t\treturn 0, err\n\t}\n\tp := s.peer\n\tp.mu.Lock()\n\tif nameRaw, request := fields[\"method\"]; request {\n\t\tvar name string\n\t\t_ = json.Unmarshal(nameRaw, &name)\n\t\tmethod := p.methods[p.remote][name]\n\t\tidRaw, isCall := fields[\"id\"]\n\t\tvar id ID\n\t\tif isCall {\n\t\t\t_ = json.Unmarshal(idRaw, &id)\n\t\t}\n\t\tunchecked := ctx.Value(uncheckedKey{}) == true\n\t\tnormalized, err := p.checkLocked(false, method, isCall, fields[\"params\"], !unchecked)\n\t\tif err != nil {\n\t\t\tp.mu.Unlock()\n\t\t\treturn rejectAdmission(ctx, err)\n\t\t}\n\t\tinternalID := id\n\t\tif custom, ok := ctx.Value(callerIDKey{}).(ID); ok && isCall {\n\t\t\tid = custom\n\t\t\tfields[\"id\"], _ = json.Marshal(id)\n\t\t\traw, _ = json.Marshal(fields)\n\t\t}\n\t\tcall := &pendingCall{id: id, method: method, receiver: p.remote}\n\t\tcall.tracker, _ = ctx.Value(callTrackerKey{}).(*callTracker)\n\t\tif unchecked {\n\t\t\t_, policyErr := p.checkLocked(false, method, isCall, fields[\"params\"], true)\n\t\t\tcall.refused = policyErr != nil\n\t\t\tif failure, ok := policyErr.(*Error); ok {\n\t\t\t\tcall.refusalCode = &failure.Code\n\t\t\t}\n\t\t}\n\t\tif err := p.beginLocked(call, isCall, normalized, nil); err != nil {\n\t\t\tp.mu.Unlock()\n\t\t\treturn rejectAdmission(ctx, err)\n\t\t}\n\t\tif isCall {\n\t\t\tvar upstream jsonrpc2.ID\n\t\t\tif internalID.text[0] == '\"' {\n\t\t\t\tvar text string\n\t\t\t\t_ = json.Unmarshal([]byte(internalID.text), &text)\n\t\t\t\tupstream = jsonrpc2.NewStringID(text)\n\t\t\t} else {\n\t\t\t\tnumber, _ := strconv.ParseInt(internalID.text, 10, 64)\n\t\t\t\tupstream = jsonrpc2.NewNumberID(number)\n\t\t\t}\n\t\t\tp.outgoing[id.key()] = upstream\n\t\t}\n\t} else {\n\t\tvar alias string\n\t\t_ = json.Unmarshal(fields[\"id\"], &alias)\n\t\tkey := jsonrpc2.NewStringID(alias)\n\t\tcall := p.incoming[key]\n\t\tif call != nil {\n\t\t\tfields[\"id\"], _ = json.Marshal(call.id)\n\t\t\tif call.responseError != nil {\n\t\t\t\tfields[\"error\"], _ = json.Marshal(call.responseError)\n\t\t\t\tdelete(fields, \"result\")\n\t\t\t}\n\t\t\tp.finishLocked(call, fields[\"result\"], len(fields[\"error\"]) != 0)\n\t\t\tdelete(p.incoming, key)\n\t\t\traw, err = json.Marshal(fields)\n\t\t}\n\t}\n\tp.mu.Unlock()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tif err := s.send(ctx, raw); err != nil {\n\t\treturn 0, err\n\t}\n\treturn int64(len(raw)), nil\n}\n\nfunc (s *peerStream) send(ctx context.Context, raw []byte) error {\n\tif err := s.peer.log(\"send\", raw); err != nil {\n\t\treturn err\n\t}\n\t// Transport libraries may retain cancellation watchers after Write returns.\n\t// The upstream per-request context is pooled at that point.\n\treturn s.transport.WriteFrame(jsonrpc2.DetachContext(ctx), raw)\n}\nfunc (s *peerStream) reject(ctx context.Context, id ID, problem *Error) error {\n\ts.writeMu.Lock()\n\tdefer s.writeMu.Unlock()\n\traw, _ := json.Marshal(struct {\n\t\tVersion string `json:\"jsonrpc\"`\n\t\tID ID `json:\"id\"`\n\t\tError *Error `json:\"error\"`\n\t}{\"2.0\", id, problem})\n\treturn s.send(ctx, raw)\n}\nfunc (s *peerStream) Close() error { s.peer.cancelAll(); return s.transport.Close() }\n\nfunc envelope(raw []byte) (map[string]json.RawMessage, *Error) {\n\tif !json.Valid(raw) {\n\t\treturn nil, NewError(-32700, \"I could not parse the JSON-RPC message\", nil)\n\t}\n\tvar fields map[string]json.RawMessage\n\tif json.Unmarshal(raw, &fields) != nil || fields == nil {\n\t\treturn nil, NewError(-32600, \"I expected a JSON-RPC request\", nil)\n\t}\n\tif string(fields[\"jsonrpc\"]) != `\"2.0\"` {\n\t\treturn nil, NewError(-32600, \"I expected a JSON-RPC request\", nil)\n\t}\n\tif method, request := fields[\"method\"]; request {\n\t\tvar name string\n\t\tif len(bytes.TrimSpace(method)) == 0 || bytes.TrimSpace(method)[0] != '\"' || json.Unmarshal(method, &name) != nil {\n\t\t\treturn nil, NewError(-32600, \"I expected a string RPC method name\", nil)\n\t\t}\n\t\tif _, result := fields[\"result\"]; result {\n\t\t\treturn nil, NewError(-32600, \"I expected a JSON-RPC request\", nil)\n\t\t}\n\t\tif _, failure := fields[\"error\"]; failure {\n\t\t\treturn nil, NewError(-32600, \"I expected a JSON-RPC request\", nil)\n\t\t}\n\t} else {\n\t\t_, result := fields[\"result\"]\n\t\t_, failure := fields[\"error\"]\n\t\t_, id := fields[\"id\"]\n\t\tif !id || result == failure {\n\t\t\treturn nil, NewError(-32600, \"I expected a JSON-RPC response\", nil)\n\t\t}\n\t}\n\treturn fields, nil\n}\n\nfunc (p *Peer) log(direction string, raw []byte) error {\n\tif p.options.Log == nil {\n\t\treturn nil\n\t}\n\tif !json.Valid(raw) {\n\t\traw, _ = json.Marshal(string(raw))\n\t}\n\tline, err := json.Marshal(struct {\n\t\tDir string `json:\"dir\"`\n\t\tMessage json.RawMessage `json:\"message\"`\n\t}{direction, raw})\n\tif err != nil {\n\t\treturn err\n\t}\n\tline = append(line, '\\n')\n\tp.logMu.Lock()\n\tdefer p.logMu.Unlock()\n\t_, err = p.options.Log.Write(line)\n\treturn err\n}\n\n// A local refusal is not a failed transport. Cancel this write's private\n// context so the upstream connection does not mark its writer as broken.\nfunc rejectAdmission(ctx context.Context, err error) (int64, error) {\n\tif cancel, ok := ctx.Value(admissionCancelKey{}).(context.CancelFunc); ok {\n\t\tcancel()\n\t}\n\treturn 0, err\n}\n",
"transport.go": "package rpc\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"sync\"\n\n\t\"go.lsp.dev/jsonrpc2\"\n)\n\n// Transport carries one complete JSON-RPC message at a time.\n// ReadFrame has one reader. WriteFrame must permit concurrent calls.\n// Close must unblock ReadFrame.\ntype Transport interface {\n\tReadFrame(context.Context) ([]byte, error)\n\tWriteFrame(context.Context, []byte) error\n\tClose() error\n}\n\ntype headerFrames interface {\n\tReadFrame(context.Context) ([]byte, int64, error)\n\tWriteFrame(context.Context, []byte) (int64, error)\n\tClose() error\n}\n\ntype stdioTransport struct{ frames headerFrames }\n\n// Stdio uses the upstream Content-Length framer. Close closes reader.\nfunc Stdio(reader io.ReadCloser, writer io.Writer) Transport {\n\tstream := jsonrpc2.NewHeaderStream(&splitStream{reader: reader, writer: writer})\n\treturn &stdioTransport{frames: stream.(headerFrames)}\n}\nfunc (s *stdioTransport) ReadFrame(ctx context.Context) ([]byte, error) {\n\tdata, _, err := s.frames.ReadFrame(ctx)\n\treturn data, err\n}\nfunc (s *stdioTransport) WriteFrame(ctx context.Context, data []byte) error {\n\t_, err := s.frames.WriteFrame(ctx, data)\n\treturn err\n}\nfunc (s *stdioTransport) Close() error { return s.frames.Close() }\n\ntype splitStream struct {\n\treader io.ReadCloser\n\twriter io.Writer\n\tonce sync.Once\n\terr error\n}\n\nfunc (s *splitStream) Read(data []byte) (int, error) { return s.reader.Read(data) }\nfunc (s *splitStream) Write(data []byte) (int, error) { return s.writer.Write(data) }\nfunc (s *splitStream) Close() error { s.once.Do(func() { s.err = s.reader.Close() }); return s.err }\n",
"websocket.go": "package rpc\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\n\t\"github.com/coder/websocket\"\n)\n\ntype websocketTransport struct{ conn *websocket.Conn }\n\n// DialWebSocket opens a connection with one JSON-RPC message per text frame.\nfunc DialWebSocket(ctx context.Context, url string) (Transport, error) {\n\tconn, response, err := websocket.Dial(ctx, url, nil)\n\tif err != nil {\n\t\tif response != nil && response.Body != nil {\n\t\t\t_ = response.Body.Close()\n\t\t}\n\t\treturn nil, err\n\t}\n\tconn.SetReadLimit(maxMessageBytes)\n\treturn &websocketTransport{conn: conn}, nil\n}\nfunc (t *websocketTransport) ReadFrame(ctx context.Context) ([]byte, error) {\n\tkind, raw, err := t.conn.Read(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif kind != websocket.MessageText {\n\t\treturn nil, errors.New(\"I require a WebSocket text frame\")\n\t}\n\treturn raw, nil\n}\nfunc (t *websocketTransport) WriteFrame(ctx context.Context, raw []byte) error {\n\treturn t.conn.Write(ctx, websocket.MessageText, raw)\n}\nfunc (t *websocketTransport) Close() error { return t.conn.CloseNow() }\n\n// NewWebSocketHandler creates a separate peer for each WebSocket connection.\nfunc NewWebSocketHandler(factory PeerFactory) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tpeer, err := factory()\n\t\tif err != nil || peer == nil {\n\t\t\thttp.Error(w, \"I cannot create the peer\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tconn, err := websocket.Accept(w, r, nil)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tdefer conn.CloseNow()\n\t\tconn.SetReadLimit(maxMessageBytes)\n\t\t_ = peer.Serve(r.Context(), &websocketTransport{conn: conn})\n\t})\n}\n",
}
}