# Contents of this crate, and how to implement support for a new detector system

This is a rough "map" on what is needed, from bottom to top:

- The most detector-specific piece is the background thread, which communicates
  in some way with the detector system. It's implemented as a background thread
  so it doesn't interfere with the main Python interpreter, which is running in
  the same process. If needed, the background thread can itself spawn more threads,
  for example if receiving the data can be parallelized.
- The interface to the background thread consists of a `Sender`/`Receiver` pair that
  communicates using standard messages. These are encapsulated into the
  `BackgroundThread` type.
- The messages are handled by the
  `GenericConnection<BackgroundThread, AcquisitionConfig>`. `GenericConnection`
  ultimately provides an API to control acquisitions and receive data.
- `GenericConnection` is rust-only (as `pyo3` bindings can't have type parameters),
  so there's the macro `impl_py_connection!(...)` which builds the Python-specific
  wrapper code for one concrete detector system. It also generates a specialized
  `FrameStackHandle` Python wrapper, which is used to return data back to the user.
- To access the data, also across process boundaries, there's a `GenericCamClient`,
  takes a `FrameStackHandle` and allows to access the data referenced by it, for
  example by decoding it into a user-provided buffer. The Python wrapper for that is
  generated by the `impl_py_cam_client!(...)` macro.
- For backwards-compatibility or experimentation, you may want to wrap the
  generated Python bindings into manually implemented wrappers, where you can
  provide compatibility- or detector-specific methods. The generated `Connection`
  type will also need a wrapper type, as that's where the background thread is spawned
  and detector-specific configuration details are passed down.
- There are a few adjacent traits that need to be implemented
  - `FrameMeta` is a central trait that contains per-frame metadata. Each stack of frames
    also contains a `Vec` of `FrameMeta`, which can be used, for example, in the decoder
    (see below).
  - `AcquisitionConfig` - the type returned in the `AcquisitionStart` message,
    often this contains information from the acquisition header.
  - `Decoder` - data is often stored in shared memory in encoded or compressed form,
    which allows to parallelize the decoding process, by running the decode on the
    process where data is consumed (usually a worker process from a pool). The decoder
    is used by the `GenericCamClient`. The module `common::decoder` contains a few
    useful helpers for decoding integers into various pixel formats.
  - `DetectorConnectionConfig` - this trait encapsulates the configuration needed
    to start the `GenericConnection` - at minimum, it knows the correct parameters
    to create the `SharedSlabAllocator`.
