TypeInfo.h

// TypeInfo.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2012

@import "cxPersistStore.h"
@import "Ceda/cxObject/Object.h"

/*
TypeInfo
--------

A TypeInfo is intended to be used within IPersistable objects within a PersistStore in order to
efficiently record a reference to a type for which ReflectionByteCode and a TypeOps is defined. 
A TypeInfo variable is serialised as a variable length ssize_t, which is an index into the persistent 
TypeOpsMap.

The TypeInfo caches the binding to the TypeOps.
*/

namespace ceda
{
$class ReflectionByteCodeValue;

$struct+ BcTypeOps
{
    const ReflectionByteCodeValue* rbcv;
    const TypeOps* typeops;
};

$typedef+ ssize_t TypeOpsId;

template <typename T> ReflectionByteCode GetReflectionByteCode();

/*
Assumes the PSpace has been set in TLS. Calls GetTypeOps() on the associated PersistStore for the
given tid.

This can be called during deserialisation of an IPersistable object!  It is often the case that an 
IPersistable object performs the following sequence of operations within its deserialise function:

    1.  Deserialise TypeOpsIds
    2.  Call GetPersistStoreTypeOps() to map the TypeOpsIds to TypeOps
    3.  Use the TypeOps to deserialise variables with dynamically defined data types within the 
        IPersistable object.

todo: currently the implementation asserts the PSpace has been set in TLS and asserts the given tid
is found in the PersistStore.  We really need to deal with these errors at run time.
*/
@api const TypeOps* GetPersistStoreTypeOps(TypeOpsId tid);

@api TypeOpsId GetPersistStoreTypeOpsId(ReflectionByteCode rbc);

template <typename T>
inline TypeOpsId GetPersistStoreTypeOpsId()
{
    return GetPersistStoreTypeOpsId(GetReflectionByteCode<T>()); 
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// TypeInfo

struct @api TypeInfo
{
    void Set(const ReflectionByteCodeValue& rbcv);
    void Set(const ReflectionByteCode rbc);
    const ReflectionByteCodeValue& GetReflectionByteCodeValue() const;

    TypeOpsId tid = 0;
    const TypeOps* typeOps = nullptr;
};

template<typename Archive>
inline void Serialise(Archive& ar, const TypeInfo& ti)
{
    cxAssert(1 <= ti.tid);
    SerialiseVariableLengthUint(ar, ti.tid);
}

template<typename Archive>
inline void Deserialise(Archive& ar, TypeInfo& ti)
{
    DeserialiseVariableLengthUint(ar,ti.tid);
    cxAssert(1 <= ti.tid);
    ti.typeOps = GetPersistStoreTypeOps(ti.tid);
}

} // namespace ceda