.. _custom_driver:

Custom Drivers
==============

Drivers are the second ingredient necessary to read (custom) datasets. Where as
``URIResolver`` s (discussed previously) determines _what_ to read, drivers determine _how_ to
read and slice it. For example, you might use the same ``ConventionResolver`` to determine
which files to read, but different drivers to read `.nc`, `.zarr` or `.tiff` files. Vice
versa you might also use the same driver but different resolvers to read data depending
on how it was organised. It should therefore be noted that to read a particular dataset
it might be necessary to implement a custom resolver as well as a custom driver.

Implementing a Drivers
^^^^^^^^^^^^^^^^^^^^^^

To function drivers MUST at least implement the following function:

.. code-block:: python

    def read(
        self,
        uris: List[str],
        ...
    ) -> Any:
        ...

You may optionally also implement the following function as is appropriate:


.. code-block:: python

    def write(
        self,
        path: StrPath,
        data: Any,
        ...
    ):
        ...

As can be seen, `read` takes all of the URIs that the `resolver` has produced and will
attempt to read data from them in whatever way is appropriate. Since the contents of the
files themselves might also have to be sliced it is advisable to take the same arguments
as the resolver is able to take. Note that the signature of the functions may vary
between data types.