Writing Packers
To write an OFRAK Packer, an OFRAK contributor needs to:
- Create a class that inherits from ofrak.component.component_packer.Packerwith a defined component config (ofrak.model.component_model.CC-- this will typically beNone);
- Implement the targetsto indicate what resource tags the packer targets;
- Implement the packmethod such that it correctly packs the resource's children or descendants.
The following is an example of a fully implemented OFRAK packer:
from dataclasses import dataclass
from ofrak.component.packer import Packer
from ofrak.service.resource_service_i import ResourceFilter
from ofrak.core.binary import GenericBinary
from ofrak.resource import Resource
from ofrak_type.range import Range
[ ... ]
@dataclass
class UImage(GenericBinary):
    async def get_header(self) -> UImageHeader:
        return await self.resource.get_only_child_as_view(
            UImageHeader, ResourceFilter.with_tags(UImageHeader)
        )
    async def get_body(self) -> UImageBody:
        return await self.resource.get_only_child_as_view(
            UImageBody, ResourceFilter.with_tags(UImageBody),
        )
[ ... ]
class UImagePacker(Packer[None]):
    """
    UImage packer.
    It patches the resource's header and body into a single binary, updating the CRC
    checksums and image data size in the header.
    """
    id = b"UImagePacker"
    targets = (UImage,)
    async def pack(self, resource: Resource, config=None):
        uimage_view = await resource.view_as(UImage)
        header = await uimage_view.get_header()
        uimage_body = await uimage_view.get_body()
        # Modify the header with the data size and CRC32
        uimage_body_bytes = await uimage_body.resource.get_data()
        ih_size = len(uimage_body_bytes)
        ih_dcrc = zlib.crc32(uimage_body_bytes)
        header_modifier_config = UImageHeaderModifierConfig(ih_size=ih_size, ih_dcrc=ih_dcrc)
        await header.resource.run(UImageHeaderModifier, header_modifier_config)
        resource.queue_patch(Range.from_size(UIMAGE_HEADER_LEN, ih_size), uimage_body_bytes)
This packer targets a UImage and repacks a UImageBody with updated UImageHeader values.
Handling External Dependencies
If the Packer makes use of tools that are not packaged in modules installable via pip from 
PyPI (commonly command-line tools), these dependencies must be explicitly declared as part of the 
packer's class declaration. See the Components Using External Tools doc for 
information on how to do that.
