virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
                       const virDomainDef *def,
                       virDomainXMLOptionPtr xmlopt,
                       void *parseOpaque)
{
    g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
    int flags = VIR_DOMAIN_DEF_FORMAT_INACTIVE | VIR_DOMAIN_DEF_FORMAT_SECURE;
    int rc = -1;
    g_autofree char *xmlStr = NULL;

    switch ((virDomainDeviceType) src->type) {
    case VIR_DOMAIN_DEVICE_DISK:
        rc = virDomainDiskDefFormat(&buf, src->data.disk, flags, xmlopt);
        break;
    case VIR_DOMAIN_DEVICE_LEASE:
        rc = virDomainLeaseDefFormat(&buf, src->data.lease);
        break;
    case VIR_DOMAIN_DEVICE_FS:
        rc = virDomainFSDefFormat(&buf, src->data.fs, flags);
        break;
    case VIR_DOMAIN_DEVICE_NET:
        rc = virDomainNetDefFormat(&buf, src->data.net, xmlopt, flags);
        break;
    case VIR_DOMAIN_DEVICE_INPUT:
        rc = virDomainInputDefFormat(&buf, src->data.input, flags);
        break;
    case VIR_DOMAIN_DEVICE_SOUND:
        rc = virDomainSoundDefFormat(&buf, src->data.sound, flags);
        break;
    case VIR_DOMAIN_DEVICE_VIDEO:
        rc = virDomainVideoDefFormat(&buf, src->data.video, flags);
        break;
    case VIR_DOMAIN_DEVICE_HOSTDEV:
        rc = virDomainHostdevDefFormat(&buf, src->data.hostdev, flags);
        break;
    case VIR_DOMAIN_DEVICE_WATCHDOG:
        rc = virDomainWatchdogDefFormat(&buf, src->data.watchdog, flags);
        break;
    case VIR_DOMAIN_DEVICE_CONTROLLER:
        rc = virDomainControllerDefFormat(&buf, src->data.controller, flags);
        break;
    case VIR_DOMAIN_DEVICE_GRAPHICS:
        rc = virDomainGraphicsDefFormat(&buf, src->data.graphics, flags);
        break;
    case VIR_DOMAIN_DEVICE_HUB:
        rc = virDomainHubDefFormat(&buf, src->data.hub, flags);
        break;
    case VIR_DOMAIN_DEVICE_REDIRDEV:
        rc = virDomainRedirdevDefFormat(&buf, src->data.redirdev, flags);
        break;
    case VIR_DOMAIN_DEVICE_RNG:
        rc = virDomainRNGDefFormat(&buf, src->data.rng, flags);
        break;
    case VIR_DOMAIN_DEVICE_CHR:
        rc = virDomainChrDefFormat(&buf, src->data.chr, flags);
        break;
    case VIR_DOMAIN_DEVICE_TPM:
        rc = virDomainTPMDefFormat(&buf, src->data.tpm, flags);
        break;
    case VIR_DOMAIN_DEVICE_PANIC:
        rc = virDomainPanicDefFormat(&buf, src->data.panic);
        break;
    case VIR_DOMAIN_DEVICE_MEMORY:
        rc = virDomainMemoryDefFormat(&buf, src->data.memory, def, flags);
        break;
    case VIR_DOMAIN_DEVICE_SHMEM:
        rc = virDomainShmemDefFormat(&buf, src->data.shmem, flags);
        break;
    case VIR_DOMAIN_DEVICE_VSOCK:
        rc = virDomainVsockDefFormat(&buf, src->data.vsock);
        break;

    case VIR_DOMAIN_DEVICE_NONE:
    case VIR_DOMAIN_DEVICE_SMARTCARD:
    case VIR_DOMAIN_DEVICE_MEMBALLOON:
    case VIR_DOMAIN_DEVICE_NVRAM:
    case VIR_DOMAIN_DEVICE_IOMMU:
    case VIR_DOMAIN_DEVICE_LAST:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Copying definition of '%d' type "
                         "is not implemented yet."),
                       src->type);
        return NULL;
    }

    if (rc < 0)
        return NULL;

    xmlStr = virBufferContentAndReset(&buf);
    return virDomainDeviceDefParse(xmlStr, def, xmlopt, parseOpaque,
                                   VIR_DOMAIN_DEF_PARSE_INACTIVE |
                                   VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE);
}