import * as beet from '@metaplex-foundation/beet';
import { FailedToDeserializeDataError, FailedToSerializeDataError, UnexpectedAccountError, } from '../errors';
export const mapSerializer = (serializer, map, unmap) => ({
    description: serializer.description,
    serialize: (value) => serializer.serialize(unmap(value)),
    deserialize: (buffer, offset) => {
        const [value, newOffset] = serializer.deserialize(buffer, offset);
        return [map(value), newOffset];
    },
});
export const createSerializerFromBeet = (beetArg) => ({
    description: beetArg.description,
    serialize: (value) => {
        const fixedBeet = beet.isFixableBeet(beetArg)
            ? beetArg.toFixedFromValue(value)
            : beetArg;
        const writer = new beet.BeetWriter(fixedBeet.byteSize);
        writer.write(fixedBeet, value);
        return writer.buffer;
    },
    deserialize: (buffer, offset) => {
        const fixedBeet = beet.isFixableBeet(beetArg)
            ? beetArg.toFixedFromData(buffer, offset !== null && offset !== void 0 ? offset : 0)
            : beetArg;
        const reader = new beet.BeetReader(buffer, offset !== null && offset !== void 0 ? offset : 0);
        const value = reader.read(fixedBeet);
        return [value, reader.offset];
    },
});
export const createSerializerFromSolitaType = (solitaType, description) => ({
    description: description !== null && description !== void 0 ? description : solitaType.name,
    serialize: (value) => {
        return solitaType.fromArgs(value).serialize()[0];
    },
    deserialize: (buffer, offset) => {
        return solitaType.deserialize(buffer, offset);
    },
});
export const serialize = (value, serializer) => {
    try {
        return serializer.serialize(value);
    }
    catch (error) {
        throw new FailedToSerializeDataError(serializer.description, {
            cause: error,
        });
    }
};
export const deserialize = (value, serializer) => {
    try {
        return serializer.deserialize(value);
    }
    catch (error) {
        throw new FailedToDeserializeDataError(serializer.description, {
            cause: error,
        });
    }
};
export function deserializeAccount(account, serializer) {
    if ('exists' in account && !account.exists) {
        return account;
    }
    try {
        const data = serializer.deserialize(account.data)[0];
        return Object.assign(Object.assign({}, account), { data });
    }
    catch (error) {
        throw new UnexpectedAccountError(account.publicKey, serializer.description, { cause: error });
    }
}
export const serializeDiscriminator = (discriminator) => {
    const serializer = createSerializerFromBeet(beet.uniformFixedSizeArray(beet.u8, 8));
    return serialize(discriminator, serializer);
};
//# sourceMappingURL=Serializer.js.map