Module factory

Module factory 

Source
Expand description

Dynamic-dispatching factories for readers with a lifetime.

§Motivation

FuncCodeReader already provides dynamic dispatching of read functions, but in some uses cases the reader has to reference some data (e.g., readers based on the same memory buffer). In this case, one would need to create a dispatching function pointer for each code and each reader because the lifetime of different readers make the function pointers incompatible.

The trait CodesReaderFactory solves this problem by providing a way to create a CodesRead with a lifetime that can reference data owned by the factory. This trait must be implemented by client applications.

At the point, one can create a FactoryFuncCodeReader depending on a specific CodesReaderFactory. The FactoryFuncCodeReader will store a function pointer with a generic lifetime that can be downcast to a specific lifetime. Thus, the function pointer is created just once at the creation of the FactoryFuncCodeReader, and can be reused to create FuncCodeReaders with any lifetime using FactoryFuncCodeReader::get.

§Implementation Notes

In principle, we would like to have inside a FactoryFuncCodeReader a field with type

for<'a> FuncCodeReader<E, CRF::CodesReader<'a>>

However, this is not possible in the Rust type system. We can however write the type

for<'a> fn(&mut CRF::CodesReader<'a>) -> Result<u64>

This workaround is not perfect as we cannot properly specify the error type:

Result<u64, <CRF::CodesReader<'a> as BitRead<E>>::Error>

The compiler here complains that the return type has a lifetime not constrained by the input arguments.

To work around this problem, we could add an otherwise useless associated type CodesReaderFactory::Error to the CodesReaderFactory trait, imposing that the error type of CodesReaderFactory::CodesReader is the same. Unfortunately, this requires that all users of the factory add a where constraint in which the error type is written explicitly.

To mitigate this problem, we provide instead a helper trait CodesReaderFactoryHelper that extends CodesReaderFactory; the helper trait contains an Error associated type and uses higher-rank trait bounds to bind the associated type to the error type of the CodesReaderFactory::CodesReader. The user can implement CodesReaderFactory on its own types and write trait bounds using CodesReaderFactoryHelper:

fn test<E: Endianness, CRF: CodesReaderFactoryHelper<E>>(factory: CRF)
{
    let reader = factory.new_reader();
    // do something with the reader
    // CRF::Error is the error type of CRF::CodesReader<'a>
}

Structs§

FactoryFuncCodeReader
A newtype depending on a CodesReaderFactory and containing a function pointer dispatching the read method for a code.

Traits§

CodesReaderFactory
A trait that models a type that can return a CodesRead that can reference data owned by the factory. The typical case is a factory that owns the bit stream, and returns a CodesRead that can read from it.
CodesReaderFactoryHelper
Extension helper trait for CodesReaderFactory.