Raw File
slang-serialize-types.h
// slang-serialize-types.h
#ifndef SLANG_SERIALIZE_TYPES_H
#define SLANG_SERIALIZE_TYPES_H

#include "../core/slang-riff.h"
#include "../core/slang-string-slice-pool.h"
#include "../core/slang-array-view.h"

//#include "slang-name.h"
//#include "slang-source-loc.h"

namespace Slang {

// An enumeration of types that can be set
enum class SerialExtraType
{
    SourceLocReader,
    SourceLocWriter,
    CountOf,
};

// Options for IR/AST/Debug serialization

struct SerialOptionFlag
{
    typedef uint32_t Type;
    enum Enum : Type
    {
        RawSourceLocation   = 0x01,     ///< If set will store directly SourceLoc - only useful if current source locs will be identical when read in (typically this is *NOT* the case)
        SourceLocation      = 0x02,     ///< If set will output SourceLoc information, that can be reconstructed when read after being stored.
        ASTModule           = 0x04,     ///< If set will output AST modules - typically required, but potentially not desired (for example with obsfucation)
        IRModule            = 0x08,     ///< If set will output IR modules - typically required
    };
};
typedef SerialOptionFlag::Type SerialOptionFlags;


// Compression styles

enum class SerialCompressionType : uint8_t
{
    None,
    VariableByteLite,
};


struct SerialStringData
{
    enum class StringIndex : uint32_t;
 
    ///enum class StringOffset : uint32_t;                     ///< Offset into the m_stringsBuffer

    typedef uint32_t SizeType;

    static const StringIndex kNullStringIndex = StringIndex(StringSlicePool::kNullHandle);
    static const StringIndex kEmptyStringIndex = StringIndex(StringSlicePool::kEmptyHandle);
};

struct SerialStringTableUtil
{
        /// Convert a pool into a string table
    static void encodeStringTable(const StringSlicePool& pool, List<char>& stringTable);
    static void encodeStringTable(const ConstArrayView<UnownedStringSlice>& slices, List<char>& stringTable);

        /// Appends the decoded strings into slicesOut
    static void appendDecodedStringTable(const char* table, size_t tableSize, List<UnownedStringSlice>& slicesOut);

        /// Decodes a string table (and does so such that the indices are compatible with StringSlicePool)
    static void decodeStringTable(const char* table, size_t tableSize, List<UnownedStringSlice>& slicesOut);

        /// Decodes a string table 
    static void decodeStringTable(const char* table, size_t tableSize, StringSlicePool& outPool);

        /// Produces an index map, from slices to indices in pool
    static void calcStringSlicePoolMap(const List<UnownedStringSlice>& slices, StringSlicePool& pool, List<StringSlicePool::Handle>& indexMap);
};

struct SerialParseUtil
{
    /// Given text, finds the compression type
    static SlangResult parseCompressionType(const UnownedStringSlice& text, SerialCompressionType& outType);
    /// Given a compression type, return text
    static UnownedStringSlice getText(SerialCompressionType type);
};

struct SerialListUtil
{
    template <typename T>
    static size_t calcArraySize(const List<T>& list)
    {
        return list.getCount() * sizeof(T);
    }

    template <typename T>
    static bool isEqual(const List<T>& aIn, const List<T>& bIn)
    {
        if (&aIn == &bIn)
        {
            return true;
        }
        const Index size = aIn.getCount();

        if (size != bIn.getCount())
        {
            return false;
        }

        const T* a = aIn.begin();
        const T* b = bIn.begin();

        if (a != b)
        {
            for (Index i = 0; i < size; ++i)
            {
                if (a[i] != b[i])
                {
                    return false;
                }
            }
        }

        return true;
    }
};

// For types/FourCC that work for serializing in general (not just IR). 
struct SerialBinary
{
    static const FourCC kRiffFourCc = RiffFourCC::kRiff;

        /// Container 
    static const FourCC kContainerFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'c');

        /// A string table
    static const FourCC kStringTableFourCc = SLANG_FOUR_CC('S', 'L', 's', 't');

        /// TranslationUnitList
    static const FourCC kModuleListFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'l');

        /// An entry point
    static const FourCC kEntryPointFourCc = SLANG_FOUR_CC('E', 'P', 'n', 't');

        /// Container
    static const FourCC kContainerHeaderFourCc = SLANG_FOUR_CC('S', 'c', 'h', 'd');

    struct ContainerHeader
    {
        uint32_t compressionType;         ///< Holds the compression type used (if used at all)
    };

    struct ArrayHeader
    {
        uint32_t numEntries;
    };
    struct CompressedArrayHeader
    {
        uint32_t numEntries;              ///< The number of entries
        uint32_t numCompressedEntries;    ///< The amount of compressed entries
    };
};

// Replace first char with 's'
#define SLANG_MAKE_COMPRESSED_FOUR_CC(fourCc) SLANG_FOUR_CC_REPLACE_FIRST_CHAR(fourCc, 's')

struct SerialRiffUtil
{
    class ListResizer
    {
    public:
        virtual void* setSize(size_t newSize) = 0;
        SLANG_FORCE_INLINE size_t getTypeSize() const { return m_typeSize; }
        ListResizer(size_t typeSize) :m_typeSize(typeSize) {}

    protected:
        size_t m_typeSize;
    };

    template <typename T>
    class ListResizerForType : public ListResizer
    {
    public:
        typedef ListResizer Parent;

        SLANG_FORCE_INLINE ListResizerForType(List<T>& list) :
            Parent(sizeof(T)),
            m_list(list)
        {}

        virtual void* setSize(size_t newSize) SLANG_OVERRIDE
        {
            m_list.setCount(UInt(newSize));
            return (void*)m_list.begin();
        }

    protected:
        List<T>& m_list;
    };

    static Result writeArrayChunk(SerialCompressionType compressionType, FourCC chunkId, const void* data, size_t numEntries, size_t typeSize, RiffContainer* container);
    
    template <typename T>
    static Result writeArrayChunk(SerialCompressionType compressionType, FourCC chunkId, const List<T>& array, RiffContainer* container)
    {
        return writeArrayChunk(compressionType, chunkId, array.begin(), size_t(array.getCount()), sizeof(T), container);
    }

    template <typename T>
    static Result writeArrayUncompressedChunk(FourCC chunkId, const List<T>& array, RiffContainer* container)
    {
        return writeArrayChunk(SerialCompressionType::None, chunkId, array.begin(), size_t(array.getCount()), sizeof(T), container);
    }

    static Result readArrayChunk(SerialCompressionType compressionType, RiffContainer::DataChunk* dataChunk, ListResizer& listOut);

    template <typename T>
    static Result readArrayChunk(SerialCompressionType moduleCompressionType, RiffContainer::DataChunk* dataChunk, List<T>& arrayOut)
    {
        SerialCompressionType compressionType = SerialCompressionType::None;
        if (dataChunk->m_fourCC == SLANG_MAKE_COMPRESSED_FOUR_CC(dataChunk->m_fourCC))
        {
            // If it has compression, use the compression type set in the header
            compressionType = moduleCompressionType;
        }
        ListResizerForType<T> resizer(arrayOut);
        return readArrayChunk(compressionType, dataChunk, resizer);
    }

    template <typename T>
    static Result readArrayUncompressedChunk(RiffContainer::DataChunk* chunk, List<T>& arrayOut)
    {
        ListResizerForType<T> resizer(arrayOut);
        return readArrayChunk(SerialCompressionType::None, chunk, resizer);
    }


};

} // namespace Slang

#endif
back to top