Introduce mjpEncoder plugin architecture

Add a new mjpEncoder plugin type mirroring the existing mjpDecoder pattern.
Encoders serialize an mjSpec + mjModel to an mjResource for a given format.

New API functions:
- mjp_registerEncoder: globally register an encoder
- mjp_defaultEncoder: zero-initialize an encoder struct
- mjp_findEncoder: look up an encoder by filename extension or content type

The mjfEncode callback takes (mjSpec*, mjModel*, mjVFS*, mjResource*) and
returns 0 on success. Writing to mjResource keeps symmetry with the decoder
reading from mjResource and leaves the door open for writable resource providers.

PiperOrigin-RevId: 889187898
Change-Id: I180771b2255b91dea188ac5e2cdc3a8f0fb85364
This commit is contained in:
Sam Haves
2026-03-25 05:34:48 -07:00
committed by Copybara-Service
parent 2d33b50243
commit f5d3ce3451
15 changed files with 617 additions and 0 deletions
+13
View File
@@ -89,6 +89,19 @@ struct mjpDecoder {
};
typedef struct mjpDecoder mjpDecoder;
//---------------------------------- Encoder -------------------------------------------------------
typedef int (*mjfEncode)(const mjSpec* s, const mjModel* m, const mjVFS* vfs,
mjResource* resource);
struct mjpEncoder {
const char* content_type;
const char* extension;
mjfEncode encode;
mjfCloseResource close_resource;
};
typedef struct mjpEncoder mjpEncoder;
//---------------------------------- Plugins -------------------------------------------------------
typedef enum mjtPluginCapabilityBit_ {
+20
View File
@@ -135,6 +135,13 @@ MJAPI mjSpec* mj_parseXMLString(const char* xml, const mjVFS* vfs, char* error,
MJAPI mjSpec* mj_parse(const char* filename, const char* content_type,
const mjVFS* vfs, char* error, int error_sz);
// Encode spec/model to a file using a registered encoder.
// Returns the number of bytes written on success, -1 on failure.
// Nullable: m, vfs, error
MJAPI int mj_encode(const mjSpec* s, const mjModel* m, const char* filename,
const char* content_type, const mjVFS* vfs, char* error,
int error_sz);
// Compile spec to model.
// Nullable: vfs
MJAPI mjModel* mj_compile(mjSpec* s, const mjVFS* vfs);
@@ -1522,6 +1529,19 @@ MJAPI void mjp_defaultDecoder(mjpDecoder* decoder);
// If no match, return NULL.
MJAPI const mjpDecoder* mjp_findDecoder(const mjResource* resource, const char* content_type);
// Globally register an encoder. This function is thread-safe.
// If an identical mjpEncoder is already registered, this function does nothing.
// If a non-identical mjpEncoder with the same name is already registered, an mju_error is raised.
MJAPI void mjp_registerEncoder(const mjpEncoder* encoder);
// Set default resource encoder definition.
MJAPI void mjp_defaultEncoder(mjpEncoder* encoder);
// Return the encoder that matches against the content type or filename extension.
// If no match, return NULL.
MJAPI const mjpEncoder* mjp_findEncoder(const char* filename, const char* content_type);
//---------------------------------- Resources -----------------------------------------------------