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:
committed by
Copybara-Service
parent
2d33b50243
commit
f5d3ce3451
@@ -209,6 +209,7 @@ _OPAQUE_STRUCTS = [
|
||||
'mjTask',
|
||||
'mjThreadPool',
|
||||
'mjpDecoder',
|
||||
'mjpEncoder',
|
||||
'mjpResourceProvider',
|
||||
'mjsElement',
|
||||
'mjString',
|
||||
|
||||
@@ -41,6 +41,8 @@ _ANONYMOUS_KEY_PATTERN = re.compile(r'\d+:\d+(?=\))')
|
||||
_EXCLUDED = (
|
||||
'mjpDecoder',
|
||||
'mjpDecoder_',
|
||||
'mjpEncoder',
|
||||
'mjpEncoder_',
|
||||
'mjpPlugin',
|
||||
'mjpPlugin_',
|
||||
'mjpResourceProvider',
|
||||
|
||||
@@ -387,6 +387,57 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
||||
),
|
||||
doc='Parse spec from a file.',
|
||||
)),
|
||||
('mj_encode',
|
||||
FunctionDecl(
|
||||
name='mj_encode',
|
||||
return_type=ValueType(name='int'),
|
||||
parameters=(
|
||||
FunctionParameterDecl(
|
||||
name='s',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjSpec', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='m',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjModel', is_const=True),
|
||||
),
|
||||
nullable=True,
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='filename',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='content_type',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='vfs',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjVFS', is_const=True),
|
||||
),
|
||||
nullable=True,
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='error',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char'),
|
||||
),
|
||||
nullable=True,
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='error_sz',
|
||||
type=ValueType(name='int'),
|
||||
),
|
||||
),
|
||||
doc='Encode spec/model to a file using a registered encoder. Returns the number of bytes written on success, -1 on failure.', # pylint: disable=line-too-long
|
||||
)),
|
||||
('mj_compile',
|
||||
FunctionDecl(
|
||||
name='mj_compile',
|
||||
@@ -9600,6 +9651,56 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
||||
),
|
||||
doc='Return the resource provider with the prefix that matches against the resource name. If no match, return NULL.', # pylint: disable=line-too-long
|
||||
)),
|
||||
('mjp_registerEncoder',
|
||||
FunctionDecl(
|
||||
name='mjp_registerEncoder',
|
||||
return_type=ValueType(name='void'),
|
||||
parameters=(
|
||||
FunctionParameterDecl(
|
||||
name='encoder',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjpEncoder', is_const=True),
|
||||
),
|
||||
),
|
||||
),
|
||||
doc='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.', # pylint: disable=line-too-long
|
||||
)),
|
||||
('mjp_defaultEncoder',
|
||||
FunctionDecl(
|
||||
name='mjp_defaultEncoder',
|
||||
return_type=ValueType(name='void'),
|
||||
parameters=(
|
||||
FunctionParameterDecl(
|
||||
name='encoder',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjpEncoder'),
|
||||
),
|
||||
),
|
||||
),
|
||||
doc='Set default resource encoder definition.',
|
||||
)),
|
||||
('mjp_findEncoder',
|
||||
FunctionDecl(
|
||||
name='mjp_findEncoder',
|
||||
return_type=PointerType(
|
||||
inner_type=ValueType(name='mjpEncoder', is_const=True),
|
||||
),
|
||||
parameters=(
|
||||
FunctionParameterDecl(
|
||||
name='filename',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='content_type',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
),
|
||||
doc='Return the encoder that matches against the content type or filename extension. If no match, return NULL.', # pylint: disable=line-too-long
|
||||
)),
|
||||
('mju_openResource',
|
||||
FunctionDecl(
|
||||
name='mju_openResource',
|
||||
|
||||
Reference in New Issue
Block a user