@classmethod
    def pack(cls, val, str_cache, object_cache, traits_cache):
        chunks = []

        if val in object_cache:
            index = object_cache.index(val)
            return AMF3Integer(index << 1)
        else:
            object_cache.append(val)
            chunks = []
            traits = type(val)

            if traits in traits_cache:
                index = traits_cache.index(traits)
                chunks.append(AMF3Integer(index << 2 | 0x01))
            else:
                header = 0x03

                if traits.__dynamic__:
                    header |= 0x02 << 2

                if traits.__externalizable__:
                    header |= 0x01 << 2

                header |= (len(traits.__members__)) << 4
                chunks.append(AMF3Integer(header))

                if isinstance(val, AMF3Object):
                    chunks.append(U8(AMF3_EMPTY_STRING))
                else:
                    chunks.append(AMF3String(traits.__name__, cache=str_cache))
                    traits_cache.append(traits)

                for member in traits.__members__:
                    chunks.append(AMF3String(member, cache=str_cache))


            for member in traits.__members__:
                value = getattr(val, member)
                value = AMF3Value.pack(value, str_cache=str_cache,
                                       object_cache=object_cache,
                                       traits_cache=traits_cache)
                chunks.append(value)


            if traits.__dynamic__:
                if isinstance(val, AMF3Object):
                    iterator = val.items()
                else:
                    iterator = val.__dict__.items()

                for key, value in iterator:
                    if key in traits.__members__:
                        continue

                    key = AMF3String(key, cache=str_cache)
                    value = AMF3Value.pack(value, str_cache=str_cache,
                                           object_cache=object_cache,
                                           traits_cache=traits_cache)

                    chunks.append(key)
                    chunks.append(value)

                # Empty string is end of dynamic values
                chunks.append(U8(AMF3_CLOSE_DYNAMIC_ARRAY))

            return b"".join(chunks)
dataset/ETHPy150Open chrippa/livestreamer/src/livestreamer/packages/flashmedia/types.py/AMF3ObjectPacker.pack/original