{"id":15420272,"url":"https://github.com/jakebailey/plugingen","last_synced_at":"2025-11-12T22:31:06.757Z","repository":{"id":57553194,"uuid":"152931272","full_name":"jakebailey/plugingen","owner":"jakebailey","description":"Code generator for hashicorp/go-plugin","archived":false,"fork":false,"pushed_at":"2019-02-27T07:11:07.000Z","size":2915,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T04:23:10.388Z","etag":null,"topics":["code-generation","go","go-plugin","golang","rpc"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jakebailey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-14T02:10:22.000Z","updated_at":"2020-03-04T10:28:36.000Z","dependencies_parsed_at":"2022-09-07T17:21:01.646Z","dependency_job_id":null,"html_url":"https://github.com/jakebailey/plugingen","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jakebailey/plugingen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakebailey%2Fplugingen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakebailey%2Fplugingen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakebailey%2Fplugingen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakebailey%2Fplugingen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jakebailey","download_url":"https://codeload.github.com/jakebailey/plugingen/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jakebailey%2Fplugingen/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284122919,"owners_count":26951149,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-12T02:00:06.336Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-generation","go","go-plugin","golang","rpc"],"created_at":"2024-10-01T17:28:49.847Z","updated_at":"2025-11-12T22:31:06.720Z","avatar_url":"https://github.com/jakebailey.png","language":"Go","readme":"# plugingen\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/jakebailey/plugingen)](https://goreportcard.com/report/github.com/jakebailey/plugingen) [![Build Status](https://travis-ci.com/jakebailey/plugingen.svg?branch=master)](https://travis-ci.com/jakebailey/plugingen) [![Coverage Status](https://coveralls.io/repos/github/jakebailey/plugingen/badge.svg?branch=master)](https://coveralls.io/github/jakebailey/plugingen?branch=master)\n\n```\ngo get -u github.com/jakebailey/plugingen\n```\n\nplugingen generates code to use arbitrary interfaces with hashicorp's\n[go-plugin](https://github.com/hashicorp/go-plugin), including the use of `MuxBroker`\nto support other interfaces as arguments.\n\n\n## Caveats\n\nplugingen comes with a few caveats:\n\n- Values that aren't serializable by `encoding/gob` won't be handled correctly\n    (ignoring interface arguments, which are brokered).\n- Unless told otherwise, plugingen will wrap all errors in `plugin.BasicError`\n    to ensure they are serialized.\n- All types must be exported so that `net/rpc` will look at them. This means\n    that the package where the generated code lives will fill with types for\n    function parameters and return values. This is somewhat mitigated by\n    prepending `Z_` to generated types, but it's still noisy.\n- plugingen does not generate gRPC plugins. Maybe in the future.\n\n\n## An example\n\nGiven the following interface:\n\n```go\ntype Finder interface {\n\tFind(string, string) (int, bool)\n}\n```\n\nThis tool will generate the following (trimming out type declarations):\n\n```go\n// Find implements Find for the Finder interface.\nfunc (c *FinderRPCClient) Find(p0 string, p1 string) (int, bool) {\n\tparams := \u0026Z_Finder_FindParams{\n\t\tP0: p0,\n\t\tP1: p1,\n\t}\n\tresults := \u0026Z_Finder_FindResults{}\n\n\tif err := c.client.Call(\"Plugin.Find\", params, results); err != nil {\n\t\tlog.Println(\"RPC call to Finder.Find failed:\", err.Error())\n\t}\n\n\treturn results.R0, results.R1\n}\n\n// Find implements the server side of net/rpc calls to Find.\nfunc (s *FinderRPCServer) Find(params *Z_Finder_FindParams, results *Z_Finder_FindResults) error {\n\tr0, r1 := s.impl.Find(params.P0, params.P1)\n\n\tresults.R0 = r0\n\tresults.R1 = r1\n\n\treturn nil\n}\n```\n\n## A more complicated example\n\nTake this more complicated interface:\n\n```go\ntype Processor interface {\n\tProcess(io.ReadCloser)\n}\n```\n\nThis interface requires a function which accepts an `io.ReadCloser`,\nwhich cannot necessarily be serialized. plugingen produces this code to handle the interface:\n\n```go\n// Process implements Process for the Processor interface.\nfunc (c *ProcessorRPCClient) Process(p0 io.ReadCloser) {\n\tp0id := c.broker.NextId()\n\tgo c.broker.AcceptAndServe(p0id, NewReadCloserRPCServer(c.broker, p0))\n\n\tparams := \u0026Z_Processor_ProcessParams{P0ID: p0id}\n\tresults := new(interface{})\n\n\tif err := c.client.Call(\"Plugin.Process\", params, results); err != nil {\n\t\tlog.Println(\"RPC call to Processor.Process failed:\", err.Error())\n\t}\n}\n\n// Process implements the server side of net/rpc calls to Process.\nfunc (s *ProcessorRPCServer) Process(params *Z_Processor_ProcessParams, _ *interface{}) error {\n\tp0conn, err := s.broker.Dial(params.P0ID)\n\tif err != nil {\n\t\treturn err\n\t}\n\tp0RPCClient := rpc.NewClient(p0conn)\n\tdefer p0RPCClient.Close()\n\tp0client := NewReadCloserRPCClient(s.broker, p0RPCClient)\n\n\ts.impl.Process(p0client)\n\n\treturn nil\n}\n```\n\n## TODOs\n\n- Fix name collisions. If two interfaces are named the same thing, ignoring\n\tpackage names, then the output code will be broken. Interfaces coming from\n\toutside packages should include a prefix which summarizes their full name.\n- Support variadic arguments of interfaces. This is technically doable just by\n\tinserting a for loop to broker each.\n- Work out some quirks with printing type information. I use `Underlying()`\n\tquite a bit, which results in some cases where names get lost.\n- Allow replacement of `net/rpc` and `hashicorp/go-plugin`. `net/rpc` is\n\tfrozen, and doesn't have context support (and never will). The \"solution\"\n\tis to use gRPC, but that may pretty massively increase the footprint of\n\tthis generator (to keep in tune with backwards compatibility), so it may\n\tbe simpler to allow using a fork of `net/rpc` like\n\t[keegancsmith/rpc](https://github.com/keegancsmith/rpc) which allow for\n\tcontext. This would also require maintaining a fork of `go-plugin`.\n- Testing. This is largely untested.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakebailey%2Fplugingen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjakebailey%2Fplugingen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjakebailey%2Fplugingen/lists"}