stellar-xdr 0.0.12

Stellar XDR types, encoding, and decoding.
Documentation
// Module  is generated from:
//  xdr/next/Stellar-SCP.x
//  xdr/next/Stellar-contract-env-meta.x
//  xdr/next/Stellar-contract-spec.x
//  xdr/next/Stellar-contract.x
//  xdr/next/Stellar-internal.x
//  xdr/next/Stellar-ledger-entries.x
//  xdr/next/Stellar-ledger.x
//  xdr/next/Stellar-overlay.x
//  xdr/next/Stellar-transaction.x
//  xdr/next/Stellar-types.x

#![allow(clippy::missing_errors_doc, clippy::unreadable_literal)]

/// `XDR_FILES_SHA256` is a list of pairs of source files and their SHA256 hashes.
pub const XDR_FILES_SHA256: [(&str, &str); 10] = [
    (
        "xdr/next/Stellar-SCP.x",
        "8f32b04d008f8bc33b8843d075e69837231a673691ee41d8b821ca229a6e802a",
    ),
    (
        "xdr/next/Stellar-contract-env-meta.x",
        "928a30de814ee589bc1d2aadd8dd81c39f71b7e6f430f56974505ccb1f49654b",
    ),
    (
        "xdr/next/Stellar-contract-spec.x",
        "1c4304a077e12a94a793efa90e18099011f11b385a8aa2272c65e334cee989df",
    ),
    (
        "xdr/next/Stellar-contract.x",
        "69e8f476cb30ceda3a0981b7f9367a4e4f1a29393336a78ae4cc1e9e7f5e750c",
    ),
    (
        "xdr/next/Stellar-internal.x",
        "368706dd6e2efafd16a8f63daf3374845b791d097b15c502aa7653a412b68b68",
    ),
    (
        "xdr/next/Stellar-ledger-entries.x",
        "bc3ef59ed74e6f990ce14dd051a000a6dd793fc6a5deb4a83c7fef1035ff1bc6",
    ),
    (
        "xdr/next/Stellar-ledger.x",
        "b19c10a07c9775594723ad12927259dd4bbd9ed9dfd0e70078662ec2e90e130d",
    ),
    (
        "xdr/next/Stellar-overlay.x",
        "3093b425866f34b32702d80d5298f9f2dc00736b0fdaac7efa653490a39fb231",
    ),
    (
        "xdr/next/Stellar-transaction.x",
        "bdac432e08265df6a13dc4c6135090ca6dcaa8eeedd61a0533ba52b4c9baf201",
    ),
    (
        "xdr/next/Stellar-types.x",
        "7b3e5470c4bcf7c19f9cc8f8bf81a494b540fc2157476329cf19863afab2343b",
    ),
];

use core::{array::TryFromSliceError, fmt, fmt::Debug, marker::Sized, ops::Deref, slice};

#[cfg(feature = "std")]
use core::marker::PhantomData;

// When feature alloc is turned off use static lifetime Box and Vec types.
#[cfg(not(feature = "alloc"))]
mod noalloc {
    pub mod boxed {
        pub type Box<T> = &'static T;
    }
    pub mod vec {
        pub type Vec<T> = &'static [T];
    }
}
#[cfg(not(feature = "alloc"))]
use noalloc::{boxed::Box, vec::Vec};

// When feature std is turned off, but feature alloc is turned on import the
// alloc crate and use its Box and Vec types.
#[cfg(all(not(feature = "std"), feature = "alloc"))]
extern crate alloc;
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::{
    borrow::ToOwned,
    boxed::Box,
    string::{FromUtf8Error, String},
    vec::Vec,
};
#[cfg(all(feature = "std"))]
use std::string::FromUtf8Error;

#[cfg(feature = "arbitrary")]
use arbitrary::Arbitrary;

// TODO: Add support for read/write xdr fns when std not available.

#[cfg(feature = "std")]
use std::{
    error, io,
    io::{BufRead, BufReader, Cursor, Read, Write},
};

/// Error contains all errors returned by functions in this crate. It can be
/// compared via `PartialEq`, however any contained IO errors will only be
/// compared on their `ErrorKind`.
#[derive(Debug)]
pub enum Error {
    Invalid,
    Unsupported,
    LengthExceedsMax,
    LengthMismatch,
    NonZeroPadding,
    Utf8Error(core::str::Utf8Error),
    #[cfg(feature = "alloc")]
    InvalidHex,
    #[cfg(feature = "std")]
    Io(io::Error),
}

impl PartialEq for Error {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::Utf8Error(l), Self::Utf8Error(r)) => l == r,
            // IO errors cannot be compared, but in the absence of any more
            // meaningful way to compare the errors we compare the kind of error
            // and ignore the embedded source error or OS error. The main use
            // case for comparing errors outputted by the XDR library is for
            // error case testing, and a lack of the ability to compare has a
            // detrimental affect on failure testing, so this is a tradeoff.
            #[cfg(feature = "std")]
            (Self::Io(l), Self::Io(r)) => l.kind() == r.kind(),
            _ => core::mem::discriminant(self) == core::mem::discriminant(other),
        }
    }
}

#[cfg(feature = "std")]
impl error::Error for Error {
    #[must_use]
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            Self::Io(e) => Some(e),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Invalid => write!(f, "xdr value invalid"),
            Error::Unsupported => write!(f, "xdr value unsupported"),
            Error::LengthExceedsMax => write!(f, "xdr value max length exceeded"),
            Error::LengthMismatch => write!(f, "xdr value length does not match"),
            Error::NonZeroPadding => write!(f, "xdr padding contains non-zero bytes"),
            Error::Utf8Error(e) => write!(f, "{e}"),
            #[cfg(feature = "alloc")]
            Error::InvalidHex => write!(f, "hex invalid"),
            #[cfg(feature = "std")]
            Error::Io(e) => write!(f, "{e}"),
        }
    }
}

impl From<TryFromSliceError> for Error {
    fn from(_: TryFromSliceError) -> Error {
        Error::LengthMismatch
    }
}

impl From<core::str::Utf8Error> for Error {
    #[must_use]
    fn from(e: core::str::Utf8Error) -> Self {
        Error::Utf8Error(e)
    }
}

#[cfg(feature = "alloc")]
impl From<FromUtf8Error> for Error {
    #[must_use]
    fn from(e: FromUtf8Error) -> Self {
        Error::Utf8Error(e.utf8_error())
    }
}

#[cfg(feature = "std")]
impl From<io::Error> for Error {
    #[must_use]
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}

impl From<Error> for () {
    fn from(_: Error) {}
}

#[allow(dead_code)]
type Result<T> = core::result::Result<T, Error>;

/// Name defines types that assign a static name to their value, such as the
/// name given to an identifier in an XDR enum, or the name given to the case in
/// a union.
pub trait Name {
    fn name(&self) -> &'static str;
}

/// Discriminant defines types that may contain a one-of value determined
/// according to the discriminant, and exposes the value of the discriminant for
/// that type, such as in an XDR union.
pub trait Discriminant<D> {
    fn discriminant(&self) -> D;
}

/// Iter defines types that have variants that can be iterated.
pub trait Variants<V> {
    fn variants() -> slice::Iter<'static, V>
    where
        V: Sized;
}

// Enum defines a type that is represented as an XDR enumeration when encoded.
pub trait Enum: Name + Variants<Self> + Sized {}

// Union defines a type that is represented as an XDR union when encoded.
pub trait Union<D>: Name + Discriminant<D> + Variants<D>
where
    D: Sized,
{
}

#[cfg(feature = "std")]
pub struct ReadXdrIter<R: Read, S: ReadXdr> {
    reader: BufReader<R>,
    _s: PhantomData<S>,
}

#[cfg(feature = "std")]
impl<R: Read, S: ReadXdr> ReadXdrIter<R, S> {
    fn new(r: R) -> Self {
        Self {
            reader: BufReader::new(r),
            _s: PhantomData,
        }
    }
}

#[cfg(feature = "std")]
impl<R: Read, S: ReadXdr> Iterator for ReadXdrIter<R, S> {
    type Item = Result<S>;

    // Next reads the internal reader and XDR decodes it into the Self type. If
    // the EOF is reached without reading any new bytes `None` is returned. If
    // EOF is reached after reading some bytes a truncated entry is assumed an
    // an `Error::Io` containing an `UnexpectedEof`. If any other IO error
    // occurs it is returned. Iteration of this iterator stops naturally when
    // `None` is returned, but not when a `Some(Err(...))` is returned. The
    // caller is responsible for checking each Result.
    fn next(&mut self) -> Option<Self::Item> {
        // Try to fill the buffer to see if the EOF has been reached or not.
        // This happens to effectively peek to see if the stream has finished
        // and there are no more items.  It is necessary to do this because the
        // xdr types in this crate heavily use the `std::io::Read::read_exact`
        // method that doesn't distinguish between an EOF at the beginning of a
        // read and an EOF after a partial fill of a read_exact.
        match self.reader.fill_buf() {
            // If the reader has no more data and is unable to fill any new data
            // into its internal buf, then the EOF has been reached.
            Ok([]) => return None,
            // If an error occurs filling the buffer, treat that as an error and stop.
            Err(e) => return Some(Err(Error::Io(e))),
            // If there is data in the buf available for reading, continue.
            Ok([..]) => (),
        };
        // Read the buf into the type.
        match S::read_xdr(&mut self.reader) {
            Ok(s) => Some(Ok(s)),
            Err(e) => Some(Err(e)),
        }
    }
}

pub trait ReadXdr
where
    Self: Sized,
{
    /// Read the XDR and construct the type.
    ///
    /// Read bytes from the given read implementation, decoding the bytes as
    /// XDR, and construct the type implementing this interface from those
    /// bytes.
    ///
    /// Just enough bytes are read from the read implementation to construct the
    /// type. Any residual bytes remain in the read implementation.
    ///
    /// All implementations should continue if the read implementation returns
    /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted).
    ///
    /// Use [`ReadXdr::read_xdr_to_end`] when the intent is for all bytes in the
    /// read implementation to be consumed by the read.
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self>;

    /// Construct the type from the XDR bytes base64 encoded.
    ///
    /// An error is returned if the bytes are not completely consumed by the
    /// deserialization.
    #[cfg(feature = "base64")]
    fn read_xdr_base64(r: &mut impl Read) -> Result<Self> {
        let mut dec = base64::read::DecoderReader::new(r, base64::STANDARD);
        let t = Self::read_xdr(&mut dec)?;
        Ok(t)
    }

    /// Read the XDR and construct the type, and consider it an error if the
    /// read does not completely consume the read implementation.
    ///
    /// Read bytes from the given read implementation, decoding the bytes as
    /// XDR, and construct the type implementing this interface from those
    /// bytes.
    ///
    /// Just enough bytes are read from the read implementation to construct the
    /// type, and then confirm that no further bytes remain. To confirm no
    /// further bytes remain additional bytes are attempted to be read from the
    /// read implementation. If it is possible to read any residual bytes from
    /// the read implementation an error is returned. The read implementation
    /// may not be exhaustively read if there are residual bytes, and it is
    /// considered undefined how many residual bytes or how much of the residual
    /// buffer are consumed in this case.
    ///
    /// All implementations should continue if the read implementation returns
    /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted).
    #[cfg(feature = "std")]
    fn read_xdr_to_end(r: &mut impl Read) -> Result<Self> {
        let s = Self::read_xdr(r)?;
        // Check that any further reads, such as this read of one byte, read no
        // data, indicating EOF. If a byte is read the data is invalid.
        if r.read(&mut [0u8; 1])? == 0 {
            Ok(s)
        } else {
            Err(Error::Invalid)
        }
    }

    /// Construct the type from the XDR bytes base64 encoded.
    ///
    /// An error is returned if the bytes are not completely consumed by the
    /// deserialization.
    #[cfg(feature = "base64")]
    fn read_xdr_base64_to_end(r: &mut impl Read) -> Result<Self> {
        let mut dec = base64::read::DecoderReader::new(r, base64::STANDARD);
        let t = Self::read_xdr_to_end(&mut dec)?;
        Ok(t)
    }

    /// Read the XDR and construct the type.
    ///
    /// Read bytes from the given read implementation, decoding the bytes as
    /// XDR, and construct the type implementing this interface from those
    /// bytes.
    ///
    /// Just enough bytes are read from the read implementation to construct the
    /// type. Any residual bytes remain in the read implementation.
    ///
    /// All implementations should continue if the read implementation returns
    /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted).
    ///
    /// Use [`ReadXdr::read_xdr_into_to_end`] when the intent is for all bytes
    /// in the read implementation to be consumed by the read.
    #[cfg(feature = "std")]
    fn read_xdr_into(&mut self, r: &mut impl Read) -> Result<()> {
        *self = Self::read_xdr(r)?;
        Ok(())
    }

    /// Read the XDR into the existing value, and consider it an error if the
    /// read does not completely consume the read implementation.
    ///
    /// Read bytes from the given read implementation, decoding the bytes as
    /// XDR, and construct the type implementing this interface from those
    /// bytes.
    ///
    /// Just enough bytes are read from the read implementation to construct the
    /// type, and then confirm that no further bytes remain. To confirm no
    /// further bytes remain additional bytes are attempted to be read from the
    /// read implementation. If it is possible to read any residual bytes from
    /// the read implementation an error is returned. The read implementation
    /// may not be exhaustively read if there are residual bytes, and it is
    /// considered undefined how many residual bytes or how much of the residual
    /// buffer are consumed in this case.
    ///
    /// All implementations should continue if the read implementation returns
    /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted).
    #[cfg(feature = "std")]
    fn read_xdr_into_to_end(&mut self, r: &mut impl Read) -> Result<()> {
        Self::read_xdr_into(self, r)?;
        // Check that any further reads, such as this read of one byte, read no
        // data, indicating EOF. If a byte is read the data is invalid.
        if r.read(&mut [0u8; 1])? == 0 {
            Ok(())
        } else {
            Err(Error::Invalid)
        }
    }

    /// Create an iterator that reads the read implementation as a stream of
    /// values that are read into the implementing type.
    ///
    /// Read bytes from the given read implementation, decoding the bytes as
    /// XDR, and construct the type implementing this interface from those
    /// bytes.
    ///
    /// Just enough bytes are read from the read implementation to construct the
    /// type, and then confirm that no further bytes remain. To confirm no
    /// further bytes remain additional bytes are attempted to be read from the
    /// read implementation. If it is possible to read any residual bytes from
    /// the read implementation an error is returned. The read implementation
    /// may not be exhaustively read if there are residual bytes, and it is
    /// considered undefined how many residual bytes or how much of the residual
    /// buffer are consumed in this case.
    ///
    /// All implementations should continue if the read implementation returns
    /// [`ErrorKind::Interrupted`](std::io::ErrorKind::Interrupted).
    #[cfg(feature = "std")]
    fn read_xdr_iter<R: Read>(r: &mut R) -> ReadXdrIter<&mut R, Self> {
        ReadXdrIter::new(r)
    }

    /// Create an iterator that reads the read implementation as a stream of
    /// values that are read into the implementing type.
    #[cfg(feature = "base64")]
    fn read_xdr_base64_iter<R: Read>(
        r: &mut R,
    ) -> ReadXdrIter<base64::read::DecoderReader<R>, Self> {
        let dec = base64::read::DecoderReader::new(r, base64::STANDARD);
        ReadXdrIter::new(dec)
    }

    /// Construct the type from the XDR bytes.
    ///
    /// An error is returned if the bytes are not completely consumed by the
    /// deserialization.
    #[cfg(feature = "std")]
    fn from_xdr(bytes: impl AsRef<[u8]>) -> Result<Self> {
        let mut cursor = Cursor::new(bytes.as_ref());
        let t = Self::read_xdr_to_end(&mut cursor)?;
        Ok(t)
    }

    /// Construct the type from the XDR bytes base64 encoded.
    ///
    /// An error is returned if the bytes are not completely consumed by the
    /// deserialization.
    #[cfg(feature = "base64")]
    fn from_xdr_base64(b64: impl AsRef<[u8]>) -> Result<Self> {
        let mut b64_reader = Cursor::new(b64);
        let mut dec = base64::read::DecoderReader::new(&mut b64_reader, base64::STANDARD);
        let t = Self::read_xdr_to_end(&mut dec)?;
        Ok(t)
    }
}

pub trait WriteXdr {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()>;

    #[cfg(feature = "std")]
    fn to_xdr(&self) -> Result<Vec<u8>> {
        let mut cursor = Cursor::new(vec![]);
        self.write_xdr(&mut cursor)?;
        let bytes = cursor.into_inner();
        Ok(bytes)
    }

    #[cfg(feature = "base64")]
    fn to_xdr_base64(&self) -> Result<String> {
        let mut enc = base64::write::EncoderStringWriter::new(base64::STANDARD);
        self.write_xdr(&mut enc)?;
        let b64 = enc.into_inner();
        Ok(b64)
    }
}

/// `Pad_len` returns the number of bytes to pad an XDR value of the given
/// length to make the final serialized size a multiple of 4.
#[cfg(feature = "std")]
fn pad_len(len: usize) -> usize {
    (4 - (len % 4)) % 4
}

impl ReadXdr for i32 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let mut b = [0u8; 4];
        r.read_exact(&mut b)?;
        let i = i32::from_be_bytes(b);
        Ok(i)
    }
}

impl WriteXdr for i32 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let b: [u8; 4] = self.to_be_bytes();
        w.write_all(&b)?;
        Ok(())
    }
}

impl ReadXdr for u32 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let mut b = [0u8; 4];
        r.read_exact(&mut b)?;
        let i = u32::from_be_bytes(b);
        Ok(i)
    }
}

impl WriteXdr for u32 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let b: [u8; 4] = self.to_be_bytes();
        w.write_all(&b)?;
        Ok(())
    }
}

impl ReadXdr for i64 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let mut b = [0u8; 8];
        r.read_exact(&mut b)?;
        let i = i64::from_be_bytes(b);
        Ok(i)
    }
}

impl WriteXdr for i64 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let b: [u8; 8] = self.to_be_bytes();
        w.write_all(&b)?;
        Ok(())
    }
}

impl ReadXdr for u64 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let mut b = [0u8; 8];
        r.read_exact(&mut b)?;
        let i = u64::from_be_bytes(b);
        Ok(i)
    }
}

impl WriteXdr for u64 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let b: [u8; 8] = self.to_be_bytes();
        w.write_all(&b)?;
        Ok(())
    }
}

impl ReadXdr for f32 {
    #[cfg(feature = "std")]
    fn read_xdr(_r: &mut impl Read) -> Result<Self> {
        todo!()
    }
}

impl WriteXdr for f32 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, _w: &mut impl Write) -> Result<()> {
        todo!()
    }
}

impl ReadXdr for f64 {
    #[cfg(feature = "std")]
    fn read_xdr(_r: &mut impl Read) -> Result<Self> {
        todo!()
    }
}

impl WriteXdr for f64 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, _w: &mut impl Write) -> Result<()> {
        todo!()
    }
}

impl ReadXdr for bool {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = u32::read_xdr(r)?;
        let b = i == 1;
        Ok(b)
    }
}

impl WriteXdr for bool {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i = u32::from(*self); // true = 1, false = 0
        i.write_xdr(w)?;
        Ok(())
    }
}

impl<T: ReadXdr> ReadXdr for Option<T> {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = u32::read_xdr(r)?;
        match i {
            0 => Ok(None),
            1 => {
                let t = T::read_xdr(r)?;
                Ok(Some(t))
            }
            _ => Err(Error::Invalid),
        }
    }
}

impl<T: WriteXdr> WriteXdr for Option<T> {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        if let Some(t) = self {
            1u32.write_xdr(w)?;
            t.write_xdr(w)?;
        } else {
            0u32.write_xdr(w)?;
        }
        Ok(())
    }
}

impl<T: ReadXdr> ReadXdr for Box<T> {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let t = T::read_xdr(r)?;
        Ok(Box::new(t))
    }
}

impl<T: WriteXdr> WriteXdr for Box<T> {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        T::write_xdr(self, w)?;
        Ok(())
    }
}

impl ReadXdr for () {
    #[cfg(feature = "std")]
    fn read_xdr(_r: &mut impl Read) -> Result<Self> {
        Ok(())
    }
}

impl WriteXdr for () {
    #[cfg(feature = "std")]
    fn write_xdr(&self, _w: &mut impl Write) -> Result<()> {
        Ok(())
    }
}

impl<const N: usize> ReadXdr for [u8; N] {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let mut arr = [0u8; N];
        r.read_exact(&mut arr)?;

        let pad = &mut [0u8; 3][..pad_len(N)];
        r.read_exact(pad)?;
        if pad.iter().any(|b| *b != 0) {
            return Err(Error::NonZeroPadding);
        }

        Ok(arr)
    }
}

impl<const N: usize> WriteXdr for [u8; N] {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        w.write_all(self)?;
        w.write_all(&[0u8; 3][..pad_len(N)])?;
        Ok(())
    }
}

impl<T: ReadXdr, const N: usize> ReadXdr for [T; N] {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let mut vec = Vec::with_capacity(N);
        for _ in 0..N {
            let t = T::read_xdr(r)?;
            vec.push(t);
        }
        let arr: [T; N] = vec.try_into().unwrap_or_else(|_: Vec<T>| unreachable!());
        Ok(arr)
    }
}

impl<T: WriteXdr, const N: usize> WriteXdr for [T; N] {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        for t in self {
            t.write_xdr(w)?;
        }
        Ok(())
    }
}

// VecM ------------------------------------------------------------------------

#[cfg(feature = "alloc")]
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub struct VecM<T, const MAX: u32 = { u32::MAX }>(Vec<T>);

#[cfg(not(feature = "alloc"))]
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub struct VecM<T, const MAX: u32 = { u32::MAX }>(Vec<T>)
where
    T: 'static;

impl<T, const MAX: u32> Deref for VecM<T, MAX> {
    type Target = Vec<T>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T, const MAX: u32> Default for VecM<T, MAX> {
    fn default() -> Self {
        Self(Vec::default())
    }
}

impl<T, const MAX: u32> VecM<T, MAX> {
    pub const MAX_LEN: usize = { MAX as usize };

    #[must_use]
    #[allow(clippy::unused_self)]
    pub fn max_len(&self) -> usize {
        Self::MAX_LEN
    }

    #[must_use]
    pub fn as_vec(&self) -> &Vec<T> {
        self.as_ref()
    }
}

impl<T: Clone, const MAX: u32> VecM<T, MAX> {
    #[must_use]
    #[cfg(feature = "alloc")]
    pub fn to_vec(&self) -> Vec<T> {
        self.into()
    }

    #[must_use]
    pub fn into_vec(self) -> Vec<T> {
        self.into()
    }
}

impl<const MAX: u32> VecM<u8, MAX> {
    #[cfg(feature = "alloc")]
    pub fn to_string(&self) -> Result<String> {
        self.try_into()
    }

    #[cfg(feature = "alloc")]
    pub fn into_string(self) -> Result<String> {
        self.try_into()
    }

    #[cfg(feature = "alloc")]
    #[must_use]
    pub fn to_string_lossy(&self) -> String {
        String::from_utf8_lossy(&self.0).into_owned()
    }

    #[cfg(feature = "alloc")]
    #[must_use]
    pub fn into_string_lossy(self) -> String {
        String::from_utf8_lossy(&self.0).into_owned()
    }
}

impl<T: Clone> VecM<T, 1> {
    #[must_use]
    pub fn to_option(&self) -> Option<T> {
        if self.len() > 0 {
            Some(self.0[0].clone())
        } else {
            None
        }
    }
}

#[cfg(not(feature = "alloc"))]
impl<T: Clone> From<VecM<T, 1>> for Option<T> {
    #[must_use]
    fn from(v: VecM<T, 1>) -> Self {
        v.to_option()
    }
}

#[cfg(feature = "alloc")]
impl<T> VecM<T, 1> {
    #[must_use]
    pub fn into_option(mut self) -> Option<T> {
        self.0.drain(..).next()
    }
}

#[cfg(feature = "alloc")]
impl<T> From<VecM<T, 1>> for Option<T> {
    #[must_use]
    fn from(v: VecM<T, 1>) -> Self {
        v.into_option()
    }
}

impl<T, const MAX: u32> TryFrom<Vec<T>> for VecM<T, MAX> {
    type Error = Error;

    fn try_from(v: Vec<T>) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(VecM(v))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

impl<T, const MAX: u32> From<VecM<T, MAX>> for Vec<T> {
    #[must_use]
    fn from(v: VecM<T, MAX>) -> Self {
        v.0
    }
}

#[cfg(feature = "alloc")]
impl<T: Clone, const MAX: u32> From<&VecM<T, MAX>> for Vec<T> {
    #[must_use]
    fn from(v: &VecM<T, MAX>) -> Self {
        v.0.clone()
    }
}

impl<T, const MAX: u32> AsRef<Vec<T>> for VecM<T, MAX> {
    #[must_use]
    fn as_ref(&self) -> &Vec<T> {
        &self.0
    }
}

#[cfg(feature = "alloc")]
impl<T: Clone, const MAX: u32> TryFrom<&Vec<T>> for VecM<T, MAX> {
    type Error = Error;

    fn try_from(v: &Vec<T>) -> Result<Self> {
        v.as_slice().try_into()
    }
}

#[cfg(feature = "alloc")]
impl<T: Clone, const MAX: u32> TryFrom<&[T]> for VecM<T, MAX> {
    type Error = Error;

    fn try_from(v: &[T]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(VecM(v.to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

impl<T, const MAX: u32> AsRef<[T]> for VecM<T, MAX> {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[T] {
        self.0.as_ref()
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[T] {
        self.0
    }
}

#[cfg(feature = "alloc")]
impl<T: Clone, const N: usize, const MAX: u32> TryFrom<[T; N]> for VecM<T, MAX> {
    type Error = Error;

    fn try_from(v: [T; N]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(VecM(v.to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<T: Clone, const N: usize, const MAX: u32> TryFrom<VecM<T, MAX>> for [T; N] {
    type Error = VecM<T, MAX>;

    fn try_from(v: VecM<T, MAX>) -> core::result::Result<Self, Self::Error> {
        let s: [T; N] = v.0.try_into().map_err(|v: Vec<T>| VecM::<T, MAX>(v))?;
        Ok(s)
    }
}

#[cfg(feature = "alloc")]
impl<T: Clone, const N: usize, const MAX: u32> TryFrom<&[T; N]> for VecM<T, MAX> {
    type Error = Error;

    fn try_from(v: &[T; N]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(VecM(v.to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(not(feature = "alloc"))]
impl<T: Clone, const N: usize, const MAX: u32> TryFrom<&'static [T; N]> for VecM<T, MAX> {
    type Error = Error;

    fn try_from(v: &'static [T; N]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(VecM(v))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&String> for VecM<u8, MAX> {
    type Error = Error;

    fn try_from(v: &String) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(VecM(v.as_bytes().to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<String> for VecM<u8, MAX> {
    type Error = Error;

    fn try_from(v: String) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(VecM(v.into()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<VecM<u8, MAX>> for String {
    type Error = Error;

    fn try_from(v: VecM<u8, MAX>) -> Result<Self> {
        Ok(String::from_utf8(v.0)?)
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&VecM<u8, MAX>> for String {
    type Error = Error;

    fn try_from(v: &VecM<u8, MAX>) -> Result<Self> {
        Ok(core::str::from_utf8(v.as_ref())?.to_owned())
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&str> for VecM<u8, MAX> {
    type Error = Error;

    fn try_from(v: &str) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(VecM(v.into()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(not(feature = "alloc"))]
impl<const MAX: u32> TryFrom<&'static str> for VecM<u8, MAX> {
    type Error = Error;

    fn try_from(v: &'static str) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(VecM(v.as_bytes()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

impl<'a, const MAX: u32> TryFrom<&'a VecM<u8, MAX>> for &'a str {
    type Error = Error;

    fn try_from(v: &'a VecM<u8, MAX>) -> Result<Self> {
        Ok(core::str::from_utf8(v.as_ref())?)
    }
}

impl<const MAX: u32> ReadXdr for VecM<u8, MAX> {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let len: u32 = u32::read_xdr(r)?;
        if len > MAX {
            return Err(Error::LengthExceedsMax);
        }

        let mut vec = vec![0u8; len as usize];
        r.read_exact(&mut vec)?;

        let pad = &mut [0u8; 3][..pad_len(len as usize)];
        r.read_exact(pad)?;
        if pad.iter().any(|b| *b != 0) {
            return Err(Error::NonZeroPadding);
        }

        Ok(VecM(vec))
    }
}

impl<const MAX: u32> WriteXdr for VecM<u8, MAX> {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        len.write_xdr(w)?;

        w.write_all(&self.0)?;

        w.write_all(&[0u8; 3][..pad_len(len as usize)])?;

        Ok(())
    }
}

impl<T: ReadXdr, const MAX: u32> ReadXdr for VecM<T, MAX> {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let len = u32::read_xdr(r)?;
        if len > MAX {
            return Err(Error::LengthExceedsMax);
        }

        let mut vec = Vec::with_capacity(len as usize);
        for _ in 0..len {
            let t = T::read_xdr(r)?;
            vec.push(t);
        }

        Ok(VecM(vec))
    }
}

impl<T: WriteXdr, const MAX: u32> WriteXdr for VecM<T, MAX> {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        len.write_xdr(w)?;

        for t in &self.0 {
            t.write_xdr(w)?;
        }

        Ok(())
    }
}

// BytesM ------------------------------------------------------------------------

#[cfg(feature = "alloc")]
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(
    feature = "serde",
    derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub struct BytesM<const MAX: u32 = { u32::MAX }>(Vec<u8>);

#[cfg(not(feature = "alloc"))]
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub struct BytesM<const MAX: u32 = { u32::MAX }>(Vec<u8>);

impl<const MAX: u32> core::fmt::Display for BytesM<MAX> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        #[cfg(feature = "alloc")]
        let v = &self.0;
        #[cfg(not(feature = "alloc"))]
        let v = self.0;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        Ok(())
    }
}

impl<const MAX: u32> core::fmt::Debug for BytesM<MAX> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        #[cfg(feature = "alloc")]
        let v = &self.0;
        #[cfg(not(feature = "alloc"))]
        let v = self.0;
        write!(f, "BytesM(")?;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        write!(f, ")")?;
        Ok(())
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> core::str::FromStr for BytesM<MAX> {
    type Err = Error;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        hex::decode(s).map_err(|_| Error::InvalidHex)?.try_into()
    }
}

impl<const MAX: u32> Deref for BytesM<MAX> {
    type Target = Vec<u8>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<const MAX: u32> Default for BytesM<MAX> {
    fn default() -> Self {
        Self(Vec::default())
    }
}

impl<const MAX: u32> BytesM<MAX> {
    pub const MAX_LEN: usize = { MAX as usize };

    #[must_use]
    #[allow(clippy::unused_self)]
    pub fn max_len(&self) -> usize {
        Self::MAX_LEN
    }

    #[must_use]
    pub fn as_vec(&self) -> &Vec<u8> {
        self.as_ref()
    }
}

impl<const MAX: u32> BytesM<MAX> {
    #[must_use]
    #[cfg(feature = "alloc")]
    pub fn to_vec(&self) -> Vec<u8> {
        self.into()
    }

    #[must_use]
    pub fn into_vec(self) -> Vec<u8> {
        self.into()
    }
}

impl<const MAX: u32> BytesM<MAX> {
    #[cfg(feature = "alloc")]
    pub fn to_string(&self) -> Result<String> {
        self.try_into()
    }

    #[cfg(feature = "alloc")]
    pub fn into_string(self) -> Result<String> {
        self.try_into()
    }

    #[cfg(feature = "alloc")]
    #[must_use]
    pub fn to_string_lossy(&self) -> String {
        String::from_utf8_lossy(&self.0).into_owned()
    }

    #[cfg(feature = "alloc")]
    #[must_use]
    pub fn into_string_lossy(self) -> String {
        String::from_utf8_lossy(&self.0).into_owned()
    }
}

impl<const MAX: u32> TryFrom<Vec<u8>> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: Vec<u8>) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(BytesM(v))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

impl<const MAX: u32> From<BytesM<MAX>> for Vec<u8> {
    #[must_use]
    fn from(v: BytesM<MAX>) -> Self {
        v.0
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> From<&BytesM<MAX>> for Vec<u8> {
    #[must_use]
    fn from(v: &BytesM<MAX>) -> Self {
        v.0.clone()
    }
}

impl<const MAX: u32> AsRef<Vec<u8>> for BytesM<MAX> {
    #[must_use]
    fn as_ref(&self) -> &Vec<u8> {
        &self.0
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&Vec<u8>> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: &Vec<u8>) -> Result<Self> {
        v.as_slice().try_into()
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&[u8]> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: &[u8]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(BytesM(v.to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

impl<const MAX: u32> AsRef<[u8]> for BytesM<MAX> {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref()
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        self.0
    }
}

#[cfg(feature = "alloc")]
impl<const N: usize, const MAX: u32> TryFrom<[u8; N]> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: [u8; N]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(BytesM(v.to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const N: usize, const MAX: u32> TryFrom<BytesM<MAX>> for [u8; N] {
    type Error = BytesM<MAX>;

    fn try_from(v: BytesM<MAX>) -> core::result::Result<Self, Self::Error> {
        let s: [u8; N] = v.0.try_into().map_err(BytesM::<MAX>)?;
        Ok(s)
    }
}

#[cfg(feature = "alloc")]
impl<const N: usize, const MAX: u32> TryFrom<&[u8; N]> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: &[u8; N]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(BytesM(v.to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(not(feature = "alloc"))]
impl<const N: usize, const MAX: u32> TryFrom<&'static [u8; N]> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: &'static [u8; N]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(BytesM(v))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&String> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: &String) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(BytesM(v.as_bytes().to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<String> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: String) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(BytesM(v.into()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<BytesM<MAX>> for String {
    type Error = Error;

    fn try_from(v: BytesM<MAX>) -> Result<Self> {
        Ok(String::from_utf8(v.0)?)
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&BytesM<MAX>> for String {
    type Error = Error;

    fn try_from(v: &BytesM<MAX>) -> Result<Self> {
        Ok(core::str::from_utf8(v.as_ref())?.to_owned())
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&str> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: &str) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(BytesM(v.into()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(not(feature = "alloc"))]
impl<const MAX: u32> TryFrom<&'static str> for BytesM<MAX> {
    type Error = Error;

    fn try_from(v: &'static str) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(BytesM(v.as_bytes()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

impl<'a, const MAX: u32> TryFrom<&'a BytesM<MAX>> for &'a str {
    type Error = Error;

    fn try_from(v: &'a BytesM<MAX>) -> Result<Self> {
        Ok(core::str::from_utf8(v.as_ref())?)
    }
}

impl<const MAX: u32> ReadXdr for BytesM<MAX> {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let len: u32 = u32::read_xdr(r)?;
        if len > MAX {
            return Err(Error::LengthExceedsMax);
        }

        let mut vec = vec![0u8; len as usize];
        r.read_exact(&mut vec)?;

        let pad = &mut [0u8; 3][..pad_len(len as usize)];
        r.read_exact(pad)?;
        if pad.iter().any(|b| *b != 0) {
            return Err(Error::NonZeroPadding);
        }

        Ok(BytesM(vec))
    }
}

impl<const MAX: u32> WriteXdr for BytesM<MAX> {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        len.write_xdr(w)?;

        w.write_all(&self.0)?;

        w.write_all(&[0u8; 3][..pad_len(len as usize)])?;

        Ok(())
    }
}

// StringM ------------------------------------------------------------------------

#[cfg(feature = "alloc")]
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(
    feature = "serde",
    derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub struct StringM<const MAX: u32 = { u32::MAX }>(Vec<u8>);

#[cfg(not(feature = "alloc"))]
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub struct StringM<const MAX: u32 = { u32::MAX }>(Vec<u8>);

/// `write_utf8_lossy` is a modified copy of the Rust stdlib docs examples here:
/// <https://doc.rust-lang.org/stable/core/str/struct.Utf8Error.html#examples>
fn write_utf8_lossy(f: &mut impl core::fmt::Write, mut input: &[u8]) -> core::fmt::Result {
    loop {
        match core::str::from_utf8(input) {
            Ok(valid) => {
                write!(f, "{valid}")?;
                break;
            }
            Err(error) => {
                let (valid, after_valid) = input.split_at(error.valid_up_to());
                write!(f, "{}", core::str::from_utf8(valid).unwrap())?;
                write!(f, "\u{FFFD}")?;

                if let Some(invalid_sequence_length) = error.error_len() {
                    input = &after_valid[invalid_sequence_length..];
                } else {
                    break;
                }
            }
        }
    }
    Ok(())
}

impl<const MAX: u32> core::fmt::Display for StringM<MAX> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        #[cfg(feature = "alloc")]
        let v = &self.0;
        #[cfg(not(feature = "alloc"))]
        let v = self.0;
        write_utf8_lossy(f, v)?;
        Ok(())
    }
}

impl<const MAX: u32> core::fmt::Debug for StringM<MAX> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        #[cfg(feature = "alloc")]
        let v = &self.0;
        #[cfg(not(feature = "alloc"))]
        let v = self.0;
        write!(f, "StringM(")?;
        write_utf8_lossy(f, v)?;
        write!(f, ")")?;
        Ok(())
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> core::str::FromStr for StringM<MAX> {
    type Err = Error;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        s.try_into()
    }
}

impl<const MAX: u32> Deref for StringM<MAX> {
    type Target = Vec<u8>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<const MAX: u32> Default for StringM<MAX> {
    fn default() -> Self {
        Self(Vec::default())
    }
}

impl<const MAX: u32> StringM<MAX> {
    pub const MAX_LEN: usize = { MAX as usize };

    #[must_use]
    #[allow(clippy::unused_self)]
    pub fn max_len(&self) -> usize {
        Self::MAX_LEN
    }

    #[must_use]
    pub fn as_vec(&self) -> &Vec<u8> {
        self.as_ref()
    }
}

impl<const MAX: u32> StringM<MAX> {
    #[must_use]
    #[cfg(feature = "alloc")]
    pub fn to_vec(&self) -> Vec<u8> {
        self.into()
    }

    #[must_use]
    pub fn into_vec(self) -> Vec<u8> {
        self.into()
    }
}

impl<const MAX: u32> StringM<MAX> {
    #[cfg(feature = "alloc")]
    pub fn to_string(&self) -> Result<String> {
        self.try_into()
    }

    #[cfg(feature = "alloc")]
    pub fn into_string(self) -> Result<String> {
        self.try_into()
    }

    #[cfg(feature = "alloc")]
    #[must_use]
    pub fn to_string_lossy(&self) -> String {
        String::from_utf8_lossy(&self.0).into_owned()
    }

    #[cfg(feature = "alloc")]
    #[must_use]
    pub fn into_string_lossy(self) -> String {
        String::from_utf8_lossy(&self.0).into_owned()
    }
}

impl<const MAX: u32> TryFrom<Vec<u8>> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: Vec<u8>) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(StringM(v))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

impl<const MAX: u32> From<StringM<MAX>> for Vec<u8> {
    #[must_use]
    fn from(v: StringM<MAX>) -> Self {
        v.0
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> From<&StringM<MAX>> for Vec<u8> {
    #[must_use]
    fn from(v: &StringM<MAX>) -> Self {
        v.0.clone()
    }
}

impl<const MAX: u32> AsRef<Vec<u8>> for StringM<MAX> {
    #[must_use]
    fn as_ref(&self) -> &Vec<u8> {
        &self.0
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&Vec<u8>> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: &Vec<u8>) -> Result<Self> {
        v.as_slice().try_into()
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&[u8]> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: &[u8]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(StringM(v.to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

impl<const MAX: u32> AsRef<[u8]> for StringM<MAX> {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref()
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        self.0
    }
}

#[cfg(feature = "alloc")]
impl<const N: usize, const MAX: u32> TryFrom<[u8; N]> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: [u8; N]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(StringM(v.to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const N: usize, const MAX: u32> TryFrom<StringM<MAX>> for [u8; N] {
    type Error = StringM<MAX>;

    fn try_from(v: StringM<MAX>) -> core::result::Result<Self, Self::Error> {
        let s: [u8; N] = v.0.try_into().map_err(StringM::<MAX>)?;
        Ok(s)
    }
}

#[cfg(feature = "alloc")]
impl<const N: usize, const MAX: u32> TryFrom<&[u8; N]> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: &[u8; N]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(StringM(v.to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(not(feature = "alloc"))]
impl<const N: usize, const MAX: u32> TryFrom<&'static [u8; N]> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: &'static [u8; N]) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(StringM(v))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&String> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: &String) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(StringM(v.as_bytes().to_vec()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<String> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: String) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(StringM(v.into()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<StringM<MAX>> for String {
    type Error = Error;

    fn try_from(v: StringM<MAX>) -> Result<Self> {
        Ok(String::from_utf8(v.0)?)
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&StringM<MAX>> for String {
    type Error = Error;

    fn try_from(v: &StringM<MAX>) -> Result<Self> {
        Ok(core::str::from_utf8(v.as_ref())?.to_owned())
    }
}

#[cfg(feature = "alloc")]
impl<const MAX: u32> TryFrom<&str> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: &str) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(StringM(v.into()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

#[cfg(not(feature = "alloc"))]
impl<const MAX: u32> TryFrom<&'static str> for StringM<MAX> {
    type Error = Error;

    fn try_from(v: &'static str) -> Result<Self> {
        let len: u32 = v.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        if len <= MAX {
            Ok(StringM(v.as_bytes()))
        } else {
            Err(Error::LengthExceedsMax)
        }
    }
}

impl<'a, const MAX: u32> TryFrom<&'a StringM<MAX>> for &'a str {
    type Error = Error;

    fn try_from(v: &'a StringM<MAX>) -> Result<Self> {
        Ok(core::str::from_utf8(v.as_ref())?)
    }
}

impl<const MAX: u32> ReadXdr for StringM<MAX> {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let len: u32 = u32::read_xdr(r)?;
        if len > MAX {
            return Err(Error::LengthExceedsMax);
        }

        let mut vec = vec![0u8; len as usize];
        r.read_exact(&mut vec)?;

        let pad = &mut [0u8; 3][..pad_len(len as usize)];
        r.read_exact(pad)?;
        if pad.iter().any(|b| *b != 0) {
            return Err(Error::NonZeroPadding);
        }

        Ok(StringM(vec))
    }
}

impl<const MAX: u32> WriteXdr for StringM<MAX> {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let len: u32 = self.len().try_into().map_err(|_| Error::LengthExceedsMax)?;
        len.write_xdr(w)?;

        w.write_all(&self.0)?;

        w.write_all(&[0u8; 3][..pad_len(len as usize)])?;

        Ok(())
    }
}

// Frame ------------------------------------------------------------------------

#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Frame<T>(pub T)
where
    T: ReadXdr;

impl<T> ReadXdr for Frame<T>
where
    T: ReadXdr,
{
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        // Read the frame header value that contains 1 flag-bit and a 33-bit length.
        //  - The 1 flag bit is 0 when there are more frames for the same record.
        //  - The 31-bit length is the length of the bytes within the frame that
        //  follow the frame header.
        let header = u32::read_xdr(r)?;
        // TODO: Use the length and cap the length we'll read from `r`.
        let last_record = header >> 31 == 1;
        if last_record {
            // Read the record in the frame.
            Ok(Self(T::read_xdr(r)?))
        } else {
            // TODO: Support reading those additional frames for the same
            // record.
            Err(Error::Unsupported)
        }
    }
}

#[cfg(all(test, feature = "std"))]
mod tests {
    use std::io::Cursor;

    use super::{Error, ReadXdr, VecM, WriteXdr};

    #[test]
    pub fn vec_u8_read_without_padding() {
        let mut buf = Cursor::new(vec![0, 0, 0, 4, 2, 2, 2, 2]);
        let v = VecM::<u8, 8>::read_xdr(&mut buf).unwrap();
        assert_eq!(v.to_vec(), vec![2, 2, 2, 2]);
    }

    #[test]
    pub fn vec_u8_read_with_padding() {
        let mut buf = Cursor::new(vec![0, 0, 0, 1, 2, 0, 0, 0]);
        let v = VecM::<u8, 8>::read_xdr(&mut buf).unwrap();
        assert_eq!(v.to_vec(), vec![2]);
    }

    #[test]
    pub fn vec_u8_read_with_insufficient_padding() {
        let mut buf = Cursor::new(vec![0, 0, 0, 1, 2, 0, 0]);
        let res = VecM::<u8, 8>::read_xdr(&mut buf);
        match res {
            Err(Error::Io(_)) => (),
            _ => panic!("expected IO error got {res:?}"),
        }
    }

    #[test]
    pub fn vec_u8_read_with_non_zero_padding() {
        let mut buf = Cursor::new(vec![0, 0, 0, 1, 2, 3, 0, 0]);
        let res = VecM::<u8, 8>::read_xdr(&mut buf);
        match res {
            Err(Error::NonZeroPadding) => (),
            _ => panic!("expected NonZeroPadding got {res:?}"),
        }
    }

    #[test]
    pub fn vec_u8_write_without_padding() {
        let mut buf = vec![];
        let v: VecM<u8, 8> = vec![2, 2, 2, 2].try_into().unwrap();
        v.write_xdr(&mut Cursor::new(&mut buf)).unwrap();
        assert_eq!(buf, vec![0, 0, 0, 4, 2, 2, 2, 2]);
    }

    #[test]
    pub fn vec_u8_write_with_padding() {
        let mut buf = vec![];
        let v: VecM<u8, 8> = vec![2].try_into().unwrap();
        v.write_xdr(&mut Cursor::new(&mut buf)).unwrap();
        assert_eq!(buf, vec![0, 0, 0, 1, 2, 0, 0, 0]);
    }

    #[test]
    pub fn arr_u8_read_without_padding() {
        let mut buf = Cursor::new(vec![2, 2, 2, 2]);
        let v = <[u8; 4]>::read_xdr(&mut buf).unwrap();
        assert_eq!(v, [2, 2, 2, 2]);
    }

    #[test]
    pub fn arr_u8_read_with_padding() {
        let mut buf = Cursor::new(vec![2, 0, 0, 0]);
        let v = <[u8; 1]>::read_xdr(&mut buf).unwrap();
        assert_eq!(v, [2]);
    }

    #[test]
    pub fn arr_u8_read_with_insufficient_padding() {
        let mut buf = Cursor::new(vec![2, 0, 0]);
        let res = <[u8; 1]>::read_xdr(&mut buf);
        match res {
            Err(Error::Io(_)) => (),
            _ => panic!("expected IO error got {res:?}"),
        }
    }

    #[test]
    pub fn arr_u8_read_with_non_zero_padding() {
        let mut buf = Cursor::new(vec![2, 3, 0, 0]);
        let res = <[u8; 1]>::read_xdr(&mut buf);
        match res {
            Err(Error::NonZeroPadding) => (),
            _ => panic!("expected NonZeroPadding got {res:?}"),
        }
    }

    #[test]
    pub fn arr_u8_write_without_padding() {
        let mut buf = vec![];
        [2u8, 2, 2, 2]
            .write_xdr(&mut Cursor::new(&mut buf))
            .unwrap();
        assert_eq!(buf, vec![2, 2, 2, 2]);
    }

    #[test]
    pub fn arr_u8_write_with_padding() {
        let mut buf = vec![];
        [2u8].write_xdr(&mut Cursor::new(&mut buf)).unwrap();
        assert_eq!(buf, vec![2, 0, 0, 0]);
    }
}

#[cfg(all(test, feature = "std"))]
mod test {
    use super::VecM;

    #[test]
    fn into_option_none() {
        let v: VecM<u32, 1> = vec![].try_into().unwrap();
        assert_eq!(v.into_option(), None);
    }

    #[test]
    fn into_option_some() {
        let v: VecM<_, 1> = vec![1].try_into().unwrap();
        assert_eq!(v.into_option(), Some(1));
    }

    #[test]
    fn to_option_none() {
        let v: VecM<u32, 1> = vec![].try_into().unwrap();
        assert_eq!(v.to_option(), None);
    }

    #[test]
    fn to_option_some() {
        let v: VecM<_, 1> = vec![1].try_into().unwrap();
        assert_eq!(v.to_option(), Some(1));
    }
}

#[cfg(all(test, not(feature = "alloc")))]
mod test {
    use super::VecM;

    #[test]
    fn to_option_none() {
        let v: VecM<u32, 1> = (&[]).try_into().unwrap();
        assert_eq!(v.to_option(), None);
    }

    #[test]
    fn to_option_some() {
        let v: VecM<_, 1> = (&[1]).try_into().unwrap();
        assert_eq!(v.to_option(), Some(1));
    }
}

// Value is an XDR Typedef defines as:
//
//   typedef opaque Value<>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Value(pub BytesM);

impl From<Value> for BytesM {
    #[must_use]
    fn from(x: Value) -> Self {
        x.0
    }
}

impl From<BytesM> for Value {
    #[must_use]
    fn from(x: BytesM) -> Self {
        Value(x)
    }
}

impl AsRef<BytesM> for Value {
    #[must_use]
    fn as_ref(&self) -> &BytesM {
        &self.0
    }
}

impl ReadXdr for Value {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = BytesM::read_xdr(r)?;
        let v = Value(i);
        Ok(v)
    }
}

impl WriteXdr for Value {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for Value {
    type Target = BytesM;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<Value> for Vec<u8> {
    #[must_use]
    fn from(x: Value) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<u8>> for Value {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        Ok(Value(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for Value {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        Ok(Value(x.try_into()?))
    }
}

impl AsRef<Vec<u8>> for Value {
    #[must_use]
    fn as_ref(&self) -> &Vec<u8> {
        &self.0 .0
    }
}

impl AsRef<[u8]> for Value {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        self.0 .0
    }
}

// ScpBallot is an XDR Struct defines as:
//
//   struct SCPBallot
//    {
//        uint32 counter; // n
//        Value value;    // x
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScpBallot {
    pub counter: u32,
    pub value: Value,
}

impl ReadXdr for ScpBallot {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            counter: u32::read_xdr(r)?,
            value: Value::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScpBallot {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.counter.write_xdr(w)?;
        self.value.write_xdr(w)?;
        Ok(())
    }
}

// ScpStatementType is an XDR Enum defines as:
//
//   enum SCPStatementType
//    {
//        SCP_ST_PREPARE = 0,
//        SCP_ST_CONFIRM = 1,
//        SCP_ST_EXTERNALIZE = 2,
//        SCP_ST_NOMINATE = 3
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScpStatementType {
    Prepare = 0,
    Confirm = 1,
    Externalize = 2,
    Nominate = 3,
}

impl ScpStatementType {
    pub const VARIANTS: [ScpStatementType; 4] = [
        ScpStatementType::Prepare,
        ScpStatementType::Confirm,
        ScpStatementType::Externalize,
        ScpStatementType::Nominate,
    ];
    pub const VARIANTS_STR: [&'static str; 4] = ["Prepare", "Confirm", "Externalize", "Nominate"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Prepare => "Prepare",
            Self::Confirm => "Confirm",
            Self::Externalize => "Externalize",
            Self::Nominate => "Nominate",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScpStatementType; 4] {
        Self::VARIANTS
    }
}

impl Name for ScpStatementType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScpStatementType> for ScpStatementType {
    fn variants() -> slice::Iter<'static, ScpStatementType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScpStatementType {}

impl fmt::Display for ScpStatementType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScpStatementType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScpStatementType::Prepare,
            1 => ScpStatementType::Confirm,
            2 => ScpStatementType::Externalize,
            3 => ScpStatementType::Nominate,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScpStatementType> for i32 {
    #[must_use]
    fn from(e: ScpStatementType) -> Self {
        e as Self
    }
}

impl ReadXdr for ScpStatementType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScpStatementType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScpNomination is an XDR Struct defines as:
//
//   struct SCPNomination
//    {
//        Hash quorumSetHash; // D
//        Value votes<>;      // X
//        Value accepted<>;   // Y
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScpNomination {
    pub quorum_set_hash: Hash,
    pub votes: VecM<Value>,
    pub accepted: VecM<Value>,
}

impl ReadXdr for ScpNomination {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            quorum_set_hash: Hash::read_xdr(r)?,
            votes: VecM::<Value>::read_xdr(r)?,
            accepted: VecM::<Value>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScpNomination {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.quorum_set_hash.write_xdr(w)?;
        self.votes.write_xdr(w)?;
        self.accepted.write_xdr(w)?;
        Ok(())
    }
}

// ScpStatementPrepare is an XDR NestedStruct defines as:
//
//   struct
//            {
//                Hash quorumSetHash;       // D
//                SCPBallot ballot;         // b
//                SCPBallot* prepared;      // p
//                SCPBallot* preparedPrime; // p'
//                uint32 nC;                // c.n
//                uint32 nH;                // h.n
//            }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScpStatementPrepare {
    pub quorum_set_hash: Hash,
    pub ballot: ScpBallot,
    pub prepared: Option<ScpBallot>,
    pub prepared_prime: Option<ScpBallot>,
    pub n_c: u32,
    pub n_h: u32,
}

impl ReadXdr for ScpStatementPrepare {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            quorum_set_hash: Hash::read_xdr(r)?,
            ballot: ScpBallot::read_xdr(r)?,
            prepared: Option::<ScpBallot>::read_xdr(r)?,
            prepared_prime: Option::<ScpBallot>::read_xdr(r)?,
            n_c: u32::read_xdr(r)?,
            n_h: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScpStatementPrepare {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.quorum_set_hash.write_xdr(w)?;
        self.ballot.write_xdr(w)?;
        self.prepared.write_xdr(w)?;
        self.prepared_prime.write_xdr(w)?;
        self.n_c.write_xdr(w)?;
        self.n_h.write_xdr(w)?;
        Ok(())
    }
}

// ScpStatementConfirm is an XDR NestedStruct defines as:
//
//   struct
//            {
//                SCPBallot ballot;   // b
//                uint32 nPrepared;   // p.n
//                uint32 nCommit;     // c.n
//                uint32 nH;          // h.n
//                Hash quorumSetHash; // D
//            }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScpStatementConfirm {
    pub ballot: ScpBallot,
    pub n_prepared: u32,
    pub n_commit: u32,
    pub n_h: u32,
    pub quorum_set_hash: Hash,
}

impl ReadXdr for ScpStatementConfirm {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ballot: ScpBallot::read_xdr(r)?,
            n_prepared: u32::read_xdr(r)?,
            n_commit: u32::read_xdr(r)?,
            n_h: u32::read_xdr(r)?,
            quorum_set_hash: Hash::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScpStatementConfirm {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ballot.write_xdr(w)?;
        self.n_prepared.write_xdr(w)?;
        self.n_commit.write_xdr(w)?;
        self.n_h.write_xdr(w)?;
        self.quorum_set_hash.write_xdr(w)?;
        Ok(())
    }
}

// ScpStatementExternalize is an XDR NestedStruct defines as:
//
//   struct
//            {
//                SCPBallot commit;         // c
//                uint32 nH;                // h.n
//                Hash commitQuorumSetHash; // D used before EXTERNALIZE
//            }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScpStatementExternalize {
    pub commit: ScpBallot,
    pub n_h: u32,
    pub commit_quorum_set_hash: Hash,
}

impl ReadXdr for ScpStatementExternalize {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            commit: ScpBallot::read_xdr(r)?,
            n_h: u32::read_xdr(r)?,
            commit_quorum_set_hash: Hash::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScpStatementExternalize {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.commit.write_xdr(w)?;
        self.n_h.write_xdr(w)?;
        self.commit_quorum_set_hash.write_xdr(w)?;
        Ok(())
    }
}

// ScpStatementPledges is an XDR NestedUnion defines as:
//
//   union switch (SCPStatementType type)
//        {
//        case SCP_ST_PREPARE:
//            struct
//            {
//                Hash quorumSetHash;       // D
//                SCPBallot ballot;         // b
//                SCPBallot* prepared;      // p
//                SCPBallot* preparedPrime; // p'
//                uint32 nC;                // c.n
//                uint32 nH;                // h.n
//            } prepare;
//        case SCP_ST_CONFIRM:
//            struct
//            {
//                SCPBallot ballot;   // b
//                uint32 nPrepared;   // p.n
//                uint32 nCommit;     // c.n
//                uint32 nH;          // h.n
//                Hash quorumSetHash; // D
//            } confirm;
//        case SCP_ST_EXTERNALIZE:
//            struct
//            {
//                SCPBallot commit;         // c
//                uint32 nH;                // h.n
//                Hash commitQuorumSetHash; // D used before EXTERNALIZE
//            } externalize;
//        case SCP_ST_NOMINATE:
//            SCPNomination nominate;
//        }
//
// union with discriminant ScpStatementType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ScpStatementPledges {
    Prepare(ScpStatementPrepare),
    Confirm(ScpStatementConfirm),
    Externalize(ScpStatementExternalize),
    Nominate(ScpNomination),
}

impl ScpStatementPledges {
    pub const VARIANTS: [ScpStatementType; 4] = [
        ScpStatementType::Prepare,
        ScpStatementType::Confirm,
        ScpStatementType::Externalize,
        ScpStatementType::Nominate,
    ];
    pub const VARIANTS_STR: [&'static str; 4] = ["Prepare", "Confirm", "Externalize", "Nominate"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Prepare(_) => "Prepare",
            Self::Confirm(_) => "Confirm",
            Self::Externalize(_) => "Externalize",
            Self::Nominate(_) => "Nominate",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ScpStatementType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Prepare(_) => ScpStatementType::Prepare,
            Self::Confirm(_) => ScpStatementType::Confirm,
            Self::Externalize(_) => ScpStatementType::Externalize,
            Self::Nominate(_) => ScpStatementType::Nominate,
        }
    }

    #[must_use]
    pub const fn variants() -> [ScpStatementType; 4] {
        Self::VARIANTS
    }
}

impl Name for ScpStatementPledges {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ScpStatementType> for ScpStatementPledges {
    #[must_use]
    fn discriminant(&self) -> ScpStatementType {
        Self::discriminant(self)
    }
}

impl Variants<ScpStatementType> for ScpStatementPledges {
    fn variants() -> slice::Iter<'static, ScpStatementType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ScpStatementType> for ScpStatementPledges {}

impl ReadXdr for ScpStatementPledges {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ScpStatementType = <ScpStatementType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ScpStatementType::Prepare => Self::Prepare(ScpStatementPrepare::read_xdr(r)?),
            ScpStatementType::Confirm => Self::Confirm(ScpStatementConfirm::read_xdr(r)?),
            ScpStatementType::Externalize => {
                Self::Externalize(ScpStatementExternalize::read_xdr(r)?)
            }
            ScpStatementType::Nominate => Self::Nominate(ScpNomination::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ScpStatementPledges {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Prepare(v) => v.write_xdr(w)?,
            Self::Confirm(v) => v.write_xdr(w)?,
            Self::Externalize(v) => v.write_xdr(w)?,
            Self::Nominate(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ScpStatement is an XDR Struct defines as:
//
//   struct SCPStatement
//    {
//        NodeID nodeID;    // v
//        uint64 slotIndex; // i
//
//        union switch (SCPStatementType type)
//        {
//        case SCP_ST_PREPARE:
//            struct
//            {
//                Hash quorumSetHash;       // D
//                SCPBallot ballot;         // b
//                SCPBallot* prepared;      // p
//                SCPBallot* preparedPrime; // p'
//                uint32 nC;                // c.n
//                uint32 nH;                // h.n
//            } prepare;
//        case SCP_ST_CONFIRM:
//            struct
//            {
//                SCPBallot ballot;   // b
//                uint32 nPrepared;   // p.n
//                uint32 nCommit;     // c.n
//                uint32 nH;          // h.n
//                Hash quorumSetHash; // D
//            } confirm;
//        case SCP_ST_EXTERNALIZE:
//            struct
//            {
//                SCPBallot commit;         // c
//                uint32 nH;                // h.n
//                Hash commitQuorumSetHash; // D used before EXTERNALIZE
//            } externalize;
//        case SCP_ST_NOMINATE:
//            SCPNomination nominate;
//        }
//        pledges;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScpStatement {
    pub node_id: NodeId,
    pub slot_index: u64,
    pub pledges: ScpStatementPledges,
}

impl ReadXdr for ScpStatement {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            node_id: NodeId::read_xdr(r)?,
            slot_index: u64::read_xdr(r)?,
            pledges: ScpStatementPledges::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScpStatement {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.node_id.write_xdr(w)?;
        self.slot_index.write_xdr(w)?;
        self.pledges.write_xdr(w)?;
        Ok(())
    }
}

// ScpEnvelope is an XDR Struct defines as:
//
//   struct SCPEnvelope
//    {
//        SCPStatement statement;
//        Signature signature;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScpEnvelope {
    pub statement: ScpStatement,
    pub signature: Signature,
}

impl ReadXdr for ScpEnvelope {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            statement: ScpStatement::read_xdr(r)?,
            signature: Signature::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScpEnvelope {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.statement.write_xdr(w)?;
        self.signature.write_xdr(w)?;
        Ok(())
    }
}

// ScpQuorumSet is an XDR Struct defines as:
//
//   struct SCPQuorumSet
//    {
//        uint32 threshold;
//        NodeID validators<>;
//        SCPQuorumSet innerSets<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScpQuorumSet {
    pub threshold: u32,
    pub validators: VecM<NodeId>,
    pub inner_sets: VecM<ScpQuorumSet>,
}

impl ReadXdr for ScpQuorumSet {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            threshold: u32::read_xdr(r)?,
            validators: VecM::<NodeId>::read_xdr(r)?,
            inner_sets: VecM::<ScpQuorumSet>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScpQuorumSet {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.threshold.write_xdr(w)?;
        self.validators.write_xdr(w)?;
        self.inner_sets.write_xdr(w)?;
        Ok(())
    }
}

// ScEnvMetaKind is an XDR Enum defines as:
//
//   enum SCEnvMetaKind
//    {
//        SC_ENV_META_KIND_INTERFACE_VERSION = 0
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScEnvMetaKind {
    ScEnvMetaKindInterfaceVersion = 0,
}

impl ScEnvMetaKind {
    pub const VARIANTS: [ScEnvMetaKind; 1] = [ScEnvMetaKind::ScEnvMetaKindInterfaceVersion];
    pub const VARIANTS_STR: [&'static str; 1] = ["ScEnvMetaKindInterfaceVersion"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ScEnvMetaKindInterfaceVersion => "ScEnvMetaKindInterfaceVersion",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScEnvMetaKind; 1] {
        Self::VARIANTS
    }
}

impl Name for ScEnvMetaKind {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScEnvMetaKind> for ScEnvMetaKind {
    fn variants() -> slice::Iter<'static, ScEnvMetaKind> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScEnvMetaKind {}

impl fmt::Display for ScEnvMetaKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScEnvMetaKind {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScEnvMetaKind::ScEnvMetaKindInterfaceVersion,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScEnvMetaKind> for i32 {
    #[must_use]
    fn from(e: ScEnvMetaKind) -> Self {
        e as Self
    }
}

impl ReadXdr for ScEnvMetaKind {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScEnvMetaKind {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScEnvMetaEntry is an XDR Union defines as:
//
//   union SCEnvMetaEntry switch (SCEnvMetaKind kind)
//    {
//    case SC_ENV_META_KIND_INTERFACE_VERSION:
//        uint64 interfaceVersion;
//    };
//
// union with discriminant ScEnvMetaKind
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ScEnvMetaEntry {
    ScEnvMetaKindInterfaceVersion(u64),
}

impl ScEnvMetaEntry {
    pub const VARIANTS: [ScEnvMetaKind; 1] = [ScEnvMetaKind::ScEnvMetaKindInterfaceVersion];
    pub const VARIANTS_STR: [&'static str; 1] = ["ScEnvMetaKindInterfaceVersion"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ScEnvMetaKindInterfaceVersion(_) => "ScEnvMetaKindInterfaceVersion",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ScEnvMetaKind {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ScEnvMetaKindInterfaceVersion(_) => ScEnvMetaKind::ScEnvMetaKindInterfaceVersion,
        }
    }

    #[must_use]
    pub const fn variants() -> [ScEnvMetaKind; 1] {
        Self::VARIANTS
    }
}

impl Name for ScEnvMetaEntry {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ScEnvMetaKind> for ScEnvMetaEntry {
    #[must_use]
    fn discriminant(&self) -> ScEnvMetaKind {
        Self::discriminant(self)
    }
}

impl Variants<ScEnvMetaKind> for ScEnvMetaEntry {
    fn variants() -> slice::Iter<'static, ScEnvMetaKind> {
        Self::VARIANTS.iter()
    }
}

impl Union<ScEnvMetaKind> for ScEnvMetaEntry {}

impl ReadXdr for ScEnvMetaEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ScEnvMetaKind = <ScEnvMetaKind as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ScEnvMetaKind::ScEnvMetaKindInterfaceVersion => {
                Self::ScEnvMetaKindInterfaceVersion(u64::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ScEnvMetaEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ScEnvMetaKindInterfaceVersion(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ScSpecType is an XDR Enum defines as:
//
//   enum SCSpecType
//    {
//        SC_SPEC_TYPE_VAL = 0,
//
//        // Types with no parameters.
//        SC_SPEC_TYPE_U32 = 1,
//        SC_SPEC_TYPE_I32 = 2,
//        SC_SPEC_TYPE_U64 = 3,
//        SC_SPEC_TYPE_I64 = 4,
//        SC_SPEC_TYPE_U128 = 5,
//        SC_SPEC_TYPE_I128 = 6,
//        SC_SPEC_TYPE_BOOL = 7,
//        SC_SPEC_TYPE_SYMBOL = 8,
//        SC_SPEC_TYPE_BITSET = 9,
//        SC_SPEC_TYPE_STATUS = 10,
//        SC_SPEC_TYPE_BYTES = 11,
//        SC_SPEC_TYPE_INVOKER = 12,
//        SC_SPEC_TYPE_ACCOUNT_ID = 13,
//
//        // Types with parameters.
//        SC_SPEC_TYPE_OPTION = 1000,
//        SC_SPEC_TYPE_RESULT = 1001,
//        SC_SPEC_TYPE_VEC = 1002,
//        SC_SPEC_TYPE_SET = 1003,
//        SC_SPEC_TYPE_MAP = 1004,
//        SC_SPEC_TYPE_TUPLE = 1005,
//        SC_SPEC_TYPE_BYTES_N = 1006,
//
//        // User defined types.
//        SC_SPEC_TYPE_UDT = 2000
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScSpecType {
    Val = 0,
    U32 = 1,
    I32 = 2,
    U64 = 3,
    I64 = 4,
    U128 = 5,
    I128 = 6,
    Bool = 7,
    Symbol = 8,
    Bitset = 9,
    Status = 10,
    Bytes = 11,
    Invoker = 12,
    AccountId = 13,
    Option = 1000,
    Result = 1001,
    Vec = 1002,
    Set = 1003,
    Map = 1004,
    Tuple = 1005,
    BytesN = 1006,
    Udt = 2000,
}

impl ScSpecType {
    pub const VARIANTS: [ScSpecType; 22] = [
        ScSpecType::Val,
        ScSpecType::U32,
        ScSpecType::I32,
        ScSpecType::U64,
        ScSpecType::I64,
        ScSpecType::U128,
        ScSpecType::I128,
        ScSpecType::Bool,
        ScSpecType::Symbol,
        ScSpecType::Bitset,
        ScSpecType::Status,
        ScSpecType::Bytes,
        ScSpecType::Invoker,
        ScSpecType::AccountId,
        ScSpecType::Option,
        ScSpecType::Result,
        ScSpecType::Vec,
        ScSpecType::Set,
        ScSpecType::Map,
        ScSpecType::Tuple,
        ScSpecType::BytesN,
        ScSpecType::Udt,
    ];
    pub const VARIANTS_STR: [&'static str; 22] = [
        "Val",
        "U32",
        "I32",
        "U64",
        "I64",
        "U128",
        "I128",
        "Bool",
        "Symbol",
        "Bitset",
        "Status",
        "Bytes",
        "Invoker",
        "AccountId",
        "Option",
        "Result",
        "Vec",
        "Set",
        "Map",
        "Tuple",
        "BytesN",
        "Udt",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Val => "Val",
            Self::U32 => "U32",
            Self::I32 => "I32",
            Self::U64 => "U64",
            Self::I64 => "I64",
            Self::U128 => "U128",
            Self::I128 => "I128",
            Self::Bool => "Bool",
            Self::Symbol => "Symbol",
            Self::Bitset => "Bitset",
            Self::Status => "Status",
            Self::Bytes => "Bytes",
            Self::Invoker => "Invoker",
            Self::AccountId => "AccountId",
            Self::Option => "Option",
            Self::Result => "Result",
            Self::Vec => "Vec",
            Self::Set => "Set",
            Self::Map => "Map",
            Self::Tuple => "Tuple",
            Self::BytesN => "BytesN",
            Self::Udt => "Udt",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScSpecType; 22] {
        Self::VARIANTS
    }
}

impl Name for ScSpecType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScSpecType> for ScSpecType {
    fn variants() -> slice::Iter<'static, ScSpecType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScSpecType {}

impl fmt::Display for ScSpecType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScSpecType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScSpecType::Val,
            1 => ScSpecType::U32,
            2 => ScSpecType::I32,
            3 => ScSpecType::U64,
            4 => ScSpecType::I64,
            5 => ScSpecType::U128,
            6 => ScSpecType::I128,
            7 => ScSpecType::Bool,
            8 => ScSpecType::Symbol,
            9 => ScSpecType::Bitset,
            10 => ScSpecType::Status,
            11 => ScSpecType::Bytes,
            12 => ScSpecType::Invoker,
            13 => ScSpecType::AccountId,
            1000 => ScSpecType::Option,
            1001 => ScSpecType::Result,
            1002 => ScSpecType::Vec,
            1003 => ScSpecType::Set,
            1004 => ScSpecType::Map,
            1005 => ScSpecType::Tuple,
            1006 => ScSpecType::BytesN,
            2000 => ScSpecType::Udt,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScSpecType> for i32 {
    #[must_use]
    fn from(e: ScSpecType) -> Self {
        e as Self
    }
}

impl ReadXdr for ScSpecType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScSpecType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScSpecTypeOption is an XDR Struct defines as:
//
//   struct SCSpecTypeOption
//    {
//        SCSpecTypeDef valueType;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecTypeOption {
    pub value_type: Box<ScSpecTypeDef>,
}

impl ReadXdr for ScSpecTypeOption {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            value_type: Box::<ScSpecTypeDef>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecTypeOption {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.value_type.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecTypeResult is an XDR Struct defines as:
//
//   struct SCSpecTypeResult
//    {
//        SCSpecTypeDef okType;
//        SCSpecTypeDef errorType;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecTypeResult {
    pub ok_type: Box<ScSpecTypeDef>,
    pub error_type: Box<ScSpecTypeDef>,
}

impl ReadXdr for ScSpecTypeResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ok_type: Box::<ScSpecTypeDef>::read_xdr(r)?,
            error_type: Box::<ScSpecTypeDef>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecTypeResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ok_type.write_xdr(w)?;
        self.error_type.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecTypeVec is an XDR Struct defines as:
//
//   struct SCSpecTypeVec
//    {
//        SCSpecTypeDef elementType;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecTypeVec {
    pub element_type: Box<ScSpecTypeDef>,
}

impl ReadXdr for ScSpecTypeVec {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            element_type: Box::<ScSpecTypeDef>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecTypeVec {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.element_type.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecTypeMap is an XDR Struct defines as:
//
//   struct SCSpecTypeMap
//    {
//        SCSpecTypeDef keyType;
//        SCSpecTypeDef valueType;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecTypeMap {
    pub key_type: Box<ScSpecTypeDef>,
    pub value_type: Box<ScSpecTypeDef>,
}

impl ReadXdr for ScSpecTypeMap {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            key_type: Box::<ScSpecTypeDef>::read_xdr(r)?,
            value_type: Box::<ScSpecTypeDef>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecTypeMap {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.key_type.write_xdr(w)?;
        self.value_type.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecTypeSet is an XDR Struct defines as:
//
//   struct SCSpecTypeSet
//    {
//        SCSpecTypeDef elementType;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecTypeSet {
    pub element_type: Box<ScSpecTypeDef>,
}

impl ReadXdr for ScSpecTypeSet {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            element_type: Box::<ScSpecTypeDef>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecTypeSet {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.element_type.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecTypeTuple is an XDR Struct defines as:
//
//   struct SCSpecTypeTuple
//    {
//        SCSpecTypeDef valueTypes<12>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecTypeTuple {
    pub value_types: VecM<ScSpecTypeDef, 12>,
}

impl ReadXdr for ScSpecTypeTuple {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            value_types: VecM::<ScSpecTypeDef, 12>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecTypeTuple {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.value_types.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecTypeBytesN is an XDR Struct defines as:
//
//   struct SCSpecTypeBytesN
//    {
//        uint32 n;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecTypeBytesN {
    pub n: u32,
}

impl ReadXdr for ScSpecTypeBytesN {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            n: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecTypeBytesN {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.n.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecTypeUdt is an XDR Struct defines as:
//
//   struct SCSpecTypeUDT
//    {
//        string name<60>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecTypeUdt {
    pub name: StringM<60>,
}

impl ReadXdr for ScSpecTypeUdt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            name: StringM::<60>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecTypeUdt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.name.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecTypeDef is an XDR Union defines as:
//
//   union SCSpecTypeDef switch (SCSpecType type)
//    {
//    case SC_SPEC_TYPE_VAL:
//    case SC_SPEC_TYPE_U64:
//    case SC_SPEC_TYPE_I64:
//    case SC_SPEC_TYPE_U128:
//    case SC_SPEC_TYPE_I128:
//    case SC_SPEC_TYPE_U32:
//    case SC_SPEC_TYPE_I32:
//    case SC_SPEC_TYPE_BOOL:
//    case SC_SPEC_TYPE_SYMBOL:
//    case SC_SPEC_TYPE_BITSET:
//    case SC_SPEC_TYPE_STATUS:
//    case SC_SPEC_TYPE_BYTES:
//    case SC_SPEC_TYPE_INVOKER:
//    case SC_SPEC_TYPE_ACCOUNT_ID:
//        void;
//    case SC_SPEC_TYPE_OPTION:
//        SCSpecTypeOption option;
//    case SC_SPEC_TYPE_RESULT:
//        SCSpecTypeResult result;
//    case SC_SPEC_TYPE_VEC:
//        SCSpecTypeVec vec;
//    case SC_SPEC_TYPE_MAP:
//        SCSpecTypeMap map;
//    case SC_SPEC_TYPE_SET:
//        SCSpecTypeSet set;
//    case SC_SPEC_TYPE_TUPLE:
//        SCSpecTypeTuple tuple;
//    case SC_SPEC_TYPE_BYTES_N:
//        SCSpecTypeBytesN bytesN;
//    case SC_SPEC_TYPE_UDT:
//        SCSpecTypeUDT udt;
//    };
//
// union with discriminant ScSpecType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ScSpecTypeDef {
    Val,
    U64,
    I64,
    U128,
    I128,
    U32,
    I32,
    Bool,
    Symbol,
    Bitset,
    Status,
    Bytes,
    Invoker,
    AccountId,
    Option(Box<ScSpecTypeOption>),
    Result(Box<ScSpecTypeResult>),
    Vec(Box<ScSpecTypeVec>),
    Map(Box<ScSpecTypeMap>),
    Set(Box<ScSpecTypeSet>),
    Tuple(Box<ScSpecTypeTuple>),
    BytesN(ScSpecTypeBytesN),
    Udt(ScSpecTypeUdt),
}

impl ScSpecTypeDef {
    pub const VARIANTS: [ScSpecType; 22] = [
        ScSpecType::Val,
        ScSpecType::U64,
        ScSpecType::I64,
        ScSpecType::U128,
        ScSpecType::I128,
        ScSpecType::U32,
        ScSpecType::I32,
        ScSpecType::Bool,
        ScSpecType::Symbol,
        ScSpecType::Bitset,
        ScSpecType::Status,
        ScSpecType::Bytes,
        ScSpecType::Invoker,
        ScSpecType::AccountId,
        ScSpecType::Option,
        ScSpecType::Result,
        ScSpecType::Vec,
        ScSpecType::Map,
        ScSpecType::Set,
        ScSpecType::Tuple,
        ScSpecType::BytesN,
        ScSpecType::Udt,
    ];
    pub const VARIANTS_STR: [&'static str; 22] = [
        "Val",
        "U64",
        "I64",
        "U128",
        "I128",
        "U32",
        "I32",
        "Bool",
        "Symbol",
        "Bitset",
        "Status",
        "Bytes",
        "Invoker",
        "AccountId",
        "Option",
        "Result",
        "Vec",
        "Map",
        "Set",
        "Tuple",
        "BytesN",
        "Udt",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Val => "Val",
            Self::U64 => "U64",
            Self::I64 => "I64",
            Self::U128 => "U128",
            Self::I128 => "I128",
            Self::U32 => "U32",
            Self::I32 => "I32",
            Self::Bool => "Bool",
            Self::Symbol => "Symbol",
            Self::Bitset => "Bitset",
            Self::Status => "Status",
            Self::Bytes => "Bytes",
            Self::Invoker => "Invoker",
            Self::AccountId => "AccountId",
            Self::Option(_) => "Option",
            Self::Result(_) => "Result",
            Self::Vec(_) => "Vec",
            Self::Map(_) => "Map",
            Self::Set(_) => "Set",
            Self::Tuple(_) => "Tuple",
            Self::BytesN(_) => "BytesN",
            Self::Udt(_) => "Udt",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ScSpecType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Val => ScSpecType::Val,
            Self::U64 => ScSpecType::U64,
            Self::I64 => ScSpecType::I64,
            Self::U128 => ScSpecType::U128,
            Self::I128 => ScSpecType::I128,
            Self::U32 => ScSpecType::U32,
            Self::I32 => ScSpecType::I32,
            Self::Bool => ScSpecType::Bool,
            Self::Symbol => ScSpecType::Symbol,
            Self::Bitset => ScSpecType::Bitset,
            Self::Status => ScSpecType::Status,
            Self::Bytes => ScSpecType::Bytes,
            Self::Invoker => ScSpecType::Invoker,
            Self::AccountId => ScSpecType::AccountId,
            Self::Option(_) => ScSpecType::Option,
            Self::Result(_) => ScSpecType::Result,
            Self::Vec(_) => ScSpecType::Vec,
            Self::Map(_) => ScSpecType::Map,
            Self::Set(_) => ScSpecType::Set,
            Self::Tuple(_) => ScSpecType::Tuple,
            Self::BytesN(_) => ScSpecType::BytesN,
            Self::Udt(_) => ScSpecType::Udt,
        }
    }

    #[must_use]
    pub const fn variants() -> [ScSpecType; 22] {
        Self::VARIANTS
    }
}

impl Name for ScSpecTypeDef {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ScSpecType> for ScSpecTypeDef {
    #[must_use]
    fn discriminant(&self) -> ScSpecType {
        Self::discriminant(self)
    }
}

impl Variants<ScSpecType> for ScSpecTypeDef {
    fn variants() -> slice::Iter<'static, ScSpecType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ScSpecType> for ScSpecTypeDef {}

impl ReadXdr for ScSpecTypeDef {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ScSpecType = <ScSpecType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ScSpecType::Val => Self::Val,
            ScSpecType::U64 => Self::U64,
            ScSpecType::I64 => Self::I64,
            ScSpecType::U128 => Self::U128,
            ScSpecType::I128 => Self::I128,
            ScSpecType::U32 => Self::U32,
            ScSpecType::I32 => Self::I32,
            ScSpecType::Bool => Self::Bool,
            ScSpecType::Symbol => Self::Symbol,
            ScSpecType::Bitset => Self::Bitset,
            ScSpecType::Status => Self::Status,
            ScSpecType::Bytes => Self::Bytes,
            ScSpecType::Invoker => Self::Invoker,
            ScSpecType::AccountId => Self::AccountId,
            ScSpecType::Option => Self::Option(Box::<ScSpecTypeOption>::read_xdr(r)?),
            ScSpecType::Result => Self::Result(Box::<ScSpecTypeResult>::read_xdr(r)?),
            ScSpecType::Vec => Self::Vec(Box::<ScSpecTypeVec>::read_xdr(r)?),
            ScSpecType::Map => Self::Map(Box::<ScSpecTypeMap>::read_xdr(r)?),
            ScSpecType::Set => Self::Set(Box::<ScSpecTypeSet>::read_xdr(r)?),
            ScSpecType::Tuple => Self::Tuple(Box::<ScSpecTypeTuple>::read_xdr(r)?),
            ScSpecType::BytesN => Self::BytesN(ScSpecTypeBytesN::read_xdr(r)?),
            ScSpecType::Udt => Self::Udt(ScSpecTypeUdt::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ScSpecTypeDef {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Val => ().write_xdr(w)?,
            Self::U64 => ().write_xdr(w)?,
            Self::I64 => ().write_xdr(w)?,
            Self::U128 => ().write_xdr(w)?,
            Self::I128 => ().write_xdr(w)?,
            Self::U32 => ().write_xdr(w)?,
            Self::I32 => ().write_xdr(w)?,
            Self::Bool => ().write_xdr(w)?,
            Self::Symbol => ().write_xdr(w)?,
            Self::Bitset => ().write_xdr(w)?,
            Self::Status => ().write_xdr(w)?,
            Self::Bytes => ().write_xdr(w)?,
            Self::Invoker => ().write_xdr(w)?,
            Self::AccountId => ().write_xdr(w)?,
            Self::Option(v) => v.write_xdr(w)?,
            Self::Result(v) => v.write_xdr(w)?,
            Self::Vec(v) => v.write_xdr(w)?,
            Self::Map(v) => v.write_xdr(w)?,
            Self::Set(v) => v.write_xdr(w)?,
            Self::Tuple(v) => v.write_xdr(w)?,
            Self::BytesN(v) => v.write_xdr(w)?,
            Self::Udt(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ScSpecUdtStructFieldV0 is an XDR Struct defines as:
//
//   struct SCSpecUDTStructFieldV0
//    {
//        string name<30>;
//        SCSpecTypeDef type;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecUdtStructFieldV0 {
    pub name: StringM<30>,
    pub type_: ScSpecTypeDef,
}

impl ReadXdr for ScSpecUdtStructFieldV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            name: StringM::<30>::read_xdr(r)?,
            type_: ScSpecTypeDef::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecUdtStructFieldV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.name.write_xdr(w)?;
        self.type_.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecUdtStructV0 is an XDR Struct defines as:
//
//   struct SCSpecUDTStructV0
//    {
//        string lib<80>;
//        string name<60>;
//        SCSpecUDTStructFieldV0 fields<40>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecUdtStructV0 {
    pub lib: StringM<80>,
    pub name: StringM<60>,
    pub fields: VecM<ScSpecUdtStructFieldV0, 40>,
}

impl ReadXdr for ScSpecUdtStructV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            lib: StringM::<80>::read_xdr(r)?,
            name: StringM::<60>::read_xdr(r)?,
            fields: VecM::<ScSpecUdtStructFieldV0, 40>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecUdtStructV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.lib.write_xdr(w)?;
        self.name.write_xdr(w)?;
        self.fields.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecUdtUnionCaseV0 is an XDR Struct defines as:
//
//   struct SCSpecUDTUnionCaseV0
//    {
//        string name<60>;
//        SCSpecTypeDef *type;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecUdtUnionCaseV0 {
    pub name: StringM<60>,
    pub type_: Option<ScSpecTypeDef>,
}

impl ReadXdr for ScSpecUdtUnionCaseV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            name: StringM::<60>::read_xdr(r)?,
            type_: Option::<ScSpecTypeDef>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecUdtUnionCaseV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.name.write_xdr(w)?;
        self.type_.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecUdtUnionV0 is an XDR Struct defines as:
//
//   struct SCSpecUDTUnionV0
//    {
//        string lib<80>;
//        string name<60>;
//        SCSpecUDTUnionCaseV0 cases<50>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecUdtUnionV0 {
    pub lib: StringM<80>,
    pub name: StringM<60>,
    pub cases: VecM<ScSpecUdtUnionCaseV0, 50>,
}

impl ReadXdr for ScSpecUdtUnionV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            lib: StringM::<80>::read_xdr(r)?,
            name: StringM::<60>::read_xdr(r)?,
            cases: VecM::<ScSpecUdtUnionCaseV0, 50>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecUdtUnionV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.lib.write_xdr(w)?;
        self.name.write_xdr(w)?;
        self.cases.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecUdtEnumCaseV0 is an XDR Struct defines as:
//
//   struct SCSpecUDTEnumCaseV0
//    {
//        string name<60>;
//        uint32 value;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecUdtEnumCaseV0 {
    pub name: StringM<60>,
    pub value: u32,
}

impl ReadXdr for ScSpecUdtEnumCaseV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            name: StringM::<60>::read_xdr(r)?,
            value: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecUdtEnumCaseV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.name.write_xdr(w)?;
        self.value.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecUdtEnumV0 is an XDR Struct defines as:
//
//   struct SCSpecUDTEnumV0
//    {
//        string lib<80>;
//        string name<60>;
//        SCSpecUDTEnumCaseV0 cases<50>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecUdtEnumV0 {
    pub lib: StringM<80>,
    pub name: StringM<60>,
    pub cases: VecM<ScSpecUdtEnumCaseV0, 50>,
}

impl ReadXdr for ScSpecUdtEnumV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            lib: StringM::<80>::read_xdr(r)?,
            name: StringM::<60>::read_xdr(r)?,
            cases: VecM::<ScSpecUdtEnumCaseV0, 50>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecUdtEnumV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.lib.write_xdr(w)?;
        self.name.write_xdr(w)?;
        self.cases.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecUdtErrorEnumCaseV0 is an XDR Struct defines as:
//
//   struct SCSpecUDTErrorEnumCaseV0
//    {
//        string name<60>;
//        uint32 value;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecUdtErrorEnumCaseV0 {
    pub name: StringM<60>,
    pub value: u32,
}

impl ReadXdr for ScSpecUdtErrorEnumCaseV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            name: StringM::<60>::read_xdr(r)?,
            value: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecUdtErrorEnumCaseV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.name.write_xdr(w)?;
        self.value.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecUdtErrorEnumV0 is an XDR Struct defines as:
//
//   struct SCSpecUDTErrorEnumV0
//    {
//        string lib<80>;
//        string name<60>;
//        SCSpecUDTErrorEnumCaseV0 cases<50>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecUdtErrorEnumV0 {
    pub lib: StringM<80>,
    pub name: StringM<60>,
    pub cases: VecM<ScSpecUdtErrorEnumCaseV0, 50>,
}

impl ReadXdr for ScSpecUdtErrorEnumV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            lib: StringM::<80>::read_xdr(r)?,
            name: StringM::<60>::read_xdr(r)?,
            cases: VecM::<ScSpecUdtErrorEnumCaseV0, 50>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecUdtErrorEnumV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.lib.write_xdr(w)?;
        self.name.write_xdr(w)?;
        self.cases.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecFunctionInputV0 is an XDR Struct defines as:
//
//   struct SCSpecFunctionInputV0
//    {
//        string name<30>;
//        SCSpecTypeDef type;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecFunctionInputV0 {
    pub name: StringM<30>,
    pub type_: ScSpecTypeDef,
}

impl ReadXdr for ScSpecFunctionInputV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            name: StringM::<30>::read_xdr(r)?,
            type_: ScSpecTypeDef::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecFunctionInputV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.name.write_xdr(w)?;
        self.type_.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecFunctionV0 is an XDR Struct defines as:
//
//   struct SCSpecFunctionV0
//    {
//        SCSymbol name;
//        SCSpecFunctionInputV0 inputs<10>;
//        SCSpecTypeDef outputs<1>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScSpecFunctionV0 {
    pub name: StringM<10>,
    pub inputs: VecM<ScSpecFunctionInputV0, 10>,
    pub outputs: VecM<ScSpecTypeDef, 1>,
}

impl ReadXdr for ScSpecFunctionV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            name: StringM::<10>::read_xdr(r)?,
            inputs: VecM::<ScSpecFunctionInputV0, 10>::read_xdr(r)?,
            outputs: VecM::<ScSpecTypeDef, 1>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScSpecFunctionV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.name.write_xdr(w)?;
        self.inputs.write_xdr(w)?;
        self.outputs.write_xdr(w)?;
        Ok(())
    }
}

// ScSpecEntryKind is an XDR Enum defines as:
//
//   enum SCSpecEntryKind
//    {
//        SC_SPEC_ENTRY_FUNCTION_V0 = 0,
//        SC_SPEC_ENTRY_UDT_STRUCT_V0 = 1,
//        SC_SPEC_ENTRY_UDT_UNION_V0 = 2,
//        SC_SPEC_ENTRY_UDT_ENUM_V0 = 3,
//        SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0 = 4
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScSpecEntryKind {
    FunctionV0 = 0,
    UdtStructV0 = 1,
    UdtUnionV0 = 2,
    UdtEnumV0 = 3,
    UdtErrorEnumV0 = 4,
}

impl ScSpecEntryKind {
    pub const VARIANTS: [ScSpecEntryKind; 5] = [
        ScSpecEntryKind::FunctionV0,
        ScSpecEntryKind::UdtStructV0,
        ScSpecEntryKind::UdtUnionV0,
        ScSpecEntryKind::UdtEnumV0,
        ScSpecEntryKind::UdtErrorEnumV0,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "FunctionV0",
        "UdtStructV0",
        "UdtUnionV0",
        "UdtEnumV0",
        "UdtErrorEnumV0",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::FunctionV0 => "FunctionV0",
            Self::UdtStructV0 => "UdtStructV0",
            Self::UdtUnionV0 => "UdtUnionV0",
            Self::UdtEnumV0 => "UdtEnumV0",
            Self::UdtErrorEnumV0 => "UdtErrorEnumV0",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScSpecEntryKind; 5] {
        Self::VARIANTS
    }
}

impl Name for ScSpecEntryKind {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScSpecEntryKind> for ScSpecEntryKind {
    fn variants() -> slice::Iter<'static, ScSpecEntryKind> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScSpecEntryKind {}

impl fmt::Display for ScSpecEntryKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScSpecEntryKind {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScSpecEntryKind::FunctionV0,
            1 => ScSpecEntryKind::UdtStructV0,
            2 => ScSpecEntryKind::UdtUnionV0,
            3 => ScSpecEntryKind::UdtEnumV0,
            4 => ScSpecEntryKind::UdtErrorEnumV0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScSpecEntryKind> for i32 {
    #[must_use]
    fn from(e: ScSpecEntryKind) -> Self {
        e as Self
    }
}

impl ReadXdr for ScSpecEntryKind {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScSpecEntryKind {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScSpecEntry is an XDR Union defines as:
//
//   union SCSpecEntry switch (SCSpecEntryKind kind)
//    {
//    case SC_SPEC_ENTRY_FUNCTION_V0:
//        SCSpecFunctionV0 functionV0;
//    case SC_SPEC_ENTRY_UDT_STRUCT_V0:
//        SCSpecUDTStructV0 udtStructV0;
//    case SC_SPEC_ENTRY_UDT_UNION_V0:
//        SCSpecUDTUnionV0 udtUnionV0;
//    case SC_SPEC_ENTRY_UDT_ENUM_V0:
//        SCSpecUDTEnumV0 udtEnumV0;
//    case SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0:
//        SCSpecUDTErrorEnumV0 udtErrorEnumV0;
//    };
//
// union with discriminant ScSpecEntryKind
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ScSpecEntry {
    FunctionV0(ScSpecFunctionV0),
    UdtStructV0(ScSpecUdtStructV0),
    UdtUnionV0(ScSpecUdtUnionV0),
    UdtEnumV0(ScSpecUdtEnumV0),
    UdtErrorEnumV0(ScSpecUdtErrorEnumV0),
}

impl ScSpecEntry {
    pub const VARIANTS: [ScSpecEntryKind; 5] = [
        ScSpecEntryKind::FunctionV0,
        ScSpecEntryKind::UdtStructV0,
        ScSpecEntryKind::UdtUnionV0,
        ScSpecEntryKind::UdtEnumV0,
        ScSpecEntryKind::UdtErrorEnumV0,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "FunctionV0",
        "UdtStructV0",
        "UdtUnionV0",
        "UdtEnumV0",
        "UdtErrorEnumV0",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::FunctionV0(_) => "FunctionV0",
            Self::UdtStructV0(_) => "UdtStructV0",
            Self::UdtUnionV0(_) => "UdtUnionV0",
            Self::UdtEnumV0(_) => "UdtEnumV0",
            Self::UdtErrorEnumV0(_) => "UdtErrorEnumV0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ScSpecEntryKind {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::FunctionV0(_) => ScSpecEntryKind::FunctionV0,
            Self::UdtStructV0(_) => ScSpecEntryKind::UdtStructV0,
            Self::UdtUnionV0(_) => ScSpecEntryKind::UdtUnionV0,
            Self::UdtEnumV0(_) => ScSpecEntryKind::UdtEnumV0,
            Self::UdtErrorEnumV0(_) => ScSpecEntryKind::UdtErrorEnumV0,
        }
    }

    #[must_use]
    pub const fn variants() -> [ScSpecEntryKind; 5] {
        Self::VARIANTS
    }
}

impl Name for ScSpecEntry {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ScSpecEntryKind> for ScSpecEntry {
    #[must_use]
    fn discriminant(&self) -> ScSpecEntryKind {
        Self::discriminant(self)
    }
}

impl Variants<ScSpecEntryKind> for ScSpecEntry {
    fn variants() -> slice::Iter<'static, ScSpecEntryKind> {
        Self::VARIANTS.iter()
    }
}

impl Union<ScSpecEntryKind> for ScSpecEntry {}

impl ReadXdr for ScSpecEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ScSpecEntryKind = <ScSpecEntryKind as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ScSpecEntryKind::FunctionV0 => Self::FunctionV0(ScSpecFunctionV0::read_xdr(r)?),
            ScSpecEntryKind::UdtStructV0 => Self::UdtStructV0(ScSpecUdtStructV0::read_xdr(r)?),
            ScSpecEntryKind::UdtUnionV0 => Self::UdtUnionV0(ScSpecUdtUnionV0::read_xdr(r)?),
            ScSpecEntryKind::UdtEnumV0 => Self::UdtEnumV0(ScSpecUdtEnumV0::read_xdr(r)?),
            ScSpecEntryKind::UdtErrorEnumV0 => {
                Self::UdtErrorEnumV0(ScSpecUdtErrorEnumV0::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ScSpecEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::FunctionV0(v) => v.write_xdr(w)?,
            Self::UdtStructV0(v) => v.write_xdr(w)?,
            Self::UdtUnionV0(v) => v.write_xdr(w)?,
            Self::UdtEnumV0(v) => v.write_xdr(w)?,
            Self::UdtErrorEnumV0(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ScSymbol is an XDR Typedef defines as:
//
//   typedef string SCSymbol<10>;
//
pub type ScSymbol = StringM<10>;

// ScValType is an XDR Enum defines as:
//
//   enum SCValType
//    {
//        SCV_U63 = 0,
//        SCV_U32 = 1,
//        SCV_I32 = 2,
//        SCV_STATIC = 3,
//        SCV_OBJECT = 4,
//        SCV_SYMBOL = 5,
//        SCV_BITSET = 6,
//        SCV_STATUS = 7
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScValType {
    U63 = 0,
    U32 = 1,
    I32 = 2,
    Static = 3,
    Object = 4,
    Symbol = 5,
    Bitset = 6,
    Status = 7,
}

impl ScValType {
    pub const VARIANTS: [ScValType; 8] = [
        ScValType::U63,
        ScValType::U32,
        ScValType::I32,
        ScValType::Static,
        ScValType::Object,
        ScValType::Symbol,
        ScValType::Bitset,
        ScValType::Status,
    ];
    pub const VARIANTS_STR: [&'static str; 8] = [
        "U63", "U32", "I32", "Static", "Object", "Symbol", "Bitset", "Status",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::U63 => "U63",
            Self::U32 => "U32",
            Self::I32 => "I32",
            Self::Static => "Static",
            Self::Object => "Object",
            Self::Symbol => "Symbol",
            Self::Bitset => "Bitset",
            Self::Status => "Status",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScValType; 8] {
        Self::VARIANTS
    }
}

impl Name for ScValType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScValType> for ScValType {
    fn variants() -> slice::Iter<'static, ScValType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScValType {}

impl fmt::Display for ScValType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScValType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScValType::U63,
            1 => ScValType::U32,
            2 => ScValType::I32,
            3 => ScValType::Static,
            4 => ScValType::Object,
            5 => ScValType::Symbol,
            6 => ScValType::Bitset,
            7 => ScValType::Status,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScValType> for i32 {
    #[must_use]
    fn from(e: ScValType) -> Self {
        e as Self
    }
}

impl ReadXdr for ScValType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScValType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScStatic is an XDR Enum defines as:
//
//   enum SCStatic
//    {
//        SCS_VOID = 0,
//        SCS_TRUE = 1,
//        SCS_FALSE = 2,
//        SCS_LEDGER_KEY_CONTRACT_CODE = 3
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScStatic {
    Void = 0,
    True = 1,
    False = 2,
    LedgerKeyContractCode = 3,
}

impl ScStatic {
    pub const VARIANTS: [ScStatic; 4] = [
        ScStatic::Void,
        ScStatic::True,
        ScStatic::False,
        ScStatic::LedgerKeyContractCode,
    ];
    pub const VARIANTS_STR: [&'static str; 4] = ["Void", "True", "False", "LedgerKeyContractCode"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Void => "Void",
            Self::True => "True",
            Self::False => "False",
            Self::LedgerKeyContractCode => "LedgerKeyContractCode",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScStatic; 4] {
        Self::VARIANTS
    }
}

impl Name for ScStatic {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScStatic> for ScStatic {
    fn variants() -> slice::Iter<'static, ScStatic> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScStatic {}

impl fmt::Display for ScStatic {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScStatic {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScStatic::Void,
            1 => ScStatic::True,
            2 => ScStatic::False,
            3 => ScStatic::LedgerKeyContractCode,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScStatic> for i32 {
    #[must_use]
    fn from(e: ScStatic) -> Self {
        e as Self
    }
}

impl ReadXdr for ScStatic {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScStatic {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScStatusType is an XDR Enum defines as:
//
//   enum SCStatusType
//    {
//        SST_OK = 0,
//        SST_UNKNOWN_ERROR = 1,
//        SST_HOST_VALUE_ERROR = 2,
//        SST_HOST_OBJECT_ERROR = 3,
//        SST_HOST_FUNCTION_ERROR = 4,
//        SST_HOST_STORAGE_ERROR = 5,
//        SST_HOST_CONTEXT_ERROR = 6,
//        SST_VM_ERROR = 7,
//        SST_CONTRACT_ERROR = 8
//        // TODO: add more
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScStatusType {
    Ok = 0,
    UnknownError = 1,
    HostValueError = 2,
    HostObjectError = 3,
    HostFunctionError = 4,
    HostStorageError = 5,
    HostContextError = 6,
    VmError = 7,
    ContractError = 8,
}

impl ScStatusType {
    pub const VARIANTS: [ScStatusType; 9] = [
        ScStatusType::Ok,
        ScStatusType::UnknownError,
        ScStatusType::HostValueError,
        ScStatusType::HostObjectError,
        ScStatusType::HostFunctionError,
        ScStatusType::HostStorageError,
        ScStatusType::HostContextError,
        ScStatusType::VmError,
        ScStatusType::ContractError,
    ];
    pub const VARIANTS_STR: [&'static str; 9] = [
        "Ok",
        "UnknownError",
        "HostValueError",
        "HostObjectError",
        "HostFunctionError",
        "HostStorageError",
        "HostContextError",
        "VmError",
        "ContractError",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Ok => "Ok",
            Self::UnknownError => "UnknownError",
            Self::HostValueError => "HostValueError",
            Self::HostObjectError => "HostObjectError",
            Self::HostFunctionError => "HostFunctionError",
            Self::HostStorageError => "HostStorageError",
            Self::HostContextError => "HostContextError",
            Self::VmError => "VmError",
            Self::ContractError => "ContractError",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScStatusType; 9] {
        Self::VARIANTS
    }
}

impl Name for ScStatusType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScStatusType> for ScStatusType {
    fn variants() -> slice::Iter<'static, ScStatusType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScStatusType {}

impl fmt::Display for ScStatusType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScStatusType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScStatusType::Ok,
            1 => ScStatusType::UnknownError,
            2 => ScStatusType::HostValueError,
            3 => ScStatusType::HostObjectError,
            4 => ScStatusType::HostFunctionError,
            5 => ScStatusType::HostStorageError,
            6 => ScStatusType::HostContextError,
            7 => ScStatusType::VmError,
            8 => ScStatusType::ContractError,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScStatusType> for i32 {
    #[must_use]
    fn from(e: ScStatusType) -> Self {
        e as Self
    }
}

impl ReadXdr for ScStatusType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScStatusType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScHostValErrorCode is an XDR Enum defines as:
//
//   enum SCHostValErrorCode
//    {
//        HOST_VALUE_UNKNOWN_ERROR = 0,
//        HOST_VALUE_RESERVED_TAG_VALUE = 1,
//        HOST_VALUE_UNEXPECTED_VAL_TYPE = 2,
//        HOST_VALUE_U63_OUT_OF_RANGE = 3,
//        HOST_VALUE_U32_OUT_OF_RANGE = 4,
//        HOST_VALUE_STATIC_UNKNOWN = 5,
//        HOST_VALUE_MISSING_OBJECT = 6,
//        HOST_VALUE_SYMBOL_TOO_LONG = 7,
//        HOST_VALUE_SYMBOL_BAD_CHAR = 8,
//        HOST_VALUE_SYMBOL_CONTAINS_NON_UTF8 = 9,
//        HOST_VALUE_BITSET_TOO_MANY_BITS = 10,
//        HOST_VALUE_STATUS_UNKNOWN = 11
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScHostValErrorCode {
    UnknownError = 0,
    ReservedTagValue = 1,
    UnexpectedValType = 2,
    U63OutOfRange = 3,
    U32OutOfRange = 4,
    StaticUnknown = 5,
    MissingObject = 6,
    SymbolTooLong = 7,
    SymbolBadChar = 8,
    SymbolContainsNonUtf8 = 9,
    BitsetTooManyBits = 10,
    StatusUnknown = 11,
}

impl ScHostValErrorCode {
    pub const VARIANTS: [ScHostValErrorCode; 12] = [
        ScHostValErrorCode::UnknownError,
        ScHostValErrorCode::ReservedTagValue,
        ScHostValErrorCode::UnexpectedValType,
        ScHostValErrorCode::U63OutOfRange,
        ScHostValErrorCode::U32OutOfRange,
        ScHostValErrorCode::StaticUnknown,
        ScHostValErrorCode::MissingObject,
        ScHostValErrorCode::SymbolTooLong,
        ScHostValErrorCode::SymbolBadChar,
        ScHostValErrorCode::SymbolContainsNonUtf8,
        ScHostValErrorCode::BitsetTooManyBits,
        ScHostValErrorCode::StatusUnknown,
    ];
    pub const VARIANTS_STR: [&'static str; 12] = [
        "UnknownError",
        "ReservedTagValue",
        "UnexpectedValType",
        "U63OutOfRange",
        "U32OutOfRange",
        "StaticUnknown",
        "MissingObject",
        "SymbolTooLong",
        "SymbolBadChar",
        "SymbolContainsNonUtf8",
        "BitsetTooManyBits",
        "StatusUnknown",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::UnknownError => "UnknownError",
            Self::ReservedTagValue => "ReservedTagValue",
            Self::UnexpectedValType => "UnexpectedValType",
            Self::U63OutOfRange => "U63OutOfRange",
            Self::U32OutOfRange => "U32OutOfRange",
            Self::StaticUnknown => "StaticUnknown",
            Self::MissingObject => "MissingObject",
            Self::SymbolTooLong => "SymbolTooLong",
            Self::SymbolBadChar => "SymbolBadChar",
            Self::SymbolContainsNonUtf8 => "SymbolContainsNonUtf8",
            Self::BitsetTooManyBits => "BitsetTooManyBits",
            Self::StatusUnknown => "StatusUnknown",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScHostValErrorCode; 12] {
        Self::VARIANTS
    }
}

impl Name for ScHostValErrorCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScHostValErrorCode> for ScHostValErrorCode {
    fn variants() -> slice::Iter<'static, ScHostValErrorCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScHostValErrorCode {}

impl fmt::Display for ScHostValErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScHostValErrorCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScHostValErrorCode::UnknownError,
            1 => ScHostValErrorCode::ReservedTagValue,
            2 => ScHostValErrorCode::UnexpectedValType,
            3 => ScHostValErrorCode::U63OutOfRange,
            4 => ScHostValErrorCode::U32OutOfRange,
            5 => ScHostValErrorCode::StaticUnknown,
            6 => ScHostValErrorCode::MissingObject,
            7 => ScHostValErrorCode::SymbolTooLong,
            8 => ScHostValErrorCode::SymbolBadChar,
            9 => ScHostValErrorCode::SymbolContainsNonUtf8,
            10 => ScHostValErrorCode::BitsetTooManyBits,
            11 => ScHostValErrorCode::StatusUnknown,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScHostValErrorCode> for i32 {
    #[must_use]
    fn from(e: ScHostValErrorCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ScHostValErrorCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScHostValErrorCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScHostObjErrorCode is an XDR Enum defines as:
//
//   enum SCHostObjErrorCode
//    {
//        HOST_OBJECT_UNKNOWN_ERROR = 0,
//        HOST_OBJECT_UNKNOWN_REFERENCE = 1,
//        HOST_OBJECT_UNEXPECTED_TYPE = 2,
//        HOST_OBJECT_OBJECT_COUNT_EXCEEDS_U32_MAX = 3,
//        HOST_OBJECT_OBJECT_NOT_EXIST = 4,
//        HOST_OBJECT_VEC_INDEX_OUT_OF_BOUND = 5,
//        HOST_OBJECT_CONTRACT_HASH_WRONG_LENGTH = 6
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScHostObjErrorCode {
    UnknownError = 0,
    UnknownReference = 1,
    UnexpectedType = 2,
    ObjectCountExceedsU32Max = 3,
    ObjectNotExist = 4,
    VecIndexOutOfBound = 5,
    ContractHashWrongLength = 6,
}

impl ScHostObjErrorCode {
    pub const VARIANTS: [ScHostObjErrorCode; 7] = [
        ScHostObjErrorCode::UnknownError,
        ScHostObjErrorCode::UnknownReference,
        ScHostObjErrorCode::UnexpectedType,
        ScHostObjErrorCode::ObjectCountExceedsU32Max,
        ScHostObjErrorCode::ObjectNotExist,
        ScHostObjErrorCode::VecIndexOutOfBound,
        ScHostObjErrorCode::ContractHashWrongLength,
    ];
    pub const VARIANTS_STR: [&'static str; 7] = [
        "UnknownError",
        "UnknownReference",
        "UnexpectedType",
        "ObjectCountExceedsU32Max",
        "ObjectNotExist",
        "VecIndexOutOfBound",
        "ContractHashWrongLength",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::UnknownError => "UnknownError",
            Self::UnknownReference => "UnknownReference",
            Self::UnexpectedType => "UnexpectedType",
            Self::ObjectCountExceedsU32Max => "ObjectCountExceedsU32Max",
            Self::ObjectNotExist => "ObjectNotExist",
            Self::VecIndexOutOfBound => "VecIndexOutOfBound",
            Self::ContractHashWrongLength => "ContractHashWrongLength",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScHostObjErrorCode; 7] {
        Self::VARIANTS
    }
}

impl Name for ScHostObjErrorCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScHostObjErrorCode> for ScHostObjErrorCode {
    fn variants() -> slice::Iter<'static, ScHostObjErrorCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScHostObjErrorCode {}

impl fmt::Display for ScHostObjErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScHostObjErrorCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScHostObjErrorCode::UnknownError,
            1 => ScHostObjErrorCode::UnknownReference,
            2 => ScHostObjErrorCode::UnexpectedType,
            3 => ScHostObjErrorCode::ObjectCountExceedsU32Max,
            4 => ScHostObjErrorCode::ObjectNotExist,
            5 => ScHostObjErrorCode::VecIndexOutOfBound,
            6 => ScHostObjErrorCode::ContractHashWrongLength,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScHostObjErrorCode> for i32 {
    #[must_use]
    fn from(e: ScHostObjErrorCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ScHostObjErrorCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScHostObjErrorCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScHostFnErrorCode is an XDR Enum defines as:
//
//   enum SCHostFnErrorCode
//    {
//        HOST_FN_UNKNOWN_ERROR = 0,
//        HOST_FN_UNEXPECTED_HOST_FUNCTION_ACTION = 1,
//        HOST_FN_INPUT_ARGS_WRONG_LENGTH = 2,
//        HOST_FN_INPUT_ARGS_WRONG_TYPE = 3,
//        HOST_FN_INPUT_ARGS_INVALID = 4
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScHostFnErrorCode {
    UnknownError = 0,
    UnexpectedHostFunctionAction = 1,
    InputArgsWrongLength = 2,
    InputArgsWrongType = 3,
    InputArgsInvalid = 4,
}

impl ScHostFnErrorCode {
    pub const VARIANTS: [ScHostFnErrorCode; 5] = [
        ScHostFnErrorCode::UnknownError,
        ScHostFnErrorCode::UnexpectedHostFunctionAction,
        ScHostFnErrorCode::InputArgsWrongLength,
        ScHostFnErrorCode::InputArgsWrongType,
        ScHostFnErrorCode::InputArgsInvalid,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "UnknownError",
        "UnexpectedHostFunctionAction",
        "InputArgsWrongLength",
        "InputArgsWrongType",
        "InputArgsInvalid",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::UnknownError => "UnknownError",
            Self::UnexpectedHostFunctionAction => "UnexpectedHostFunctionAction",
            Self::InputArgsWrongLength => "InputArgsWrongLength",
            Self::InputArgsWrongType => "InputArgsWrongType",
            Self::InputArgsInvalid => "InputArgsInvalid",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScHostFnErrorCode; 5] {
        Self::VARIANTS
    }
}

impl Name for ScHostFnErrorCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScHostFnErrorCode> for ScHostFnErrorCode {
    fn variants() -> slice::Iter<'static, ScHostFnErrorCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScHostFnErrorCode {}

impl fmt::Display for ScHostFnErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScHostFnErrorCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScHostFnErrorCode::UnknownError,
            1 => ScHostFnErrorCode::UnexpectedHostFunctionAction,
            2 => ScHostFnErrorCode::InputArgsWrongLength,
            3 => ScHostFnErrorCode::InputArgsWrongType,
            4 => ScHostFnErrorCode::InputArgsInvalid,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScHostFnErrorCode> for i32 {
    #[must_use]
    fn from(e: ScHostFnErrorCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ScHostFnErrorCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScHostFnErrorCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScHostStorageErrorCode is an XDR Enum defines as:
//
//   enum SCHostStorageErrorCode
//    {
//        HOST_STORAGE_UNKNOWN_ERROR = 0,
//        HOST_STORAGE_EXPECT_CONTRACT_DATA = 1,
//        HOST_STORAGE_READWRITE_ACCESS_TO_READONLY_ENTRY = 2,
//        HOST_STORAGE_ACCESS_TO_UNKNOWN_ENTRY = 3,
//        HOST_STORAGE_MISSING_KEY_IN_GET = 4,
//        HOST_STORAGE_GET_ON_DELETED_KEY = 5
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScHostStorageErrorCode {
    UnknownError = 0,
    ExpectContractData = 1,
    ReadwriteAccessToReadonlyEntry = 2,
    AccessToUnknownEntry = 3,
    MissingKeyInGet = 4,
    GetOnDeletedKey = 5,
}

impl ScHostStorageErrorCode {
    pub const VARIANTS: [ScHostStorageErrorCode; 6] = [
        ScHostStorageErrorCode::UnknownError,
        ScHostStorageErrorCode::ExpectContractData,
        ScHostStorageErrorCode::ReadwriteAccessToReadonlyEntry,
        ScHostStorageErrorCode::AccessToUnknownEntry,
        ScHostStorageErrorCode::MissingKeyInGet,
        ScHostStorageErrorCode::GetOnDeletedKey,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "UnknownError",
        "ExpectContractData",
        "ReadwriteAccessToReadonlyEntry",
        "AccessToUnknownEntry",
        "MissingKeyInGet",
        "GetOnDeletedKey",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::UnknownError => "UnknownError",
            Self::ExpectContractData => "ExpectContractData",
            Self::ReadwriteAccessToReadonlyEntry => "ReadwriteAccessToReadonlyEntry",
            Self::AccessToUnknownEntry => "AccessToUnknownEntry",
            Self::MissingKeyInGet => "MissingKeyInGet",
            Self::GetOnDeletedKey => "GetOnDeletedKey",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScHostStorageErrorCode; 6] {
        Self::VARIANTS
    }
}

impl Name for ScHostStorageErrorCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScHostStorageErrorCode> for ScHostStorageErrorCode {
    fn variants() -> slice::Iter<'static, ScHostStorageErrorCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScHostStorageErrorCode {}

impl fmt::Display for ScHostStorageErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScHostStorageErrorCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScHostStorageErrorCode::UnknownError,
            1 => ScHostStorageErrorCode::ExpectContractData,
            2 => ScHostStorageErrorCode::ReadwriteAccessToReadonlyEntry,
            3 => ScHostStorageErrorCode::AccessToUnknownEntry,
            4 => ScHostStorageErrorCode::MissingKeyInGet,
            5 => ScHostStorageErrorCode::GetOnDeletedKey,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScHostStorageErrorCode> for i32 {
    #[must_use]
    fn from(e: ScHostStorageErrorCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ScHostStorageErrorCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScHostStorageErrorCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScHostContextErrorCode is an XDR Enum defines as:
//
//   enum SCHostContextErrorCode
//    {
//        HOST_CONTEXT_UNKNOWN_ERROR = 0,
//        HOST_CONTEXT_NO_CONTRACT_RUNNING = 1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScHostContextErrorCode {
    UnknownError = 0,
    NoContractRunning = 1,
}

impl ScHostContextErrorCode {
    pub const VARIANTS: [ScHostContextErrorCode; 2] = [
        ScHostContextErrorCode::UnknownError,
        ScHostContextErrorCode::NoContractRunning,
    ];
    pub const VARIANTS_STR: [&'static str; 2] = ["UnknownError", "NoContractRunning"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::UnknownError => "UnknownError",
            Self::NoContractRunning => "NoContractRunning",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScHostContextErrorCode; 2] {
        Self::VARIANTS
    }
}

impl Name for ScHostContextErrorCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScHostContextErrorCode> for ScHostContextErrorCode {
    fn variants() -> slice::Iter<'static, ScHostContextErrorCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScHostContextErrorCode {}

impl fmt::Display for ScHostContextErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScHostContextErrorCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScHostContextErrorCode::UnknownError,
            1 => ScHostContextErrorCode::NoContractRunning,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScHostContextErrorCode> for i32 {
    #[must_use]
    fn from(e: ScHostContextErrorCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ScHostContextErrorCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScHostContextErrorCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScVmErrorCode is an XDR Enum defines as:
//
//   enum SCVmErrorCode {
//        VM_UNKNOWN = 0,
//        VM_VALIDATION = 1,
//        VM_INSTANTIATION = 2,
//        VM_FUNCTION = 3,
//        VM_TABLE = 4,
//        VM_MEMORY = 5,
//        VM_GLOBAL = 6,
//        VM_VALUE = 7,
//        VM_TRAP_UNREACHABLE = 8,
//        VM_TRAP_MEMORY_ACCESS_OUT_OF_BOUNDS = 9,
//        VM_TRAP_TABLE_ACCESS_OUT_OF_BOUNDS = 10,
//        VM_TRAP_ELEM_UNINITIALIZED = 11,
//        VM_TRAP_DIVISION_BY_ZERO = 12,
//        VM_TRAP_INTEGER_OVERFLOW = 13,
//        VM_TRAP_INVALID_CONVERSION_TO_INT = 14,
//        VM_TRAP_STACK_OVERFLOW = 15,
//        VM_TRAP_UNEXPECTED_SIGNATURE = 16,
//        VM_TRAP_MEM_LIMIT_EXCEEDED = 17,
//        VM_TRAP_CPU_LIMIT_EXCEEDED = 18
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScVmErrorCode {
    Unknown = 0,
    Validation = 1,
    Instantiation = 2,
    Function = 3,
    Table = 4,
    Memory = 5,
    Global = 6,
    Value = 7,
    TrapUnreachable = 8,
    TrapMemoryAccessOutOfBounds = 9,
    TrapTableAccessOutOfBounds = 10,
    TrapElemUninitialized = 11,
    TrapDivisionByZero = 12,
    TrapIntegerOverflow = 13,
    TrapInvalidConversionToInt = 14,
    TrapStackOverflow = 15,
    TrapUnexpectedSignature = 16,
    TrapMemLimitExceeded = 17,
    TrapCpuLimitExceeded = 18,
}

impl ScVmErrorCode {
    pub const VARIANTS: [ScVmErrorCode; 19] = [
        ScVmErrorCode::Unknown,
        ScVmErrorCode::Validation,
        ScVmErrorCode::Instantiation,
        ScVmErrorCode::Function,
        ScVmErrorCode::Table,
        ScVmErrorCode::Memory,
        ScVmErrorCode::Global,
        ScVmErrorCode::Value,
        ScVmErrorCode::TrapUnreachable,
        ScVmErrorCode::TrapMemoryAccessOutOfBounds,
        ScVmErrorCode::TrapTableAccessOutOfBounds,
        ScVmErrorCode::TrapElemUninitialized,
        ScVmErrorCode::TrapDivisionByZero,
        ScVmErrorCode::TrapIntegerOverflow,
        ScVmErrorCode::TrapInvalidConversionToInt,
        ScVmErrorCode::TrapStackOverflow,
        ScVmErrorCode::TrapUnexpectedSignature,
        ScVmErrorCode::TrapMemLimitExceeded,
        ScVmErrorCode::TrapCpuLimitExceeded,
    ];
    pub const VARIANTS_STR: [&'static str; 19] = [
        "Unknown",
        "Validation",
        "Instantiation",
        "Function",
        "Table",
        "Memory",
        "Global",
        "Value",
        "TrapUnreachable",
        "TrapMemoryAccessOutOfBounds",
        "TrapTableAccessOutOfBounds",
        "TrapElemUninitialized",
        "TrapDivisionByZero",
        "TrapIntegerOverflow",
        "TrapInvalidConversionToInt",
        "TrapStackOverflow",
        "TrapUnexpectedSignature",
        "TrapMemLimitExceeded",
        "TrapCpuLimitExceeded",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Unknown => "Unknown",
            Self::Validation => "Validation",
            Self::Instantiation => "Instantiation",
            Self::Function => "Function",
            Self::Table => "Table",
            Self::Memory => "Memory",
            Self::Global => "Global",
            Self::Value => "Value",
            Self::TrapUnreachable => "TrapUnreachable",
            Self::TrapMemoryAccessOutOfBounds => "TrapMemoryAccessOutOfBounds",
            Self::TrapTableAccessOutOfBounds => "TrapTableAccessOutOfBounds",
            Self::TrapElemUninitialized => "TrapElemUninitialized",
            Self::TrapDivisionByZero => "TrapDivisionByZero",
            Self::TrapIntegerOverflow => "TrapIntegerOverflow",
            Self::TrapInvalidConversionToInt => "TrapInvalidConversionToInt",
            Self::TrapStackOverflow => "TrapStackOverflow",
            Self::TrapUnexpectedSignature => "TrapUnexpectedSignature",
            Self::TrapMemLimitExceeded => "TrapMemLimitExceeded",
            Self::TrapCpuLimitExceeded => "TrapCpuLimitExceeded",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScVmErrorCode; 19] {
        Self::VARIANTS
    }
}

impl Name for ScVmErrorCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScVmErrorCode> for ScVmErrorCode {
    fn variants() -> slice::Iter<'static, ScVmErrorCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScVmErrorCode {}

impl fmt::Display for ScVmErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScVmErrorCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScVmErrorCode::Unknown,
            1 => ScVmErrorCode::Validation,
            2 => ScVmErrorCode::Instantiation,
            3 => ScVmErrorCode::Function,
            4 => ScVmErrorCode::Table,
            5 => ScVmErrorCode::Memory,
            6 => ScVmErrorCode::Global,
            7 => ScVmErrorCode::Value,
            8 => ScVmErrorCode::TrapUnreachable,
            9 => ScVmErrorCode::TrapMemoryAccessOutOfBounds,
            10 => ScVmErrorCode::TrapTableAccessOutOfBounds,
            11 => ScVmErrorCode::TrapElemUninitialized,
            12 => ScVmErrorCode::TrapDivisionByZero,
            13 => ScVmErrorCode::TrapIntegerOverflow,
            14 => ScVmErrorCode::TrapInvalidConversionToInt,
            15 => ScVmErrorCode::TrapStackOverflow,
            16 => ScVmErrorCode::TrapUnexpectedSignature,
            17 => ScVmErrorCode::TrapMemLimitExceeded,
            18 => ScVmErrorCode::TrapCpuLimitExceeded,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScVmErrorCode> for i32 {
    #[must_use]
    fn from(e: ScVmErrorCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ScVmErrorCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScVmErrorCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScUnknownErrorCode is an XDR Enum defines as:
//
//   enum SCUnknownErrorCode
//    {
//        UNKNOWN_ERROR_GENERAL = 0,
//        UNKNOWN_ERROR_XDR = 1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScUnknownErrorCode {
    General = 0,
    Xdr = 1,
}

impl ScUnknownErrorCode {
    pub const VARIANTS: [ScUnknownErrorCode; 2] =
        [ScUnknownErrorCode::General, ScUnknownErrorCode::Xdr];
    pub const VARIANTS_STR: [&'static str; 2] = ["General", "Xdr"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::General => "General",
            Self::Xdr => "Xdr",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScUnknownErrorCode; 2] {
        Self::VARIANTS
    }
}

impl Name for ScUnknownErrorCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScUnknownErrorCode> for ScUnknownErrorCode {
    fn variants() -> slice::Iter<'static, ScUnknownErrorCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScUnknownErrorCode {}

impl fmt::Display for ScUnknownErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScUnknownErrorCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScUnknownErrorCode::General,
            1 => ScUnknownErrorCode::Xdr,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScUnknownErrorCode> for i32 {
    #[must_use]
    fn from(e: ScUnknownErrorCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ScUnknownErrorCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScUnknownErrorCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScStatus is an XDR Union defines as:
//
//   union SCStatus switch (SCStatusType type)
//    {
//    case SST_OK:
//        void;
//    case SST_UNKNOWN_ERROR:
//        SCUnknownErrorCode unknownCode;
//    case SST_HOST_VALUE_ERROR:
//        SCHostValErrorCode valCode;
//    case SST_HOST_OBJECT_ERROR:
//        SCHostObjErrorCode objCode;
//    case SST_HOST_FUNCTION_ERROR:
//        SCHostFnErrorCode fnCode;
//    case SST_HOST_STORAGE_ERROR:
//        SCHostStorageErrorCode storageCode;
//    case SST_HOST_CONTEXT_ERROR:
//        SCHostContextErrorCode contextCode;
//    case SST_VM_ERROR:
//        SCVmErrorCode vmCode;
//    case SST_CONTRACT_ERROR:
//        uint32 contractCode;
//    };
//
// union with discriminant ScStatusType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ScStatus {
    Ok,
    UnknownError(ScUnknownErrorCode),
    HostValueError(ScHostValErrorCode),
    HostObjectError(ScHostObjErrorCode),
    HostFunctionError(ScHostFnErrorCode),
    HostStorageError(ScHostStorageErrorCode),
    HostContextError(ScHostContextErrorCode),
    VmError(ScVmErrorCode),
    ContractError(u32),
}

impl ScStatus {
    pub const VARIANTS: [ScStatusType; 9] = [
        ScStatusType::Ok,
        ScStatusType::UnknownError,
        ScStatusType::HostValueError,
        ScStatusType::HostObjectError,
        ScStatusType::HostFunctionError,
        ScStatusType::HostStorageError,
        ScStatusType::HostContextError,
        ScStatusType::VmError,
        ScStatusType::ContractError,
    ];
    pub const VARIANTS_STR: [&'static str; 9] = [
        "Ok",
        "UnknownError",
        "HostValueError",
        "HostObjectError",
        "HostFunctionError",
        "HostStorageError",
        "HostContextError",
        "VmError",
        "ContractError",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Ok => "Ok",
            Self::UnknownError(_) => "UnknownError",
            Self::HostValueError(_) => "HostValueError",
            Self::HostObjectError(_) => "HostObjectError",
            Self::HostFunctionError(_) => "HostFunctionError",
            Self::HostStorageError(_) => "HostStorageError",
            Self::HostContextError(_) => "HostContextError",
            Self::VmError(_) => "VmError",
            Self::ContractError(_) => "ContractError",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ScStatusType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Ok => ScStatusType::Ok,
            Self::UnknownError(_) => ScStatusType::UnknownError,
            Self::HostValueError(_) => ScStatusType::HostValueError,
            Self::HostObjectError(_) => ScStatusType::HostObjectError,
            Self::HostFunctionError(_) => ScStatusType::HostFunctionError,
            Self::HostStorageError(_) => ScStatusType::HostStorageError,
            Self::HostContextError(_) => ScStatusType::HostContextError,
            Self::VmError(_) => ScStatusType::VmError,
            Self::ContractError(_) => ScStatusType::ContractError,
        }
    }

    #[must_use]
    pub const fn variants() -> [ScStatusType; 9] {
        Self::VARIANTS
    }
}

impl Name for ScStatus {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ScStatusType> for ScStatus {
    #[must_use]
    fn discriminant(&self) -> ScStatusType {
        Self::discriminant(self)
    }
}

impl Variants<ScStatusType> for ScStatus {
    fn variants() -> slice::Iter<'static, ScStatusType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ScStatusType> for ScStatus {}

impl ReadXdr for ScStatus {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ScStatusType = <ScStatusType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ScStatusType::Ok => Self::Ok,
            ScStatusType::UnknownError => Self::UnknownError(ScUnknownErrorCode::read_xdr(r)?),
            ScStatusType::HostValueError => Self::HostValueError(ScHostValErrorCode::read_xdr(r)?),
            ScStatusType::HostObjectError => {
                Self::HostObjectError(ScHostObjErrorCode::read_xdr(r)?)
            }
            ScStatusType::HostFunctionError => {
                Self::HostFunctionError(ScHostFnErrorCode::read_xdr(r)?)
            }
            ScStatusType::HostStorageError => {
                Self::HostStorageError(ScHostStorageErrorCode::read_xdr(r)?)
            }
            ScStatusType::HostContextError => {
                Self::HostContextError(ScHostContextErrorCode::read_xdr(r)?)
            }
            ScStatusType::VmError => Self::VmError(ScVmErrorCode::read_xdr(r)?),
            ScStatusType::ContractError => Self::ContractError(u32::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ScStatus {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Ok => ().write_xdr(w)?,
            Self::UnknownError(v) => v.write_xdr(w)?,
            Self::HostValueError(v) => v.write_xdr(w)?,
            Self::HostObjectError(v) => v.write_xdr(w)?,
            Self::HostFunctionError(v) => v.write_xdr(w)?,
            Self::HostStorageError(v) => v.write_xdr(w)?,
            Self::HostContextError(v) => v.write_xdr(w)?,
            Self::VmError(v) => v.write_xdr(w)?,
            Self::ContractError(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ScVal is an XDR Union defines as:
//
//   union SCVal switch (SCValType type)
//    {
//    case SCV_U63:
//        int64 u63;
//    case SCV_U32:
//        uint32 u32;
//    case SCV_I32:
//        int32 i32;
//    case SCV_STATIC:
//        SCStatic ic;
//    case SCV_OBJECT:
//        SCObject* obj;
//    case SCV_SYMBOL:
//        SCSymbol sym;
//    case SCV_BITSET:
//        uint64 bits;
//    case SCV_STATUS:
//        SCStatus status;
//    };
//
// union with discriminant ScValType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ScVal {
    U63(i64),
    U32(u32),
    I32(i32),
    Static(ScStatic),
    Object(Option<ScObject>),
    Symbol(StringM<10>),
    Bitset(u64),
    Status(ScStatus),
}

impl ScVal {
    pub const VARIANTS: [ScValType; 8] = [
        ScValType::U63,
        ScValType::U32,
        ScValType::I32,
        ScValType::Static,
        ScValType::Object,
        ScValType::Symbol,
        ScValType::Bitset,
        ScValType::Status,
    ];
    pub const VARIANTS_STR: [&'static str; 8] = [
        "U63", "U32", "I32", "Static", "Object", "Symbol", "Bitset", "Status",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::U63(_) => "U63",
            Self::U32(_) => "U32",
            Self::I32(_) => "I32",
            Self::Static(_) => "Static",
            Self::Object(_) => "Object",
            Self::Symbol(_) => "Symbol",
            Self::Bitset(_) => "Bitset",
            Self::Status(_) => "Status",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ScValType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::U63(_) => ScValType::U63,
            Self::U32(_) => ScValType::U32,
            Self::I32(_) => ScValType::I32,
            Self::Static(_) => ScValType::Static,
            Self::Object(_) => ScValType::Object,
            Self::Symbol(_) => ScValType::Symbol,
            Self::Bitset(_) => ScValType::Bitset,
            Self::Status(_) => ScValType::Status,
        }
    }

    #[must_use]
    pub const fn variants() -> [ScValType; 8] {
        Self::VARIANTS
    }
}

impl Name for ScVal {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ScValType> for ScVal {
    #[must_use]
    fn discriminant(&self) -> ScValType {
        Self::discriminant(self)
    }
}

impl Variants<ScValType> for ScVal {
    fn variants() -> slice::Iter<'static, ScValType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ScValType> for ScVal {}

impl ReadXdr for ScVal {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ScValType = <ScValType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ScValType::U63 => Self::U63(i64::read_xdr(r)?),
            ScValType::U32 => Self::U32(u32::read_xdr(r)?),
            ScValType::I32 => Self::I32(i32::read_xdr(r)?),
            ScValType::Static => Self::Static(ScStatic::read_xdr(r)?),
            ScValType::Object => Self::Object(Option::<ScObject>::read_xdr(r)?),
            ScValType::Symbol => Self::Symbol(StringM::<10>::read_xdr(r)?),
            ScValType::Bitset => Self::Bitset(u64::read_xdr(r)?),
            ScValType::Status => Self::Status(ScStatus::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ScVal {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::U63(v) => v.write_xdr(w)?,
            Self::U32(v) => v.write_xdr(w)?,
            Self::I32(v) => v.write_xdr(w)?,
            Self::Static(v) => v.write_xdr(w)?,
            Self::Object(v) => v.write_xdr(w)?,
            Self::Symbol(v) => v.write_xdr(w)?,
            Self::Bitset(v) => v.write_xdr(w)?,
            Self::Status(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ScObjectType is an XDR Enum defines as:
//
//   enum SCObjectType
//    {
//        // We have a few objects that represent non-stellar-specific concepts
//        // like general-purpose maps, vectors, numbers, blobs.
//
//        SCO_VEC = 0,
//        SCO_MAP = 1,
//        SCO_U64 = 2,
//        SCO_I64 = 3,
//        SCO_U128 = 4,
//        SCO_I128 = 5,
//        SCO_BYTES = 6,
//        SCO_CONTRACT_CODE = 7,
//        SCO_ACCOUNT_ID = 8
//
//        // TODO: add more
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScObjectType {
    Vec = 0,
    Map = 1,
    U64 = 2,
    I64 = 3,
    U128 = 4,
    I128 = 5,
    Bytes = 6,
    ContractCode = 7,
    AccountId = 8,
}

impl ScObjectType {
    pub const VARIANTS: [ScObjectType; 9] = [
        ScObjectType::Vec,
        ScObjectType::Map,
        ScObjectType::U64,
        ScObjectType::I64,
        ScObjectType::U128,
        ScObjectType::I128,
        ScObjectType::Bytes,
        ScObjectType::ContractCode,
        ScObjectType::AccountId,
    ];
    pub const VARIANTS_STR: [&'static str; 9] = [
        "Vec",
        "Map",
        "U64",
        "I64",
        "U128",
        "I128",
        "Bytes",
        "ContractCode",
        "AccountId",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Vec => "Vec",
            Self::Map => "Map",
            Self::U64 => "U64",
            Self::I64 => "I64",
            Self::U128 => "U128",
            Self::I128 => "I128",
            Self::Bytes => "Bytes",
            Self::ContractCode => "ContractCode",
            Self::AccountId => "AccountId",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScObjectType; 9] {
        Self::VARIANTS
    }
}

impl Name for ScObjectType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScObjectType> for ScObjectType {
    fn variants() -> slice::Iter<'static, ScObjectType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScObjectType {}

impl fmt::Display for ScObjectType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScObjectType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScObjectType::Vec,
            1 => ScObjectType::Map,
            2 => ScObjectType::U64,
            3 => ScObjectType::I64,
            4 => ScObjectType::U128,
            5 => ScObjectType::I128,
            6 => ScObjectType::Bytes,
            7 => ScObjectType::ContractCode,
            8 => ScObjectType::AccountId,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScObjectType> for i32 {
    #[must_use]
    fn from(e: ScObjectType) -> Self {
        e as Self
    }
}

impl ReadXdr for ScObjectType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScObjectType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScMapEntry is an XDR Struct defines as:
//
//   struct SCMapEntry
//    {
//        SCVal key;
//        SCVal val;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScMapEntry {
    pub key: ScVal,
    pub val: ScVal,
}

impl ReadXdr for ScMapEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            key: ScVal::read_xdr(r)?,
            val: ScVal::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScMapEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.key.write_xdr(w)?;
        self.val.write_xdr(w)?;
        Ok(())
    }
}

// ScvalLimit is an XDR Const defines as:
//
//   const SCVAL_LIMIT = 256000;
//
pub const SCVAL_LIMIT: u64 = 256000;

// ScVec is an XDR Typedef defines as:
//
//   typedef SCVal SCVec<SCVAL_LIMIT>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScVec(pub VecM<ScVal, 256000>);

impl From<ScVec> for VecM<ScVal, 256000> {
    #[must_use]
    fn from(x: ScVec) -> Self {
        x.0
    }
}

impl From<VecM<ScVal, 256000>> for ScVec {
    #[must_use]
    fn from(x: VecM<ScVal, 256000>) -> Self {
        ScVec(x)
    }
}

impl AsRef<VecM<ScVal, 256000>> for ScVec {
    #[must_use]
    fn as_ref(&self) -> &VecM<ScVal, 256000> {
        &self.0
    }
}

impl ReadXdr for ScVec {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = VecM::<ScVal, 256000>::read_xdr(r)?;
        let v = ScVec(i);
        Ok(v)
    }
}

impl WriteXdr for ScVec {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for ScVec {
    type Target = VecM<ScVal, 256000>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<ScVec> for Vec<ScVal> {
    #[must_use]
    fn from(x: ScVec) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<ScVal>> for ScVec {
    type Error = Error;
    fn try_from(x: Vec<ScVal>) -> Result<Self> {
        Ok(ScVec(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<ScVal>> for ScVec {
    type Error = Error;
    fn try_from(x: &Vec<ScVal>) -> Result<Self> {
        Ok(ScVec(x.try_into()?))
    }
}

impl AsRef<Vec<ScVal>> for ScVec {
    #[must_use]
    fn as_ref(&self) -> &Vec<ScVal> {
        &self.0 .0
    }
}

impl AsRef<[ScVal]> for ScVec {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[ScVal] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[ScVal] {
        self.0 .0
    }
}

// ScMap is an XDR Typedef defines as:
//
//   typedef SCMapEntry SCMap<SCVAL_LIMIT>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScMap(pub VecM<ScMapEntry, 256000>);

impl From<ScMap> for VecM<ScMapEntry, 256000> {
    #[must_use]
    fn from(x: ScMap) -> Self {
        x.0
    }
}

impl From<VecM<ScMapEntry, 256000>> for ScMap {
    #[must_use]
    fn from(x: VecM<ScMapEntry, 256000>) -> Self {
        ScMap(x)
    }
}

impl AsRef<VecM<ScMapEntry, 256000>> for ScMap {
    #[must_use]
    fn as_ref(&self) -> &VecM<ScMapEntry, 256000> {
        &self.0
    }
}

impl ReadXdr for ScMap {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = VecM::<ScMapEntry, 256000>::read_xdr(r)?;
        let v = ScMap(i);
        Ok(v)
    }
}

impl WriteXdr for ScMap {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for ScMap {
    type Target = VecM<ScMapEntry, 256000>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<ScMap> for Vec<ScMapEntry> {
    #[must_use]
    fn from(x: ScMap) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<ScMapEntry>> for ScMap {
    type Error = Error;
    fn try_from(x: Vec<ScMapEntry>) -> Result<Self> {
        Ok(ScMap(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<ScMapEntry>> for ScMap {
    type Error = Error;
    fn try_from(x: &Vec<ScMapEntry>) -> Result<Self> {
        Ok(ScMap(x.try_into()?))
    }
}

impl AsRef<Vec<ScMapEntry>> for ScMap {
    #[must_use]
    fn as_ref(&self) -> &Vec<ScMapEntry> {
        &self.0 .0
    }
}

impl AsRef<[ScMapEntry]> for ScMap {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[ScMapEntry] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[ScMapEntry] {
        self.0 .0
    }
}

// ScContractCodeType is an XDR Enum defines as:
//
//   enum SCContractCodeType
//    {
//        SCCONTRACT_CODE_WASM_REF = 0,
//        SCCONTRACT_CODE_TOKEN = 1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ScContractCodeType {
    WasmRef = 0,
    Token = 1,
}

impl ScContractCodeType {
    pub const VARIANTS: [ScContractCodeType; 2] =
        [ScContractCodeType::WasmRef, ScContractCodeType::Token];
    pub const VARIANTS_STR: [&'static str; 2] = ["WasmRef", "Token"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::WasmRef => "WasmRef",
            Self::Token => "Token",
        }
    }

    #[must_use]
    pub const fn variants() -> [ScContractCodeType; 2] {
        Self::VARIANTS
    }
}

impl Name for ScContractCodeType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ScContractCodeType> for ScContractCodeType {
    fn variants() -> slice::Iter<'static, ScContractCodeType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ScContractCodeType {}

impl fmt::Display for ScContractCodeType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ScContractCodeType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ScContractCodeType::WasmRef,
            1 => ScContractCodeType::Token,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ScContractCodeType> for i32 {
    #[must_use]
    fn from(e: ScContractCodeType) -> Self {
        e as Self
    }
}

impl ReadXdr for ScContractCodeType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ScContractCodeType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ScContractCode is an XDR Union defines as:
//
//   union SCContractCode switch (SCContractCodeType type)
//    {
//    case SCCONTRACT_CODE_WASM_REF:
//        Hash wasm_id;
//    case SCCONTRACT_CODE_TOKEN:
//        void;
//    };
//
// union with discriminant ScContractCodeType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ScContractCode {
    WasmRef(Hash),
    Token,
}

impl ScContractCode {
    pub const VARIANTS: [ScContractCodeType; 2] =
        [ScContractCodeType::WasmRef, ScContractCodeType::Token];
    pub const VARIANTS_STR: [&'static str; 2] = ["WasmRef", "Token"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::WasmRef(_) => "WasmRef",
            Self::Token => "Token",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ScContractCodeType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::WasmRef(_) => ScContractCodeType::WasmRef,
            Self::Token => ScContractCodeType::Token,
        }
    }

    #[must_use]
    pub const fn variants() -> [ScContractCodeType; 2] {
        Self::VARIANTS
    }
}

impl Name for ScContractCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ScContractCodeType> for ScContractCode {
    #[must_use]
    fn discriminant(&self) -> ScContractCodeType {
        Self::discriminant(self)
    }
}

impl Variants<ScContractCodeType> for ScContractCode {
    fn variants() -> slice::Iter<'static, ScContractCodeType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ScContractCodeType> for ScContractCode {}

impl ReadXdr for ScContractCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ScContractCodeType = <ScContractCodeType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ScContractCodeType::WasmRef => Self::WasmRef(Hash::read_xdr(r)?),
            ScContractCodeType::Token => Self::Token,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ScContractCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::WasmRef(v) => v.write_xdr(w)?,
            Self::Token => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// Int128Parts is an XDR Struct defines as:
//
//   struct Int128Parts {
//        // Both signed and unsigned 128-bit ints
//        // are transported in a pair of uint64s
//        // to reduce the risk of sign-extension.
//        uint64 lo;
//        uint64 hi;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Int128Parts {
    pub lo: u64,
    pub hi: u64,
}

impl ReadXdr for Int128Parts {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            lo: u64::read_xdr(r)?,
            hi: u64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Int128Parts {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.lo.write_xdr(w)?;
        self.hi.write_xdr(w)?;
        Ok(())
    }
}

// ScObject is an XDR Union defines as:
//
//   union SCObject switch (SCObjectType type)
//    {
//    case SCO_VEC:
//        SCVec vec;
//    case SCO_MAP:
//        SCMap map;
//    case SCO_U64:
//        uint64 u64;
//    case SCO_I64:
//        int64 i64;
//    case SCO_U128:
//        Int128Parts u128;
//    case SCO_I128:
//        Int128Parts i128;
//    case SCO_BYTES:
//        opaque bin<SCVAL_LIMIT>;
//    case SCO_CONTRACT_CODE:
//        SCContractCode contractCode;
//    case SCO_ACCOUNT_ID:
//        AccountID accountID;
//    };
//
// union with discriminant ScObjectType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ScObject {
    Vec(ScVec),
    Map(ScMap),
    U64(u64),
    I64(i64),
    U128(Int128Parts),
    I128(Int128Parts),
    Bytes(BytesM<256000>),
    ContractCode(ScContractCode),
    AccountId(AccountId),
}

impl ScObject {
    pub const VARIANTS: [ScObjectType; 9] = [
        ScObjectType::Vec,
        ScObjectType::Map,
        ScObjectType::U64,
        ScObjectType::I64,
        ScObjectType::U128,
        ScObjectType::I128,
        ScObjectType::Bytes,
        ScObjectType::ContractCode,
        ScObjectType::AccountId,
    ];
    pub const VARIANTS_STR: [&'static str; 9] = [
        "Vec",
        "Map",
        "U64",
        "I64",
        "U128",
        "I128",
        "Bytes",
        "ContractCode",
        "AccountId",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Vec(_) => "Vec",
            Self::Map(_) => "Map",
            Self::U64(_) => "U64",
            Self::I64(_) => "I64",
            Self::U128(_) => "U128",
            Self::I128(_) => "I128",
            Self::Bytes(_) => "Bytes",
            Self::ContractCode(_) => "ContractCode",
            Self::AccountId(_) => "AccountId",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ScObjectType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Vec(_) => ScObjectType::Vec,
            Self::Map(_) => ScObjectType::Map,
            Self::U64(_) => ScObjectType::U64,
            Self::I64(_) => ScObjectType::I64,
            Self::U128(_) => ScObjectType::U128,
            Self::I128(_) => ScObjectType::I128,
            Self::Bytes(_) => ScObjectType::Bytes,
            Self::ContractCode(_) => ScObjectType::ContractCode,
            Self::AccountId(_) => ScObjectType::AccountId,
        }
    }

    #[must_use]
    pub const fn variants() -> [ScObjectType; 9] {
        Self::VARIANTS
    }
}

impl Name for ScObject {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ScObjectType> for ScObject {
    #[must_use]
    fn discriminant(&self) -> ScObjectType {
        Self::discriminant(self)
    }
}

impl Variants<ScObjectType> for ScObject {
    fn variants() -> slice::Iter<'static, ScObjectType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ScObjectType> for ScObject {}

impl ReadXdr for ScObject {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ScObjectType = <ScObjectType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ScObjectType::Vec => Self::Vec(ScVec::read_xdr(r)?),
            ScObjectType::Map => Self::Map(ScMap::read_xdr(r)?),
            ScObjectType::U64 => Self::U64(u64::read_xdr(r)?),
            ScObjectType::I64 => Self::I64(i64::read_xdr(r)?),
            ScObjectType::U128 => Self::U128(Int128Parts::read_xdr(r)?),
            ScObjectType::I128 => Self::I128(Int128Parts::read_xdr(r)?),
            ScObjectType::Bytes => Self::Bytes(BytesM::<256000>::read_xdr(r)?),
            ScObjectType::ContractCode => Self::ContractCode(ScContractCode::read_xdr(r)?),
            ScObjectType::AccountId => Self::AccountId(AccountId::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ScObject {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Vec(v) => v.write_xdr(w)?,
            Self::Map(v) => v.write_xdr(w)?,
            Self::U64(v) => v.write_xdr(w)?,
            Self::I64(v) => v.write_xdr(w)?,
            Self::U128(v) => v.write_xdr(w)?,
            Self::I128(v) => v.write_xdr(w)?,
            Self::Bytes(v) => v.write_xdr(w)?,
            Self::ContractCode(v) => v.write_xdr(w)?,
            Self::AccountId(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// StoredTransactionSet is an XDR Union defines as:
//
//   union StoredTransactionSet switch (int v)
//    {
//    case 0:
//    	TransactionSet txSet;
//    case 1:
//    	GeneralizedTransactionSet generalizedTxSet;
//    };
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum StoredTransactionSet {
    V0(TransactionSet),
    V1(GeneralizedTransactionSet),
}

impl StoredTransactionSet {
    pub const VARIANTS: [i32; 2] = [0, 1];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V1"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0(_) => "V0",
            Self::V1(_) => "V1",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(_) => 0,
            Self::V1(_) => 1,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for StoredTransactionSet {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for StoredTransactionSet {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for StoredTransactionSet {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for StoredTransactionSet {}

impl ReadXdr for StoredTransactionSet {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0(TransactionSet::read_xdr(r)?),
            1 => Self::V1(GeneralizedTransactionSet::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for StoredTransactionSet {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(v) => v.write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// PersistedScpStateV0 is an XDR Struct defines as:
//
//   struct PersistedSCPStateV0
//    {
//    	SCPEnvelope scpEnvelopes<>;
//    	SCPQuorumSet quorumSets<>;
//    	StoredTransactionSet txSets<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PersistedScpStateV0 {
    pub scp_envelopes: VecM<ScpEnvelope>,
    pub quorum_sets: VecM<ScpQuorumSet>,
    pub tx_sets: VecM<StoredTransactionSet>,
}

impl ReadXdr for PersistedScpStateV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            scp_envelopes: VecM::<ScpEnvelope>::read_xdr(r)?,
            quorum_sets: VecM::<ScpQuorumSet>::read_xdr(r)?,
            tx_sets: VecM::<StoredTransactionSet>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PersistedScpStateV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.scp_envelopes.write_xdr(w)?;
        self.quorum_sets.write_xdr(w)?;
        self.tx_sets.write_xdr(w)?;
        Ok(())
    }
}

// PersistedScpStateV1 is an XDR Struct defines as:
//
//   struct PersistedSCPStateV1
//    {
//    	// Tx sets are saved separately
//    	SCPEnvelope scpEnvelopes<>;
//    	SCPQuorumSet quorumSets<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PersistedScpStateV1 {
    pub scp_envelopes: VecM<ScpEnvelope>,
    pub quorum_sets: VecM<ScpQuorumSet>,
}

impl ReadXdr for PersistedScpStateV1 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            scp_envelopes: VecM::<ScpEnvelope>::read_xdr(r)?,
            quorum_sets: VecM::<ScpQuorumSet>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PersistedScpStateV1 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.scp_envelopes.write_xdr(w)?;
        self.quorum_sets.write_xdr(w)?;
        Ok(())
    }
}

// PersistedScpState is an XDR Union defines as:
//
//   union PersistedSCPState switch (int v)
//    {
//    case 0:
//    	PersistedSCPStateV0 v0;
//    case 1:
//    	PersistedSCPStateV1 v1;
//    };
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum PersistedScpState {
    V0(PersistedScpStateV0),
    V1(PersistedScpStateV1),
}

impl PersistedScpState {
    pub const VARIANTS: [i32; 2] = [0, 1];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V1"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0(_) => "V0",
            Self::V1(_) => "V1",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(_) => 0,
            Self::V1(_) => 1,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for PersistedScpState {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for PersistedScpState {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for PersistedScpState {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for PersistedScpState {}

impl ReadXdr for PersistedScpState {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0(PersistedScpStateV0::read_xdr(r)?),
            1 => Self::V1(PersistedScpStateV1::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for PersistedScpState {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(v) => v.write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// Thresholds is an XDR Typedef defines as:
//
//   typedef opaque Thresholds[4];
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
)]
pub struct Thresholds(pub [u8; 4]);

impl core::fmt::Display for Thresholds {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        Ok(())
    }
}

impl core::fmt::Debug for Thresholds {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        write!(f, "Thresholds(")?;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        write!(f, ")")?;
        Ok(())
    }
}

#[cfg(feature = "alloc")]
impl core::str::FromStr for Thresholds {
    type Err = Error;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        hex::decode(s).map_err(|_| Error::InvalidHex)?.try_into()
    }
}
impl From<Thresholds> for [u8; 4] {
    #[must_use]
    fn from(x: Thresholds) -> Self {
        x.0
    }
}

impl From<[u8; 4]> for Thresholds {
    #[must_use]
    fn from(x: [u8; 4]) -> Self {
        Thresholds(x)
    }
}

impl AsRef<[u8; 4]> for Thresholds {
    #[must_use]
    fn as_ref(&self) -> &[u8; 4] {
        &self.0
    }
}

impl ReadXdr for Thresholds {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = <[u8; 4]>::read_xdr(r)?;
        let v = Thresholds(i);
        Ok(v)
    }
}

impl WriteXdr for Thresholds {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Thresholds {
    #[must_use]
    pub fn as_slice(&self) -> &[u8] {
        &self.0
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<Vec<u8>> for Thresholds {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for Thresholds {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

impl TryFrom<&[u8]> for Thresholds {
    type Error = Error;
    fn try_from(x: &[u8]) -> Result<Self> {
        Ok(Thresholds(x.try_into()?))
    }
}

impl AsRef<[u8]> for Thresholds {
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

// String32 is an XDR Typedef defines as:
//
//   typedef string string32<32>;
//
pub type String32 = StringM<32>;

// String64 is an XDR Typedef defines as:
//
//   typedef string string64<64>;
//
pub type String64 = StringM<64>;

// SequenceNumber is an XDR Typedef defines as:
//
//   typedef int64 SequenceNumber;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SequenceNumber(pub i64);

impl From<SequenceNumber> for i64 {
    #[must_use]
    fn from(x: SequenceNumber) -> Self {
        x.0
    }
}

impl From<i64> for SequenceNumber {
    #[must_use]
    fn from(x: i64) -> Self {
        SequenceNumber(x)
    }
}

impl AsRef<i64> for SequenceNumber {
    #[must_use]
    fn as_ref(&self) -> &i64 {
        &self.0
    }
}

impl ReadXdr for SequenceNumber {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = i64::read_xdr(r)?;
        let v = SequenceNumber(i);
        Ok(v)
    }
}

impl WriteXdr for SequenceNumber {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

// TimePoint is an XDR Typedef defines as:
//
//   typedef uint64 TimePoint;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TimePoint(pub u64);

impl From<TimePoint> for u64 {
    #[must_use]
    fn from(x: TimePoint) -> Self {
        x.0
    }
}

impl From<u64> for TimePoint {
    #[must_use]
    fn from(x: u64) -> Self {
        TimePoint(x)
    }
}

impl AsRef<u64> for TimePoint {
    #[must_use]
    fn as_ref(&self) -> &u64 {
        &self.0
    }
}

impl ReadXdr for TimePoint {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = u64::read_xdr(r)?;
        let v = TimePoint(i);
        Ok(v)
    }
}

impl WriteXdr for TimePoint {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

// Duration is an XDR Typedef defines as:
//
//   typedef uint64 Duration;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Duration(pub u64);

impl From<Duration> for u64 {
    #[must_use]
    fn from(x: Duration) -> Self {
        x.0
    }
}

impl From<u64> for Duration {
    #[must_use]
    fn from(x: u64) -> Self {
        Duration(x)
    }
}

impl AsRef<u64> for Duration {
    #[must_use]
    fn as_ref(&self) -> &u64 {
        &self.0
    }
}

impl ReadXdr for Duration {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = u64::read_xdr(r)?;
        let v = Duration(i);
        Ok(v)
    }
}

impl WriteXdr for Duration {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

// DataValue is an XDR Typedef defines as:
//
//   typedef opaque DataValue<64>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct DataValue(pub BytesM<64>);

impl From<DataValue> for BytesM<64> {
    #[must_use]
    fn from(x: DataValue) -> Self {
        x.0
    }
}

impl From<BytesM<64>> for DataValue {
    #[must_use]
    fn from(x: BytesM<64>) -> Self {
        DataValue(x)
    }
}

impl AsRef<BytesM<64>> for DataValue {
    #[must_use]
    fn as_ref(&self) -> &BytesM<64> {
        &self.0
    }
}

impl ReadXdr for DataValue {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = BytesM::<64>::read_xdr(r)?;
        let v = DataValue(i);
        Ok(v)
    }
}

impl WriteXdr for DataValue {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for DataValue {
    type Target = BytesM<64>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<DataValue> for Vec<u8> {
    #[must_use]
    fn from(x: DataValue) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<u8>> for DataValue {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        Ok(DataValue(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for DataValue {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        Ok(DataValue(x.try_into()?))
    }
}

impl AsRef<Vec<u8>> for DataValue {
    #[must_use]
    fn as_ref(&self) -> &Vec<u8> {
        &self.0 .0
    }
}

impl AsRef<[u8]> for DataValue {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        self.0 .0
    }
}

// PoolId is an XDR Typedef defines as:
//
//   typedef Hash PoolID;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PoolId(pub Hash);

impl From<PoolId> for Hash {
    #[must_use]
    fn from(x: PoolId) -> Self {
        x.0
    }
}

impl From<Hash> for PoolId {
    #[must_use]
    fn from(x: Hash) -> Self {
        PoolId(x)
    }
}

impl AsRef<Hash> for PoolId {
    #[must_use]
    fn as_ref(&self) -> &Hash {
        &self.0
    }
}

impl ReadXdr for PoolId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = Hash::read_xdr(r)?;
        let v = PoolId(i);
        Ok(v)
    }
}

impl WriteXdr for PoolId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

// AssetCode4 is an XDR Typedef defines as:
//
//   typedef opaque AssetCode4[4];
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
)]
pub struct AssetCode4(pub [u8; 4]);

impl core::fmt::Display for AssetCode4 {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        Ok(())
    }
}

impl core::fmt::Debug for AssetCode4 {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        write!(f, "AssetCode4(")?;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        write!(f, ")")?;
        Ok(())
    }
}

#[cfg(feature = "alloc")]
impl core::str::FromStr for AssetCode4 {
    type Err = Error;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        hex::decode(s).map_err(|_| Error::InvalidHex)?.try_into()
    }
}
impl From<AssetCode4> for [u8; 4] {
    #[must_use]
    fn from(x: AssetCode4) -> Self {
        x.0
    }
}

impl From<[u8; 4]> for AssetCode4 {
    #[must_use]
    fn from(x: [u8; 4]) -> Self {
        AssetCode4(x)
    }
}

impl AsRef<[u8; 4]> for AssetCode4 {
    #[must_use]
    fn as_ref(&self) -> &[u8; 4] {
        &self.0
    }
}

impl ReadXdr for AssetCode4 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = <[u8; 4]>::read_xdr(r)?;
        let v = AssetCode4(i);
        Ok(v)
    }
}

impl WriteXdr for AssetCode4 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl AssetCode4 {
    #[must_use]
    pub fn as_slice(&self) -> &[u8] {
        &self.0
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<Vec<u8>> for AssetCode4 {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for AssetCode4 {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

impl TryFrom<&[u8]> for AssetCode4 {
    type Error = Error;
    fn try_from(x: &[u8]) -> Result<Self> {
        Ok(AssetCode4(x.try_into()?))
    }
}

impl AsRef<[u8]> for AssetCode4 {
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

// AssetCode12 is an XDR Typedef defines as:
//
//   typedef opaque AssetCode12[12];
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
)]
pub struct AssetCode12(pub [u8; 12]);

impl core::fmt::Display for AssetCode12 {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        Ok(())
    }
}

impl core::fmt::Debug for AssetCode12 {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        write!(f, "AssetCode12(")?;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        write!(f, ")")?;
        Ok(())
    }
}

#[cfg(feature = "alloc")]
impl core::str::FromStr for AssetCode12 {
    type Err = Error;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        hex::decode(s).map_err(|_| Error::InvalidHex)?.try_into()
    }
}
impl From<AssetCode12> for [u8; 12] {
    #[must_use]
    fn from(x: AssetCode12) -> Self {
        x.0
    }
}

impl From<[u8; 12]> for AssetCode12 {
    #[must_use]
    fn from(x: [u8; 12]) -> Self {
        AssetCode12(x)
    }
}

impl AsRef<[u8; 12]> for AssetCode12 {
    #[must_use]
    fn as_ref(&self) -> &[u8; 12] {
        &self.0
    }
}

impl ReadXdr for AssetCode12 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = <[u8; 12]>::read_xdr(r)?;
        let v = AssetCode12(i);
        Ok(v)
    }
}

impl WriteXdr for AssetCode12 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl AssetCode12 {
    #[must_use]
    pub fn as_slice(&self) -> &[u8] {
        &self.0
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<Vec<u8>> for AssetCode12 {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for AssetCode12 {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

impl TryFrom<&[u8]> for AssetCode12 {
    type Error = Error;
    fn try_from(x: &[u8]) -> Result<Self> {
        Ok(AssetCode12(x.try_into()?))
    }
}

impl AsRef<[u8]> for AssetCode12 {
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

// AssetType is an XDR Enum defines as:
//
//   enum AssetType
//    {
//        ASSET_TYPE_NATIVE = 0,
//        ASSET_TYPE_CREDIT_ALPHANUM4 = 1,
//        ASSET_TYPE_CREDIT_ALPHANUM12 = 2,
//        ASSET_TYPE_POOL_SHARE = 3
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum AssetType {
    Native = 0,
    CreditAlphanum4 = 1,
    CreditAlphanum12 = 2,
    PoolShare = 3,
}

impl AssetType {
    pub const VARIANTS: [AssetType; 4] = [
        AssetType::Native,
        AssetType::CreditAlphanum4,
        AssetType::CreditAlphanum12,
        AssetType::PoolShare,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Native", "CreditAlphanum4", "CreditAlphanum12", "PoolShare"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Native => "Native",
            Self::CreditAlphanum4 => "CreditAlphanum4",
            Self::CreditAlphanum12 => "CreditAlphanum12",
            Self::PoolShare => "PoolShare",
        }
    }

    #[must_use]
    pub const fn variants() -> [AssetType; 4] {
        Self::VARIANTS
    }
}

impl Name for AssetType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<AssetType> for AssetType {
    fn variants() -> slice::Iter<'static, AssetType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for AssetType {}

impl fmt::Display for AssetType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for AssetType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => AssetType::Native,
            1 => AssetType::CreditAlphanum4,
            2 => AssetType::CreditAlphanum12,
            3 => AssetType::PoolShare,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<AssetType> for i32 {
    #[must_use]
    fn from(e: AssetType) -> Self {
        e as Self
    }
}

impl ReadXdr for AssetType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for AssetType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// AssetCode is an XDR Union defines as:
//
//   union AssetCode switch (AssetType type)
//    {
//    case ASSET_TYPE_CREDIT_ALPHANUM4:
//        AssetCode4 assetCode4;
//
//    case ASSET_TYPE_CREDIT_ALPHANUM12:
//        AssetCode12 assetCode12;
//
//        // add other asset types here in the future
//    };
//
// union with discriminant AssetType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum AssetCode {
    CreditAlphanum4(AssetCode4),
    CreditAlphanum12(AssetCode12),
}

impl AssetCode {
    pub const VARIANTS: [AssetType; 2] = [AssetType::CreditAlphanum4, AssetType::CreditAlphanum12];
    pub const VARIANTS_STR: [&'static str; 2] = ["CreditAlphanum4", "CreditAlphanum12"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::CreditAlphanum4(_) => "CreditAlphanum4",
            Self::CreditAlphanum12(_) => "CreditAlphanum12",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> AssetType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::CreditAlphanum4(_) => AssetType::CreditAlphanum4,
            Self::CreditAlphanum12(_) => AssetType::CreditAlphanum12,
        }
    }

    #[must_use]
    pub const fn variants() -> [AssetType; 2] {
        Self::VARIANTS
    }
}

impl Name for AssetCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<AssetType> for AssetCode {
    #[must_use]
    fn discriminant(&self) -> AssetType {
        Self::discriminant(self)
    }
}

impl Variants<AssetType> for AssetCode {
    fn variants() -> slice::Iter<'static, AssetType> {
        Self::VARIANTS.iter()
    }
}

impl Union<AssetType> for AssetCode {}

impl ReadXdr for AssetCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: AssetType = <AssetType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            AssetType::CreditAlphanum4 => Self::CreditAlphanum4(AssetCode4::read_xdr(r)?),
            AssetType::CreditAlphanum12 => Self::CreditAlphanum12(AssetCode12::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for AssetCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::CreditAlphanum4(v) => v.write_xdr(w)?,
            Self::CreditAlphanum12(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// AlphaNum4 is an XDR Struct defines as:
//
//   struct AlphaNum4
//    {
//        AssetCode4 assetCode;
//        AccountID issuer;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AlphaNum4 {
    pub asset_code: AssetCode4,
    pub issuer: AccountId,
}

impl ReadXdr for AlphaNum4 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            asset_code: AssetCode4::read_xdr(r)?,
            issuer: AccountId::read_xdr(r)?,
        })
    }
}

impl WriteXdr for AlphaNum4 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.asset_code.write_xdr(w)?;
        self.issuer.write_xdr(w)?;
        Ok(())
    }
}

// AlphaNum12 is an XDR Struct defines as:
//
//   struct AlphaNum12
//    {
//        AssetCode12 assetCode;
//        AccountID issuer;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AlphaNum12 {
    pub asset_code: AssetCode12,
    pub issuer: AccountId,
}

impl ReadXdr for AlphaNum12 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            asset_code: AssetCode12::read_xdr(r)?,
            issuer: AccountId::read_xdr(r)?,
        })
    }
}

impl WriteXdr for AlphaNum12 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.asset_code.write_xdr(w)?;
        self.issuer.write_xdr(w)?;
        Ok(())
    }
}

// Asset is an XDR Union defines as:
//
//   union Asset switch (AssetType type)
//    {
//    case ASSET_TYPE_NATIVE: // Not credit
//        void;
//
//    case ASSET_TYPE_CREDIT_ALPHANUM4:
//        AlphaNum4 alphaNum4;
//
//    case ASSET_TYPE_CREDIT_ALPHANUM12:
//        AlphaNum12 alphaNum12;
//
//        // add other asset types here in the future
//    };
//
// union with discriminant AssetType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum Asset {
    Native,
    CreditAlphanum4(AlphaNum4),
    CreditAlphanum12(AlphaNum12),
}

impl Asset {
    pub const VARIANTS: [AssetType; 3] = [
        AssetType::Native,
        AssetType::CreditAlphanum4,
        AssetType::CreditAlphanum12,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["Native", "CreditAlphanum4", "CreditAlphanum12"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Native => "Native",
            Self::CreditAlphanum4(_) => "CreditAlphanum4",
            Self::CreditAlphanum12(_) => "CreditAlphanum12",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> AssetType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Native => AssetType::Native,
            Self::CreditAlphanum4(_) => AssetType::CreditAlphanum4,
            Self::CreditAlphanum12(_) => AssetType::CreditAlphanum12,
        }
    }

    #[must_use]
    pub const fn variants() -> [AssetType; 3] {
        Self::VARIANTS
    }
}

impl Name for Asset {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<AssetType> for Asset {
    #[must_use]
    fn discriminant(&self) -> AssetType {
        Self::discriminant(self)
    }
}

impl Variants<AssetType> for Asset {
    fn variants() -> slice::Iter<'static, AssetType> {
        Self::VARIANTS.iter()
    }
}

impl Union<AssetType> for Asset {}

impl ReadXdr for Asset {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: AssetType = <AssetType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            AssetType::Native => Self::Native,
            AssetType::CreditAlphanum4 => Self::CreditAlphanum4(AlphaNum4::read_xdr(r)?),
            AssetType::CreditAlphanum12 => Self::CreditAlphanum12(AlphaNum12::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for Asset {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Native => ().write_xdr(w)?,
            Self::CreditAlphanum4(v) => v.write_xdr(w)?,
            Self::CreditAlphanum12(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// Price is an XDR Struct defines as:
//
//   struct Price
//    {
//        int32 n; // numerator
//        int32 d; // denominator
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Price {
    pub n: i32,
    pub d: i32,
}

impl ReadXdr for Price {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            n: i32::read_xdr(r)?,
            d: i32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Price {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.n.write_xdr(w)?;
        self.d.write_xdr(w)?;
        Ok(())
    }
}

// Liabilities is an XDR Struct defines as:
//
//   struct Liabilities
//    {
//        int64 buying;
//        int64 selling;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Liabilities {
    pub buying: i64,
    pub selling: i64,
}

impl ReadXdr for Liabilities {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            buying: i64::read_xdr(r)?,
            selling: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Liabilities {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.buying.write_xdr(w)?;
        self.selling.write_xdr(w)?;
        Ok(())
    }
}

// ThresholdIndexes is an XDR Enum defines as:
//
//   enum ThresholdIndexes
//    {
//        THRESHOLD_MASTER_WEIGHT = 0,
//        THRESHOLD_LOW = 1,
//        THRESHOLD_MED = 2,
//        THRESHOLD_HIGH = 3
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ThresholdIndexes {
    MasterWeight = 0,
    Low = 1,
    Med = 2,
    High = 3,
}

impl ThresholdIndexes {
    pub const VARIANTS: [ThresholdIndexes; 4] = [
        ThresholdIndexes::MasterWeight,
        ThresholdIndexes::Low,
        ThresholdIndexes::Med,
        ThresholdIndexes::High,
    ];
    pub const VARIANTS_STR: [&'static str; 4] = ["MasterWeight", "Low", "Med", "High"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::MasterWeight => "MasterWeight",
            Self::Low => "Low",
            Self::Med => "Med",
            Self::High => "High",
        }
    }

    #[must_use]
    pub const fn variants() -> [ThresholdIndexes; 4] {
        Self::VARIANTS
    }
}

impl Name for ThresholdIndexes {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ThresholdIndexes> for ThresholdIndexes {
    fn variants() -> slice::Iter<'static, ThresholdIndexes> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ThresholdIndexes {}

impl fmt::Display for ThresholdIndexes {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ThresholdIndexes {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ThresholdIndexes::MasterWeight,
            1 => ThresholdIndexes::Low,
            2 => ThresholdIndexes::Med,
            3 => ThresholdIndexes::High,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ThresholdIndexes> for i32 {
    #[must_use]
    fn from(e: ThresholdIndexes) -> Self {
        e as Self
    }
}

impl ReadXdr for ThresholdIndexes {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ThresholdIndexes {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// LedgerEntryType is an XDR Enum defines as:
//
//   enum LedgerEntryType
//    {
//        ACCOUNT = 0,
//        TRUSTLINE = 1,
//        OFFER = 2,
//        DATA = 3,
//        CLAIMABLE_BALANCE = 4,
//        LIQUIDITY_POOL = 5,
//        CONTRACT_DATA = 6,
//        CONTRACT_CODE = 7,
//        CONFIG_SETTING = 8
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum LedgerEntryType {
    Account = 0,
    Trustline = 1,
    Offer = 2,
    Data = 3,
    ClaimableBalance = 4,
    LiquidityPool = 5,
    ContractData = 6,
    ContractCode = 7,
    ConfigSetting = 8,
}

impl LedgerEntryType {
    pub const VARIANTS: [LedgerEntryType; 9] = [
        LedgerEntryType::Account,
        LedgerEntryType::Trustline,
        LedgerEntryType::Offer,
        LedgerEntryType::Data,
        LedgerEntryType::ClaimableBalance,
        LedgerEntryType::LiquidityPool,
        LedgerEntryType::ContractData,
        LedgerEntryType::ContractCode,
        LedgerEntryType::ConfigSetting,
    ];
    pub const VARIANTS_STR: [&'static str; 9] = [
        "Account",
        "Trustline",
        "Offer",
        "Data",
        "ClaimableBalance",
        "LiquidityPool",
        "ContractData",
        "ContractCode",
        "ConfigSetting",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Account => "Account",
            Self::Trustline => "Trustline",
            Self::Offer => "Offer",
            Self::Data => "Data",
            Self::ClaimableBalance => "ClaimableBalance",
            Self::LiquidityPool => "LiquidityPool",
            Self::ContractData => "ContractData",
            Self::ContractCode => "ContractCode",
            Self::ConfigSetting => "ConfigSetting",
        }
    }

    #[must_use]
    pub const fn variants() -> [LedgerEntryType; 9] {
        Self::VARIANTS
    }
}

impl Name for LedgerEntryType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<LedgerEntryType> for LedgerEntryType {
    fn variants() -> slice::Iter<'static, LedgerEntryType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for LedgerEntryType {}

impl fmt::Display for LedgerEntryType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for LedgerEntryType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => LedgerEntryType::Account,
            1 => LedgerEntryType::Trustline,
            2 => LedgerEntryType::Offer,
            3 => LedgerEntryType::Data,
            4 => LedgerEntryType::ClaimableBalance,
            5 => LedgerEntryType::LiquidityPool,
            6 => LedgerEntryType::ContractData,
            7 => LedgerEntryType::ContractCode,
            8 => LedgerEntryType::ConfigSetting,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<LedgerEntryType> for i32 {
    #[must_use]
    fn from(e: LedgerEntryType) -> Self {
        e as Self
    }
}

impl ReadXdr for LedgerEntryType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for LedgerEntryType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// Signer is an XDR Struct defines as:
//
//   struct Signer
//    {
//        SignerKey key;
//        uint32 weight; // really only need 1 byte
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Signer {
    pub key: SignerKey,
    pub weight: u32,
}

impl ReadXdr for Signer {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            key: SignerKey::read_xdr(r)?,
            weight: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Signer {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.key.write_xdr(w)?;
        self.weight.write_xdr(w)?;
        Ok(())
    }
}

// AccountFlags is an XDR Enum defines as:
//
//   enum AccountFlags
//    { // masks for each flag
//
//        // Flags set on issuer accounts
//        // TrustLines are created with authorized set to "false" requiring
//        // the issuer to set it for each TrustLine
//        AUTH_REQUIRED_FLAG = 0x1,
//        // If set, the authorized flag in TrustLines can be cleared
//        // otherwise, authorization cannot be revoked
//        AUTH_REVOCABLE_FLAG = 0x2,
//        // Once set, causes all AUTH_* flags to be read-only
//        AUTH_IMMUTABLE_FLAG = 0x4,
//        // Trustlines are created with clawback enabled set to "true",
//        // and claimable balances created from those trustlines are created
//        // with clawback enabled set to "true"
//        AUTH_CLAWBACK_ENABLED_FLAG = 0x8
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum AccountFlags {
    RequiredFlag = 1,
    RevocableFlag = 2,
    ImmutableFlag = 4,
    ClawbackEnabledFlag = 8,
}

impl AccountFlags {
    pub const VARIANTS: [AccountFlags; 4] = [
        AccountFlags::RequiredFlag,
        AccountFlags::RevocableFlag,
        AccountFlags::ImmutableFlag,
        AccountFlags::ClawbackEnabledFlag,
    ];
    pub const VARIANTS_STR: [&'static str; 4] = [
        "RequiredFlag",
        "RevocableFlag",
        "ImmutableFlag",
        "ClawbackEnabledFlag",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::RequiredFlag => "RequiredFlag",
            Self::RevocableFlag => "RevocableFlag",
            Self::ImmutableFlag => "ImmutableFlag",
            Self::ClawbackEnabledFlag => "ClawbackEnabledFlag",
        }
    }

    #[must_use]
    pub const fn variants() -> [AccountFlags; 4] {
        Self::VARIANTS
    }
}

impl Name for AccountFlags {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<AccountFlags> for AccountFlags {
    fn variants() -> slice::Iter<'static, AccountFlags> {
        Self::VARIANTS.iter()
    }
}

impl Enum for AccountFlags {}

impl fmt::Display for AccountFlags {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for AccountFlags {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            1 => AccountFlags::RequiredFlag,
            2 => AccountFlags::RevocableFlag,
            4 => AccountFlags::ImmutableFlag,
            8 => AccountFlags::ClawbackEnabledFlag,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<AccountFlags> for i32 {
    #[must_use]
    fn from(e: AccountFlags) -> Self {
        e as Self
    }
}

impl ReadXdr for AccountFlags {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for AccountFlags {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// MaskAccountFlags is an XDR Const defines as:
//
//   const MASK_ACCOUNT_FLAGS = 0x7;
//
pub const MASK_ACCOUNT_FLAGS: u64 = 0x7;

// MaskAccountFlagsV17 is an XDR Const defines as:
//
//   const MASK_ACCOUNT_FLAGS_V17 = 0xF;
//
pub const MASK_ACCOUNT_FLAGS_V17: u64 = 0xF;

// MaxSigners is an XDR Const defines as:
//
//   const MAX_SIGNERS = 20;
//
pub const MAX_SIGNERS: u64 = 20;

// SponsorshipDescriptor is an XDR Typedef defines as:
//
//   typedef AccountID* SponsorshipDescriptor;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SponsorshipDescriptor(pub Option<AccountId>);

impl From<SponsorshipDescriptor> for Option<AccountId> {
    #[must_use]
    fn from(x: SponsorshipDescriptor) -> Self {
        x.0
    }
}

impl From<Option<AccountId>> for SponsorshipDescriptor {
    #[must_use]
    fn from(x: Option<AccountId>) -> Self {
        SponsorshipDescriptor(x)
    }
}

impl AsRef<Option<AccountId>> for SponsorshipDescriptor {
    #[must_use]
    fn as_ref(&self) -> &Option<AccountId> {
        &self.0
    }
}

impl ReadXdr for SponsorshipDescriptor {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = Option::<AccountId>::read_xdr(r)?;
        let v = SponsorshipDescriptor(i);
        Ok(v)
    }
}

impl WriteXdr for SponsorshipDescriptor {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

// AccountEntryExtensionV3 is an XDR Struct defines as:
//
//   struct AccountEntryExtensionV3
//    {
//        // We can use this to add more fields, or because it is first, to
//        // change AccountEntryExtensionV3 into a union.
//        ExtensionPoint ext;
//
//        // Ledger number at which `seqNum` took on its present value.
//        uint32 seqLedger;
//
//        // Time at which `seqNum` took on its present value.
//        TimePoint seqTime;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AccountEntryExtensionV3 {
    pub ext: ExtensionPoint,
    pub seq_ledger: u32,
    pub seq_time: TimePoint,
}

impl ReadXdr for AccountEntryExtensionV3 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ext: ExtensionPoint::read_xdr(r)?,
            seq_ledger: u32::read_xdr(r)?,
            seq_time: TimePoint::read_xdr(r)?,
        })
    }
}

impl WriteXdr for AccountEntryExtensionV3 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ext.write_xdr(w)?;
        self.seq_ledger.write_xdr(w)?;
        self.seq_time.write_xdr(w)?;
        Ok(())
    }
}

// AccountEntryExtensionV2Ext is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        case 3:
//            AccountEntryExtensionV3 v3;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum AccountEntryExtensionV2Ext {
    V0,
    V3(AccountEntryExtensionV3),
}

impl AccountEntryExtensionV2Ext {
    pub const VARIANTS: [i32; 2] = [0, 3];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V3"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::V3(_) => "V3",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
            Self::V3(_) => 3,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for AccountEntryExtensionV2Ext {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for AccountEntryExtensionV2Ext {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for AccountEntryExtensionV2Ext {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for AccountEntryExtensionV2Ext {}

impl ReadXdr for AccountEntryExtensionV2Ext {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            3 => Self::V3(AccountEntryExtensionV3::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for AccountEntryExtensionV2Ext {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
            Self::V3(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// AccountEntryExtensionV2 is an XDR Struct defines as:
//
//   struct AccountEntryExtensionV2
//    {
//        uint32 numSponsored;
//        uint32 numSponsoring;
//        SponsorshipDescriptor signerSponsoringIDs<MAX_SIGNERS>;
//
//        union switch (int v)
//        {
//        case 0:
//            void;
//        case 3:
//            AccountEntryExtensionV3 v3;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AccountEntryExtensionV2 {
    pub num_sponsored: u32,
    pub num_sponsoring: u32,
    pub signer_sponsoring_i_ds: VecM<SponsorshipDescriptor, 20>,
    pub ext: AccountEntryExtensionV2Ext,
}

impl ReadXdr for AccountEntryExtensionV2 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            num_sponsored: u32::read_xdr(r)?,
            num_sponsoring: u32::read_xdr(r)?,
            signer_sponsoring_i_ds: VecM::<SponsorshipDescriptor, 20>::read_xdr(r)?,
            ext: AccountEntryExtensionV2Ext::read_xdr(r)?,
        })
    }
}

impl WriteXdr for AccountEntryExtensionV2 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.num_sponsored.write_xdr(w)?;
        self.num_sponsoring.write_xdr(w)?;
        self.signer_sponsoring_i_ds.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// AccountEntryExtensionV1Ext is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        case 2:
//            AccountEntryExtensionV2 v2;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum AccountEntryExtensionV1Ext {
    V0,
    V2(AccountEntryExtensionV2),
}

impl AccountEntryExtensionV1Ext {
    pub const VARIANTS: [i32; 2] = [0, 2];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V2"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::V2(_) => "V2",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
            Self::V2(_) => 2,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for AccountEntryExtensionV1Ext {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for AccountEntryExtensionV1Ext {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for AccountEntryExtensionV1Ext {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for AccountEntryExtensionV1Ext {}

impl ReadXdr for AccountEntryExtensionV1Ext {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            2 => Self::V2(AccountEntryExtensionV2::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for AccountEntryExtensionV1Ext {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
            Self::V2(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// AccountEntryExtensionV1 is an XDR Struct defines as:
//
//   struct AccountEntryExtensionV1
//    {
//        Liabilities liabilities;
//
//        union switch (int v)
//        {
//        case 0:
//            void;
//        case 2:
//            AccountEntryExtensionV2 v2;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AccountEntryExtensionV1 {
    pub liabilities: Liabilities,
    pub ext: AccountEntryExtensionV1Ext,
}

impl ReadXdr for AccountEntryExtensionV1 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            liabilities: Liabilities::read_xdr(r)?,
            ext: AccountEntryExtensionV1Ext::read_xdr(r)?,
        })
    }
}

impl WriteXdr for AccountEntryExtensionV1 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.liabilities.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// AccountEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            AccountEntryExtensionV1 v1;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum AccountEntryExt {
    V0,
    V1(AccountEntryExtensionV1),
}

impl AccountEntryExt {
    pub const VARIANTS: [i32; 2] = [0, 1];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V1"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::V1(_) => "V1",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
            Self::V1(_) => 1,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for AccountEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for AccountEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for AccountEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for AccountEntryExt {}

impl ReadXdr for AccountEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            1 => Self::V1(AccountEntryExtensionV1::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for AccountEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// AccountEntry is an XDR Struct defines as:
//
//   struct AccountEntry
//    {
//        AccountID accountID;      // master public key for this account
//        int64 balance;            // in stroops
//        SequenceNumber seqNum;    // last sequence number used for this account
//        uint32 numSubEntries;     // number of sub-entries this account has
//                                  // drives the reserve
//        AccountID* inflationDest; // Account to vote for during inflation
//        uint32 flags;             // see AccountFlags
//
//        string32 homeDomain; // can be used for reverse federation and memo lookup
//
//        // fields used for signatures
//        // thresholds stores unsigned bytes: [weight of master|low|medium|high]
//        Thresholds thresholds;
//
//        Signer signers<MAX_SIGNERS>; // possible signers for this account
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            AccountEntryExtensionV1 v1;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AccountEntry {
    pub account_id: AccountId,
    pub balance: i64,
    pub seq_num: SequenceNumber,
    pub num_sub_entries: u32,
    pub inflation_dest: Option<AccountId>,
    pub flags: u32,
    pub home_domain: StringM<32>,
    pub thresholds: Thresholds,
    pub signers: VecM<Signer, 20>,
    pub ext: AccountEntryExt,
}

impl ReadXdr for AccountEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            account_id: AccountId::read_xdr(r)?,
            balance: i64::read_xdr(r)?,
            seq_num: SequenceNumber::read_xdr(r)?,
            num_sub_entries: u32::read_xdr(r)?,
            inflation_dest: Option::<AccountId>::read_xdr(r)?,
            flags: u32::read_xdr(r)?,
            home_domain: StringM::<32>::read_xdr(r)?,
            thresholds: Thresholds::read_xdr(r)?,
            signers: VecM::<Signer, 20>::read_xdr(r)?,
            ext: AccountEntryExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for AccountEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.account_id.write_xdr(w)?;
        self.balance.write_xdr(w)?;
        self.seq_num.write_xdr(w)?;
        self.num_sub_entries.write_xdr(w)?;
        self.inflation_dest.write_xdr(w)?;
        self.flags.write_xdr(w)?;
        self.home_domain.write_xdr(w)?;
        self.thresholds.write_xdr(w)?;
        self.signers.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// TrustLineFlags is an XDR Enum defines as:
//
//   enum TrustLineFlags
//    {
//        // issuer has authorized account to perform transactions with its credit
//        AUTHORIZED_FLAG = 1,
//        // issuer has authorized account to maintain and reduce liabilities for its
//        // credit
//        AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG = 2,
//        // issuer has specified that it may clawback its credit, and that claimable
//        // balances created with its credit may also be clawed back
//        TRUSTLINE_CLAWBACK_ENABLED_FLAG = 4
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum TrustLineFlags {
    AuthorizedFlag = 1,
    AuthorizedToMaintainLiabilitiesFlag = 2,
    TrustlineClawbackEnabledFlag = 4,
}

impl TrustLineFlags {
    pub const VARIANTS: [TrustLineFlags; 3] = [
        TrustLineFlags::AuthorizedFlag,
        TrustLineFlags::AuthorizedToMaintainLiabilitiesFlag,
        TrustLineFlags::TrustlineClawbackEnabledFlag,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = [
        "AuthorizedFlag",
        "AuthorizedToMaintainLiabilitiesFlag",
        "TrustlineClawbackEnabledFlag",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::AuthorizedFlag => "AuthorizedFlag",
            Self::AuthorizedToMaintainLiabilitiesFlag => "AuthorizedToMaintainLiabilitiesFlag",
            Self::TrustlineClawbackEnabledFlag => "TrustlineClawbackEnabledFlag",
        }
    }

    #[must_use]
    pub const fn variants() -> [TrustLineFlags; 3] {
        Self::VARIANTS
    }
}

impl Name for TrustLineFlags {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<TrustLineFlags> for TrustLineFlags {
    fn variants() -> slice::Iter<'static, TrustLineFlags> {
        Self::VARIANTS.iter()
    }
}

impl Enum for TrustLineFlags {}

impl fmt::Display for TrustLineFlags {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for TrustLineFlags {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            1 => TrustLineFlags::AuthorizedFlag,
            2 => TrustLineFlags::AuthorizedToMaintainLiabilitiesFlag,
            4 => TrustLineFlags::TrustlineClawbackEnabledFlag,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<TrustLineFlags> for i32 {
    #[must_use]
    fn from(e: TrustLineFlags) -> Self {
        e as Self
    }
}

impl ReadXdr for TrustLineFlags {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for TrustLineFlags {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// MaskTrustlineFlags is an XDR Const defines as:
//
//   const MASK_TRUSTLINE_FLAGS = 1;
//
pub const MASK_TRUSTLINE_FLAGS: u64 = 1;

// MaskTrustlineFlagsV13 is an XDR Const defines as:
//
//   const MASK_TRUSTLINE_FLAGS_V13 = 3;
//
pub const MASK_TRUSTLINE_FLAGS_V13: u64 = 3;

// MaskTrustlineFlagsV17 is an XDR Const defines as:
//
//   const MASK_TRUSTLINE_FLAGS_V17 = 7;
//
pub const MASK_TRUSTLINE_FLAGS_V17: u64 = 7;

// LiquidityPoolType is an XDR Enum defines as:
//
//   enum LiquidityPoolType
//    {
//        LIQUIDITY_POOL_CONSTANT_PRODUCT = 0
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum LiquidityPoolType {
    LiquidityPoolConstantProduct = 0,
}

impl LiquidityPoolType {
    pub const VARIANTS: [LiquidityPoolType; 1] = [LiquidityPoolType::LiquidityPoolConstantProduct];
    pub const VARIANTS_STR: [&'static str; 1] = ["LiquidityPoolConstantProduct"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::LiquidityPoolConstantProduct => "LiquidityPoolConstantProduct",
        }
    }

    #[must_use]
    pub const fn variants() -> [LiquidityPoolType; 1] {
        Self::VARIANTS
    }
}

impl Name for LiquidityPoolType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<LiquidityPoolType> for LiquidityPoolType {
    fn variants() -> slice::Iter<'static, LiquidityPoolType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for LiquidityPoolType {}

impl fmt::Display for LiquidityPoolType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for LiquidityPoolType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => LiquidityPoolType::LiquidityPoolConstantProduct,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<LiquidityPoolType> for i32 {
    #[must_use]
    fn from(e: LiquidityPoolType) -> Self {
        e as Self
    }
}

impl ReadXdr for LiquidityPoolType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for LiquidityPoolType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// TrustLineAsset is an XDR Union defines as:
//
//   union TrustLineAsset switch (AssetType type)
//    {
//    case ASSET_TYPE_NATIVE: // Not credit
//        void;
//
//    case ASSET_TYPE_CREDIT_ALPHANUM4:
//        AlphaNum4 alphaNum4;
//
//    case ASSET_TYPE_CREDIT_ALPHANUM12:
//        AlphaNum12 alphaNum12;
//
//    case ASSET_TYPE_POOL_SHARE:
//        PoolID liquidityPoolID;
//
//        // add other asset types here in the future
//    };
//
// union with discriminant AssetType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TrustLineAsset {
    Native,
    CreditAlphanum4(AlphaNum4),
    CreditAlphanum12(AlphaNum12),
    PoolShare(PoolId),
}

impl TrustLineAsset {
    pub const VARIANTS: [AssetType; 4] = [
        AssetType::Native,
        AssetType::CreditAlphanum4,
        AssetType::CreditAlphanum12,
        AssetType::PoolShare,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Native", "CreditAlphanum4", "CreditAlphanum12", "PoolShare"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Native => "Native",
            Self::CreditAlphanum4(_) => "CreditAlphanum4",
            Self::CreditAlphanum12(_) => "CreditAlphanum12",
            Self::PoolShare(_) => "PoolShare",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> AssetType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Native => AssetType::Native,
            Self::CreditAlphanum4(_) => AssetType::CreditAlphanum4,
            Self::CreditAlphanum12(_) => AssetType::CreditAlphanum12,
            Self::PoolShare(_) => AssetType::PoolShare,
        }
    }

    #[must_use]
    pub const fn variants() -> [AssetType; 4] {
        Self::VARIANTS
    }
}

impl Name for TrustLineAsset {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<AssetType> for TrustLineAsset {
    #[must_use]
    fn discriminant(&self) -> AssetType {
        Self::discriminant(self)
    }
}

impl Variants<AssetType> for TrustLineAsset {
    fn variants() -> slice::Iter<'static, AssetType> {
        Self::VARIANTS.iter()
    }
}

impl Union<AssetType> for TrustLineAsset {}

impl ReadXdr for TrustLineAsset {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: AssetType = <AssetType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            AssetType::Native => Self::Native,
            AssetType::CreditAlphanum4 => Self::CreditAlphanum4(AlphaNum4::read_xdr(r)?),
            AssetType::CreditAlphanum12 => Self::CreditAlphanum12(AlphaNum12::read_xdr(r)?),
            AssetType::PoolShare => Self::PoolShare(PoolId::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TrustLineAsset {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Native => ().write_xdr(w)?,
            Self::CreditAlphanum4(v) => v.write_xdr(w)?,
            Self::CreditAlphanum12(v) => v.write_xdr(w)?,
            Self::PoolShare(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TrustLineEntryExtensionV2Ext is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TrustLineEntryExtensionV2Ext {
    V0,
}

impl TrustLineEntryExtensionV2Ext {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for TrustLineEntryExtensionV2Ext {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TrustLineEntryExtensionV2Ext {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TrustLineEntryExtensionV2Ext {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TrustLineEntryExtensionV2Ext {}

impl ReadXdr for TrustLineEntryExtensionV2Ext {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TrustLineEntryExtensionV2Ext {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// TrustLineEntryExtensionV2 is an XDR Struct defines as:
//
//   struct TrustLineEntryExtensionV2
//    {
//        int32 liquidityPoolUseCount;
//
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TrustLineEntryExtensionV2 {
    pub liquidity_pool_use_count: i32,
    pub ext: TrustLineEntryExtensionV2Ext,
}

impl ReadXdr for TrustLineEntryExtensionV2 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            liquidity_pool_use_count: i32::read_xdr(r)?,
            ext: TrustLineEntryExtensionV2Ext::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TrustLineEntryExtensionV2 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.liquidity_pool_use_count.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// TrustLineEntryV1Ext is an XDR NestedUnion defines as:
//
//   union switch (int v)
//                {
//                case 0:
//                    void;
//                case 2:
//                    TrustLineEntryExtensionV2 v2;
//                }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TrustLineEntryV1Ext {
    V0,
    V2(TrustLineEntryExtensionV2),
}

impl TrustLineEntryV1Ext {
    pub const VARIANTS: [i32; 2] = [0, 2];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V2"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::V2(_) => "V2",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
            Self::V2(_) => 2,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for TrustLineEntryV1Ext {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TrustLineEntryV1Ext {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TrustLineEntryV1Ext {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TrustLineEntryV1Ext {}

impl ReadXdr for TrustLineEntryV1Ext {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            2 => Self::V2(TrustLineEntryExtensionV2::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TrustLineEntryV1Ext {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
            Self::V2(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TrustLineEntryV1 is an XDR NestedStruct defines as:
//
//   struct
//            {
//                Liabilities liabilities;
//
//                union switch (int v)
//                {
//                case 0:
//                    void;
//                case 2:
//                    TrustLineEntryExtensionV2 v2;
//                }
//                ext;
//            }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TrustLineEntryV1 {
    pub liabilities: Liabilities,
    pub ext: TrustLineEntryV1Ext,
}

impl ReadXdr for TrustLineEntryV1 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            liabilities: Liabilities::read_xdr(r)?,
            ext: TrustLineEntryV1Ext::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TrustLineEntryV1 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.liabilities.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// TrustLineEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            struct
//            {
//                Liabilities liabilities;
//
//                union switch (int v)
//                {
//                case 0:
//                    void;
//                case 2:
//                    TrustLineEntryExtensionV2 v2;
//                }
//                ext;
//            } v1;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TrustLineEntryExt {
    V0,
    V1(TrustLineEntryV1),
}

impl TrustLineEntryExt {
    pub const VARIANTS: [i32; 2] = [0, 1];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V1"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::V1(_) => "V1",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
            Self::V1(_) => 1,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for TrustLineEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TrustLineEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TrustLineEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TrustLineEntryExt {}

impl ReadXdr for TrustLineEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            1 => Self::V1(TrustLineEntryV1::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TrustLineEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TrustLineEntry is an XDR Struct defines as:
//
//   struct TrustLineEntry
//    {
//        AccountID accountID;  // account this trustline belongs to
//        TrustLineAsset asset; // type of asset (with issuer)
//        int64 balance;        // how much of this asset the user has.
//                              // Asset defines the unit for this;
//
//        int64 limit;  // balance cannot be above this
//        uint32 flags; // see TrustLineFlags
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            struct
//            {
//                Liabilities liabilities;
//
//                union switch (int v)
//                {
//                case 0:
//                    void;
//                case 2:
//                    TrustLineEntryExtensionV2 v2;
//                }
//                ext;
//            } v1;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TrustLineEntry {
    pub account_id: AccountId,
    pub asset: TrustLineAsset,
    pub balance: i64,
    pub limit: i64,
    pub flags: u32,
    pub ext: TrustLineEntryExt,
}

impl ReadXdr for TrustLineEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            account_id: AccountId::read_xdr(r)?,
            asset: TrustLineAsset::read_xdr(r)?,
            balance: i64::read_xdr(r)?,
            limit: i64::read_xdr(r)?,
            flags: u32::read_xdr(r)?,
            ext: TrustLineEntryExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TrustLineEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.account_id.write_xdr(w)?;
        self.asset.write_xdr(w)?;
        self.balance.write_xdr(w)?;
        self.limit.write_xdr(w)?;
        self.flags.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// OfferEntryFlags is an XDR Enum defines as:
//
//   enum OfferEntryFlags
//    {
//        // an offer with this flag will not act on and take a reverse offer of equal
//        // price
//        PASSIVE_FLAG = 1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum OfferEntryFlags {
    PassiveFlag = 1,
}

impl OfferEntryFlags {
    pub const VARIANTS: [OfferEntryFlags; 1] = [OfferEntryFlags::PassiveFlag];
    pub const VARIANTS_STR: [&'static str; 1] = ["PassiveFlag"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::PassiveFlag => "PassiveFlag",
        }
    }

    #[must_use]
    pub const fn variants() -> [OfferEntryFlags; 1] {
        Self::VARIANTS
    }
}

impl Name for OfferEntryFlags {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<OfferEntryFlags> for OfferEntryFlags {
    fn variants() -> slice::Iter<'static, OfferEntryFlags> {
        Self::VARIANTS.iter()
    }
}

impl Enum for OfferEntryFlags {}

impl fmt::Display for OfferEntryFlags {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for OfferEntryFlags {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            1 => OfferEntryFlags::PassiveFlag,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<OfferEntryFlags> for i32 {
    #[must_use]
    fn from(e: OfferEntryFlags) -> Self {
        e as Self
    }
}

impl ReadXdr for OfferEntryFlags {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for OfferEntryFlags {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// MaskOfferentryFlags is an XDR Const defines as:
//
//   const MASK_OFFERENTRY_FLAGS = 1;
//
pub const MASK_OFFERENTRY_FLAGS: u64 = 1;

// OfferEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum OfferEntryExt {
    V0,
}

impl OfferEntryExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for OfferEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for OfferEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for OfferEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for OfferEntryExt {}

impl ReadXdr for OfferEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for OfferEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// OfferEntry is an XDR Struct defines as:
//
//   struct OfferEntry
//    {
//        AccountID sellerID;
//        int64 offerID;
//        Asset selling; // A
//        Asset buying;  // B
//        int64 amount;  // amount of A
//
//        /* price for this offer:
//            price of A in terms of B
//            price=AmountB/AmountA=priceNumerator/priceDenominator
//            price is after fees
//        */
//        Price price;
//        uint32 flags; // see OfferEntryFlags
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct OfferEntry {
    pub seller_id: AccountId,
    pub offer_id: i64,
    pub selling: Asset,
    pub buying: Asset,
    pub amount: i64,
    pub price: Price,
    pub flags: u32,
    pub ext: OfferEntryExt,
}

impl ReadXdr for OfferEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            seller_id: AccountId::read_xdr(r)?,
            offer_id: i64::read_xdr(r)?,
            selling: Asset::read_xdr(r)?,
            buying: Asset::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
            price: Price::read_xdr(r)?,
            flags: u32::read_xdr(r)?,
            ext: OfferEntryExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for OfferEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.seller_id.write_xdr(w)?;
        self.offer_id.write_xdr(w)?;
        self.selling.write_xdr(w)?;
        self.buying.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        self.price.write_xdr(w)?;
        self.flags.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// DataEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum DataEntryExt {
    V0,
}

impl DataEntryExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for DataEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for DataEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for DataEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for DataEntryExt {}

impl ReadXdr for DataEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for DataEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// DataEntry is an XDR Struct defines as:
//
//   struct DataEntry
//    {
//        AccountID accountID; // account this data belongs to
//        string64 dataName;
//        DataValue dataValue;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct DataEntry {
    pub account_id: AccountId,
    pub data_name: StringM<64>,
    pub data_value: DataValue,
    pub ext: DataEntryExt,
}

impl ReadXdr for DataEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            account_id: AccountId::read_xdr(r)?,
            data_name: StringM::<64>::read_xdr(r)?,
            data_value: DataValue::read_xdr(r)?,
            ext: DataEntryExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for DataEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.account_id.write_xdr(w)?;
        self.data_name.write_xdr(w)?;
        self.data_value.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// ClaimPredicateType is an XDR Enum defines as:
//
//   enum ClaimPredicateType
//    {
//        CLAIM_PREDICATE_UNCONDITIONAL = 0,
//        CLAIM_PREDICATE_AND = 1,
//        CLAIM_PREDICATE_OR = 2,
//        CLAIM_PREDICATE_NOT = 3,
//        CLAIM_PREDICATE_BEFORE_ABSOLUTE_TIME = 4,
//        CLAIM_PREDICATE_BEFORE_RELATIVE_TIME = 5
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ClaimPredicateType {
    Unconditional = 0,
    And = 1,
    Or = 2,
    Not = 3,
    BeforeAbsoluteTime = 4,
    BeforeRelativeTime = 5,
}

impl ClaimPredicateType {
    pub const VARIANTS: [ClaimPredicateType; 6] = [
        ClaimPredicateType::Unconditional,
        ClaimPredicateType::And,
        ClaimPredicateType::Or,
        ClaimPredicateType::Not,
        ClaimPredicateType::BeforeAbsoluteTime,
        ClaimPredicateType::BeforeRelativeTime,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Unconditional",
        "And",
        "Or",
        "Not",
        "BeforeAbsoluteTime",
        "BeforeRelativeTime",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Unconditional => "Unconditional",
            Self::And => "And",
            Self::Or => "Or",
            Self::Not => "Not",
            Self::BeforeAbsoluteTime => "BeforeAbsoluteTime",
            Self::BeforeRelativeTime => "BeforeRelativeTime",
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimPredicateType; 6] {
        Self::VARIANTS
    }
}

impl Name for ClaimPredicateType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ClaimPredicateType> for ClaimPredicateType {
    fn variants() -> slice::Iter<'static, ClaimPredicateType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ClaimPredicateType {}

impl fmt::Display for ClaimPredicateType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ClaimPredicateType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ClaimPredicateType::Unconditional,
            1 => ClaimPredicateType::And,
            2 => ClaimPredicateType::Or,
            3 => ClaimPredicateType::Not,
            4 => ClaimPredicateType::BeforeAbsoluteTime,
            5 => ClaimPredicateType::BeforeRelativeTime,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ClaimPredicateType> for i32 {
    #[must_use]
    fn from(e: ClaimPredicateType) -> Self {
        e as Self
    }
}

impl ReadXdr for ClaimPredicateType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ClaimPredicateType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ClaimPredicate is an XDR Union defines as:
//
//   union ClaimPredicate switch (ClaimPredicateType type)
//    {
//    case CLAIM_PREDICATE_UNCONDITIONAL:
//        void;
//    case CLAIM_PREDICATE_AND:
//        ClaimPredicate andPredicates<2>;
//    case CLAIM_PREDICATE_OR:
//        ClaimPredicate orPredicates<2>;
//    case CLAIM_PREDICATE_NOT:
//        ClaimPredicate* notPredicate;
//    case CLAIM_PREDICATE_BEFORE_ABSOLUTE_TIME:
//        int64 absBefore; // Predicate will be true if closeTime < absBefore
//    case CLAIM_PREDICATE_BEFORE_RELATIVE_TIME:
//        int64 relBefore; // Seconds since closeTime of the ledger in which the
//                         // ClaimableBalanceEntry was created
//    };
//
// union with discriminant ClaimPredicateType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ClaimPredicate {
    Unconditional,
    And(VecM<ClaimPredicate, 2>),
    Or(VecM<ClaimPredicate, 2>),
    Not(Option<Box<ClaimPredicate>>),
    BeforeAbsoluteTime(i64),
    BeforeRelativeTime(i64),
}

impl ClaimPredicate {
    pub const VARIANTS: [ClaimPredicateType; 6] = [
        ClaimPredicateType::Unconditional,
        ClaimPredicateType::And,
        ClaimPredicateType::Or,
        ClaimPredicateType::Not,
        ClaimPredicateType::BeforeAbsoluteTime,
        ClaimPredicateType::BeforeRelativeTime,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Unconditional",
        "And",
        "Or",
        "Not",
        "BeforeAbsoluteTime",
        "BeforeRelativeTime",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Unconditional => "Unconditional",
            Self::And(_) => "And",
            Self::Or(_) => "Or",
            Self::Not(_) => "Not",
            Self::BeforeAbsoluteTime(_) => "BeforeAbsoluteTime",
            Self::BeforeRelativeTime(_) => "BeforeRelativeTime",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ClaimPredicateType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Unconditional => ClaimPredicateType::Unconditional,
            Self::And(_) => ClaimPredicateType::And,
            Self::Or(_) => ClaimPredicateType::Or,
            Self::Not(_) => ClaimPredicateType::Not,
            Self::BeforeAbsoluteTime(_) => ClaimPredicateType::BeforeAbsoluteTime,
            Self::BeforeRelativeTime(_) => ClaimPredicateType::BeforeRelativeTime,
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimPredicateType; 6] {
        Self::VARIANTS
    }
}

impl Name for ClaimPredicate {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ClaimPredicateType> for ClaimPredicate {
    #[must_use]
    fn discriminant(&self) -> ClaimPredicateType {
        Self::discriminant(self)
    }
}

impl Variants<ClaimPredicateType> for ClaimPredicate {
    fn variants() -> slice::Iter<'static, ClaimPredicateType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ClaimPredicateType> for ClaimPredicate {}

impl ReadXdr for ClaimPredicate {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ClaimPredicateType = <ClaimPredicateType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ClaimPredicateType::Unconditional => Self::Unconditional,
            ClaimPredicateType::And => Self::And(VecM::<ClaimPredicate, 2>::read_xdr(r)?),
            ClaimPredicateType::Or => Self::Or(VecM::<ClaimPredicate, 2>::read_xdr(r)?),
            ClaimPredicateType::Not => Self::Not(Option::<Box<ClaimPredicate>>::read_xdr(r)?),
            ClaimPredicateType::BeforeAbsoluteTime => Self::BeforeAbsoluteTime(i64::read_xdr(r)?),
            ClaimPredicateType::BeforeRelativeTime => Self::BeforeRelativeTime(i64::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ClaimPredicate {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Unconditional => ().write_xdr(w)?,
            Self::And(v) => v.write_xdr(w)?,
            Self::Or(v) => v.write_xdr(w)?,
            Self::Not(v) => v.write_xdr(w)?,
            Self::BeforeAbsoluteTime(v) => v.write_xdr(w)?,
            Self::BeforeRelativeTime(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ClaimantType is an XDR Enum defines as:
//
//   enum ClaimantType
//    {
//        CLAIMANT_TYPE_V0 = 0
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ClaimantType {
    ClaimantTypeV0 = 0,
}

impl ClaimantType {
    pub const VARIANTS: [ClaimantType; 1] = [ClaimantType::ClaimantTypeV0];
    pub const VARIANTS_STR: [&'static str; 1] = ["ClaimantTypeV0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ClaimantTypeV0 => "ClaimantTypeV0",
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimantType; 1] {
        Self::VARIANTS
    }
}

impl Name for ClaimantType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ClaimantType> for ClaimantType {
    fn variants() -> slice::Iter<'static, ClaimantType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ClaimantType {}

impl fmt::Display for ClaimantType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ClaimantType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ClaimantType::ClaimantTypeV0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ClaimantType> for i32 {
    #[must_use]
    fn from(e: ClaimantType) -> Self {
        e as Self
    }
}

impl ReadXdr for ClaimantType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ClaimantType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ClaimantV0 is an XDR NestedStruct defines as:
//
//   struct
//        {
//            AccountID destination;    // The account that can use this condition
//            ClaimPredicate predicate; // Claimable if predicate is true
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ClaimantV0 {
    pub destination: AccountId,
    pub predicate: ClaimPredicate,
}

impl ReadXdr for ClaimantV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            destination: AccountId::read_xdr(r)?,
            predicate: ClaimPredicate::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ClaimantV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.destination.write_xdr(w)?;
        self.predicate.write_xdr(w)?;
        Ok(())
    }
}

// Claimant is an XDR Union defines as:
//
//   union Claimant switch (ClaimantType type)
//    {
//    case CLAIMANT_TYPE_V0:
//        struct
//        {
//            AccountID destination;    // The account that can use this condition
//            ClaimPredicate predicate; // Claimable if predicate is true
//        } v0;
//    };
//
// union with discriminant ClaimantType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum Claimant {
    ClaimantTypeV0(ClaimantV0),
}

impl Claimant {
    pub const VARIANTS: [ClaimantType; 1] = [ClaimantType::ClaimantTypeV0];
    pub const VARIANTS_STR: [&'static str; 1] = ["ClaimantTypeV0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ClaimantTypeV0(_) => "ClaimantTypeV0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ClaimantType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ClaimantTypeV0(_) => ClaimantType::ClaimantTypeV0,
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimantType; 1] {
        Self::VARIANTS
    }
}

impl Name for Claimant {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ClaimantType> for Claimant {
    #[must_use]
    fn discriminant(&self) -> ClaimantType {
        Self::discriminant(self)
    }
}

impl Variants<ClaimantType> for Claimant {
    fn variants() -> slice::Iter<'static, ClaimantType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ClaimantType> for Claimant {}

impl ReadXdr for Claimant {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ClaimantType = <ClaimantType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ClaimantType::ClaimantTypeV0 => Self::ClaimantTypeV0(ClaimantV0::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for Claimant {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ClaimantTypeV0(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ClaimableBalanceIdType is an XDR Enum defines as:
//
//   enum ClaimableBalanceIDType
//    {
//        CLAIMABLE_BALANCE_ID_TYPE_V0 = 0
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ClaimableBalanceIdType {
    ClaimableBalanceIdTypeV0 = 0,
}

impl ClaimableBalanceIdType {
    pub const VARIANTS: [ClaimableBalanceIdType; 1] =
        [ClaimableBalanceIdType::ClaimableBalanceIdTypeV0];
    pub const VARIANTS_STR: [&'static str; 1] = ["ClaimableBalanceIdTypeV0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ClaimableBalanceIdTypeV0 => "ClaimableBalanceIdTypeV0",
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimableBalanceIdType; 1] {
        Self::VARIANTS
    }
}

impl Name for ClaimableBalanceIdType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ClaimableBalanceIdType> for ClaimableBalanceIdType {
    fn variants() -> slice::Iter<'static, ClaimableBalanceIdType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ClaimableBalanceIdType {}

impl fmt::Display for ClaimableBalanceIdType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ClaimableBalanceIdType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ClaimableBalanceIdType::ClaimableBalanceIdTypeV0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ClaimableBalanceIdType> for i32 {
    #[must_use]
    fn from(e: ClaimableBalanceIdType) -> Self {
        e as Self
    }
}

impl ReadXdr for ClaimableBalanceIdType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ClaimableBalanceIdType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ClaimableBalanceId is an XDR Union defines as:
//
//   union ClaimableBalanceID switch (ClaimableBalanceIDType type)
//    {
//    case CLAIMABLE_BALANCE_ID_TYPE_V0:
//        Hash v0;
//    };
//
// union with discriminant ClaimableBalanceIdType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ClaimableBalanceId {
    ClaimableBalanceIdTypeV0(Hash),
}

impl ClaimableBalanceId {
    pub const VARIANTS: [ClaimableBalanceIdType; 1] =
        [ClaimableBalanceIdType::ClaimableBalanceIdTypeV0];
    pub const VARIANTS_STR: [&'static str; 1] = ["ClaimableBalanceIdTypeV0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ClaimableBalanceIdTypeV0(_) => "ClaimableBalanceIdTypeV0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ClaimableBalanceIdType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ClaimableBalanceIdTypeV0(_) => ClaimableBalanceIdType::ClaimableBalanceIdTypeV0,
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimableBalanceIdType; 1] {
        Self::VARIANTS
    }
}

impl Name for ClaimableBalanceId {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ClaimableBalanceIdType> for ClaimableBalanceId {
    #[must_use]
    fn discriminant(&self) -> ClaimableBalanceIdType {
        Self::discriminant(self)
    }
}

impl Variants<ClaimableBalanceIdType> for ClaimableBalanceId {
    fn variants() -> slice::Iter<'static, ClaimableBalanceIdType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ClaimableBalanceIdType> for ClaimableBalanceId {}

impl ReadXdr for ClaimableBalanceId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ClaimableBalanceIdType = <ClaimableBalanceIdType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ClaimableBalanceIdType::ClaimableBalanceIdTypeV0 => {
                Self::ClaimableBalanceIdTypeV0(Hash::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ClaimableBalanceId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ClaimableBalanceIdTypeV0(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ClaimableBalanceFlags is an XDR Enum defines as:
//
//   enum ClaimableBalanceFlags
//    {
//        // If set, the issuer account of the asset held by the claimable balance may
//        // clawback the claimable balance
//        CLAIMABLE_BALANCE_CLAWBACK_ENABLED_FLAG = 0x1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ClaimableBalanceFlags {
    ClaimableBalanceClawbackEnabledFlag = 1,
}

impl ClaimableBalanceFlags {
    pub const VARIANTS: [ClaimableBalanceFlags; 1] =
        [ClaimableBalanceFlags::ClaimableBalanceClawbackEnabledFlag];
    pub const VARIANTS_STR: [&'static str; 1] = ["ClaimableBalanceClawbackEnabledFlag"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ClaimableBalanceClawbackEnabledFlag => "ClaimableBalanceClawbackEnabledFlag",
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimableBalanceFlags; 1] {
        Self::VARIANTS
    }
}

impl Name for ClaimableBalanceFlags {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ClaimableBalanceFlags> for ClaimableBalanceFlags {
    fn variants() -> slice::Iter<'static, ClaimableBalanceFlags> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ClaimableBalanceFlags {}

impl fmt::Display for ClaimableBalanceFlags {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ClaimableBalanceFlags {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            1 => ClaimableBalanceFlags::ClaimableBalanceClawbackEnabledFlag,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ClaimableBalanceFlags> for i32 {
    #[must_use]
    fn from(e: ClaimableBalanceFlags) -> Self {
        e as Self
    }
}

impl ReadXdr for ClaimableBalanceFlags {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ClaimableBalanceFlags {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// MaskClaimableBalanceFlags is an XDR Const defines as:
//
//   const MASK_CLAIMABLE_BALANCE_FLAGS = 0x1;
//
pub const MASK_CLAIMABLE_BALANCE_FLAGS: u64 = 0x1;

// ClaimableBalanceEntryExtensionV1Ext is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ClaimableBalanceEntryExtensionV1Ext {
    V0,
}

impl ClaimableBalanceEntryExtensionV1Ext {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for ClaimableBalanceEntryExtensionV1Ext {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for ClaimableBalanceEntryExtensionV1Ext {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for ClaimableBalanceEntryExtensionV1Ext {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for ClaimableBalanceEntryExtensionV1Ext {}

impl ReadXdr for ClaimableBalanceEntryExtensionV1Ext {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ClaimableBalanceEntryExtensionV1Ext {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ClaimableBalanceEntryExtensionV1 is an XDR Struct defines as:
//
//   struct ClaimableBalanceEntryExtensionV1
//    {
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//
//        uint32 flags; // see ClaimableBalanceFlags
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ClaimableBalanceEntryExtensionV1 {
    pub ext: ClaimableBalanceEntryExtensionV1Ext,
    pub flags: u32,
}

impl ReadXdr for ClaimableBalanceEntryExtensionV1 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ext: ClaimableBalanceEntryExtensionV1Ext::read_xdr(r)?,
            flags: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ClaimableBalanceEntryExtensionV1 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ext.write_xdr(w)?;
        self.flags.write_xdr(w)?;
        Ok(())
    }
}

// ClaimableBalanceEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            ClaimableBalanceEntryExtensionV1 v1;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ClaimableBalanceEntryExt {
    V0,
    V1(ClaimableBalanceEntryExtensionV1),
}

impl ClaimableBalanceEntryExt {
    pub const VARIANTS: [i32; 2] = [0, 1];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V1"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::V1(_) => "V1",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
            Self::V1(_) => 1,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for ClaimableBalanceEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for ClaimableBalanceEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for ClaimableBalanceEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for ClaimableBalanceEntryExt {}

impl ReadXdr for ClaimableBalanceEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            1 => Self::V1(ClaimableBalanceEntryExtensionV1::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ClaimableBalanceEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ClaimableBalanceEntry is an XDR Struct defines as:
//
//   struct ClaimableBalanceEntry
//    {
//        // Unique identifier for this ClaimableBalanceEntry
//        ClaimableBalanceID balanceID;
//
//        // List of claimants with associated predicate
//        Claimant claimants<10>;
//
//        // Any asset including native
//        Asset asset;
//
//        // Amount of asset
//        int64 amount;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            ClaimableBalanceEntryExtensionV1 v1;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ClaimableBalanceEntry {
    pub balance_id: ClaimableBalanceId,
    pub claimants: VecM<Claimant, 10>,
    pub asset: Asset,
    pub amount: i64,
    pub ext: ClaimableBalanceEntryExt,
}

impl ReadXdr for ClaimableBalanceEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            balance_id: ClaimableBalanceId::read_xdr(r)?,
            claimants: VecM::<Claimant, 10>::read_xdr(r)?,
            asset: Asset::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
            ext: ClaimableBalanceEntryExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ClaimableBalanceEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.balance_id.write_xdr(w)?;
        self.claimants.write_xdr(w)?;
        self.asset.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// LiquidityPoolConstantProductParameters is an XDR Struct defines as:
//
//   struct LiquidityPoolConstantProductParameters
//    {
//        Asset assetA; // assetA < assetB
//        Asset assetB;
//        int32 fee; // Fee is in basis points, so the actual rate is (fee/100)%
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LiquidityPoolConstantProductParameters {
    pub asset_a: Asset,
    pub asset_b: Asset,
    pub fee: i32,
}

impl ReadXdr for LiquidityPoolConstantProductParameters {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            asset_a: Asset::read_xdr(r)?,
            asset_b: Asset::read_xdr(r)?,
            fee: i32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LiquidityPoolConstantProductParameters {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.asset_a.write_xdr(w)?;
        self.asset_b.write_xdr(w)?;
        self.fee.write_xdr(w)?;
        Ok(())
    }
}

// LiquidityPoolEntryConstantProduct is an XDR NestedStruct defines as:
//
//   struct
//            {
//                LiquidityPoolConstantProductParameters params;
//
//                int64 reserveA;        // amount of A in the pool
//                int64 reserveB;        // amount of B in the pool
//                int64 totalPoolShares; // total number of pool shares issued
//                int64 poolSharesTrustLineCount; // number of trust lines for the
//                                                // associated pool shares
//            }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LiquidityPoolEntryConstantProduct {
    pub params: LiquidityPoolConstantProductParameters,
    pub reserve_a: i64,
    pub reserve_b: i64,
    pub total_pool_shares: i64,
    pub pool_shares_trust_line_count: i64,
}

impl ReadXdr for LiquidityPoolEntryConstantProduct {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            params: LiquidityPoolConstantProductParameters::read_xdr(r)?,
            reserve_a: i64::read_xdr(r)?,
            reserve_b: i64::read_xdr(r)?,
            total_pool_shares: i64::read_xdr(r)?,
            pool_shares_trust_line_count: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LiquidityPoolEntryConstantProduct {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.params.write_xdr(w)?;
        self.reserve_a.write_xdr(w)?;
        self.reserve_b.write_xdr(w)?;
        self.total_pool_shares.write_xdr(w)?;
        self.pool_shares_trust_line_count.write_xdr(w)?;
        Ok(())
    }
}

// LiquidityPoolEntryBody is an XDR NestedUnion defines as:
//
//   union switch (LiquidityPoolType type)
//        {
//        case LIQUIDITY_POOL_CONSTANT_PRODUCT:
//            struct
//            {
//                LiquidityPoolConstantProductParameters params;
//
//                int64 reserveA;        // amount of A in the pool
//                int64 reserveB;        // amount of B in the pool
//                int64 totalPoolShares; // total number of pool shares issued
//                int64 poolSharesTrustLineCount; // number of trust lines for the
//                                                // associated pool shares
//            } constantProduct;
//        }
//
// union with discriminant LiquidityPoolType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LiquidityPoolEntryBody {
    LiquidityPoolConstantProduct(LiquidityPoolEntryConstantProduct),
}

impl LiquidityPoolEntryBody {
    pub const VARIANTS: [LiquidityPoolType; 1] = [LiquidityPoolType::LiquidityPoolConstantProduct];
    pub const VARIANTS_STR: [&'static str; 1] = ["LiquidityPoolConstantProduct"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::LiquidityPoolConstantProduct(_) => "LiquidityPoolConstantProduct",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> LiquidityPoolType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::LiquidityPoolConstantProduct(_) => {
                LiquidityPoolType::LiquidityPoolConstantProduct
            }
        }
    }

    #[must_use]
    pub const fn variants() -> [LiquidityPoolType; 1] {
        Self::VARIANTS
    }
}

impl Name for LiquidityPoolEntryBody {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<LiquidityPoolType> for LiquidityPoolEntryBody {
    #[must_use]
    fn discriminant(&self) -> LiquidityPoolType {
        Self::discriminant(self)
    }
}

impl Variants<LiquidityPoolType> for LiquidityPoolEntryBody {
    fn variants() -> slice::Iter<'static, LiquidityPoolType> {
        Self::VARIANTS.iter()
    }
}

impl Union<LiquidityPoolType> for LiquidityPoolEntryBody {}

impl ReadXdr for LiquidityPoolEntryBody {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: LiquidityPoolType = <LiquidityPoolType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            LiquidityPoolType::LiquidityPoolConstantProduct => {
                Self::LiquidityPoolConstantProduct(LiquidityPoolEntryConstantProduct::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LiquidityPoolEntryBody {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::LiquidityPoolConstantProduct(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// LiquidityPoolEntry is an XDR Struct defines as:
//
//   struct LiquidityPoolEntry
//    {
//        PoolID liquidityPoolID;
//
//        union switch (LiquidityPoolType type)
//        {
//        case LIQUIDITY_POOL_CONSTANT_PRODUCT:
//            struct
//            {
//                LiquidityPoolConstantProductParameters params;
//
//                int64 reserveA;        // amount of A in the pool
//                int64 reserveB;        // amount of B in the pool
//                int64 totalPoolShares; // total number of pool shares issued
//                int64 poolSharesTrustLineCount; // number of trust lines for the
//                                                // associated pool shares
//            } constantProduct;
//        }
//        body;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LiquidityPoolEntry {
    pub liquidity_pool_id: PoolId,
    pub body: LiquidityPoolEntryBody,
}

impl ReadXdr for LiquidityPoolEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            liquidity_pool_id: PoolId::read_xdr(r)?,
            body: LiquidityPoolEntryBody::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LiquidityPoolEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.liquidity_pool_id.write_xdr(w)?;
        self.body.write_xdr(w)?;
        Ok(())
    }
}

// ContractDataEntry is an XDR Struct defines as:
//
//   struct ContractDataEntry {
//        Hash contractID;
//        SCVal key;
//        SCVal val;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ContractDataEntry {
    pub contract_id: Hash,
    pub key: ScVal,
    pub val: ScVal,
}

impl ReadXdr for ContractDataEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            contract_id: Hash::read_xdr(r)?,
            key: ScVal::read_xdr(r)?,
            val: ScVal::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ContractDataEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.contract_id.write_xdr(w)?;
        self.key.write_xdr(w)?;
        self.val.write_xdr(w)?;
        Ok(())
    }
}

// ContractCodeEntry is an XDR Struct defines as:
//
//   struct ContractCodeEntry {
//        ExtensionPoint ext;
//
//        Hash hash;
//        opaque code<SCVAL_LIMIT>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ContractCodeEntry {
    pub ext: ExtensionPoint,
    pub hash: Hash,
    pub code: BytesM<256000>,
}

impl ReadXdr for ContractCodeEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ext: ExtensionPoint::read_xdr(r)?,
            hash: Hash::read_xdr(r)?,
            code: BytesM::<256000>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ContractCodeEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ext.write_xdr(w)?;
        self.hash.write_xdr(w)?;
        self.code.write_xdr(w)?;
        Ok(())
    }
}

// ConfigSettingType is an XDR Enum defines as:
//
//   enum ConfigSettingType
//    {
//        CONFIG_SETTING_TYPE_UINT32 = 0
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ConfigSettingType {
    ConfigSettingTypeUint32 = 0,
}

impl ConfigSettingType {
    pub const VARIANTS: [ConfigSettingType; 1] = [ConfigSettingType::ConfigSettingTypeUint32];
    pub const VARIANTS_STR: [&'static str; 1] = ["ConfigSettingTypeUint32"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ConfigSettingTypeUint32 => "ConfigSettingTypeUint32",
        }
    }

    #[must_use]
    pub const fn variants() -> [ConfigSettingType; 1] {
        Self::VARIANTS
    }
}

impl Name for ConfigSettingType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ConfigSettingType> for ConfigSettingType {
    fn variants() -> slice::Iter<'static, ConfigSettingType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ConfigSettingType {}

impl fmt::Display for ConfigSettingType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ConfigSettingType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ConfigSettingType::ConfigSettingTypeUint32,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ConfigSettingType> for i32 {
    #[must_use]
    fn from(e: ConfigSettingType) -> Self {
        e as Self
    }
}

impl ReadXdr for ConfigSettingType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ConfigSettingType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ConfigSetting is an XDR Union defines as:
//
//   union ConfigSetting switch (ConfigSettingType type)
//    {
//    case CONFIG_SETTING_TYPE_UINT32:
//        uint32 uint32Val;
//    };
//
// union with discriminant ConfigSettingType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ConfigSetting {
    ConfigSettingTypeUint32(u32),
}

impl ConfigSetting {
    pub const VARIANTS: [ConfigSettingType; 1] = [ConfigSettingType::ConfigSettingTypeUint32];
    pub const VARIANTS_STR: [&'static str; 1] = ["ConfigSettingTypeUint32"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ConfigSettingTypeUint32(_) => "ConfigSettingTypeUint32",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ConfigSettingType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ConfigSettingTypeUint32(_) => ConfigSettingType::ConfigSettingTypeUint32,
        }
    }

    #[must_use]
    pub const fn variants() -> [ConfigSettingType; 1] {
        Self::VARIANTS
    }
}

impl Name for ConfigSetting {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ConfigSettingType> for ConfigSetting {
    #[must_use]
    fn discriminant(&self) -> ConfigSettingType {
        Self::discriminant(self)
    }
}

impl Variants<ConfigSettingType> for ConfigSetting {
    fn variants() -> slice::Iter<'static, ConfigSettingType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ConfigSettingType> for ConfigSetting {}

impl ReadXdr for ConfigSetting {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ConfigSettingType = <ConfigSettingType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ConfigSettingType::ConfigSettingTypeUint32 => {
                Self::ConfigSettingTypeUint32(u32::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ConfigSetting {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ConfigSettingTypeUint32(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ConfigSettingId is an XDR Enum defines as:
//
//   enum ConfigSettingID
//    {
//        CONFIG_SETTING_CONTRACT_MAX_SIZE = 0
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ConfigSettingId {
    ConfigSettingContractMaxSize = 0,
}

impl ConfigSettingId {
    pub const VARIANTS: [ConfigSettingId; 1] = [ConfigSettingId::ConfigSettingContractMaxSize];
    pub const VARIANTS_STR: [&'static str; 1] = ["ConfigSettingContractMaxSize"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ConfigSettingContractMaxSize => "ConfigSettingContractMaxSize",
        }
    }

    #[must_use]
    pub const fn variants() -> [ConfigSettingId; 1] {
        Self::VARIANTS
    }
}

impl Name for ConfigSettingId {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ConfigSettingId> for ConfigSettingId {
    fn variants() -> slice::Iter<'static, ConfigSettingId> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ConfigSettingId {}

impl fmt::Display for ConfigSettingId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ConfigSettingId {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ConfigSettingId::ConfigSettingContractMaxSize,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ConfigSettingId> for i32 {
    #[must_use]
    fn from(e: ConfigSettingId) -> Self {
        e as Self
    }
}

impl ReadXdr for ConfigSettingId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ConfigSettingId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ConfigSettingEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ConfigSettingEntryExt {
    V0,
}

impl ConfigSettingEntryExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for ConfigSettingEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for ConfigSettingEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for ConfigSettingEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for ConfigSettingEntryExt {}

impl ReadXdr for ConfigSettingEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ConfigSettingEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ConfigSettingEntry is an XDR Struct defines as:
//
//   struct ConfigSettingEntry
//    {
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//
//        ConfigSettingID configSettingID;
//        ConfigSetting setting;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ConfigSettingEntry {
    pub ext: ConfigSettingEntryExt,
    pub config_setting_id: ConfigSettingId,
    pub setting: ConfigSetting,
}

impl ReadXdr for ConfigSettingEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ext: ConfigSettingEntryExt::read_xdr(r)?,
            config_setting_id: ConfigSettingId::read_xdr(r)?,
            setting: ConfigSetting::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ConfigSettingEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ext.write_xdr(w)?;
        self.config_setting_id.write_xdr(w)?;
        self.setting.write_xdr(w)?;
        Ok(())
    }
}

// LedgerEntryExtensionV1Ext is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerEntryExtensionV1Ext {
    V0,
}

impl LedgerEntryExtensionV1Ext {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for LedgerEntryExtensionV1Ext {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for LedgerEntryExtensionV1Ext {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for LedgerEntryExtensionV1Ext {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for LedgerEntryExtensionV1Ext {}

impl ReadXdr for LedgerEntryExtensionV1Ext {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerEntryExtensionV1Ext {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// LedgerEntryExtensionV1 is an XDR Struct defines as:
//
//   struct LedgerEntryExtensionV1
//    {
//        SponsorshipDescriptor sponsoringID;
//
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerEntryExtensionV1 {
    pub sponsoring_id: SponsorshipDescriptor,
    pub ext: LedgerEntryExtensionV1Ext,
}

impl ReadXdr for LedgerEntryExtensionV1 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            sponsoring_id: SponsorshipDescriptor::read_xdr(r)?,
            ext: LedgerEntryExtensionV1Ext::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerEntryExtensionV1 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.sponsoring_id.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// LedgerEntryData is an XDR NestedUnion defines as:
//
//   union switch (LedgerEntryType type)
//        {
//        case ACCOUNT:
//            AccountEntry account;
//        case TRUSTLINE:
//            TrustLineEntry trustLine;
//        case OFFER:
//            OfferEntry offer;
//        case DATA:
//            DataEntry data;
//        case CLAIMABLE_BALANCE:
//            ClaimableBalanceEntry claimableBalance;
//        case LIQUIDITY_POOL:
//            LiquidityPoolEntry liquidityPool;
//        case CONTRACT_DATA:
//            ContractDataEntry contractData;
//        case CONTRACT_CODE:
//            ContractCodeEntry contractCode;
//        case CONFIG_SETTING:
//            ConfigSettingEntry configSetting;
//        }
//
// union with discriminant LedgerEntryType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerEntryData {
    Account(AccountEntry),
    Trustline(TrustLineEntry),
    Offer(OfferEntry),
    Data(DataEntry),
    ClaimableBalance(ClaimableBalanceEntry),
    LiquidityPool(LiquidityPoolEntry),
    ContractData(ContractDataEntry),
    ContractCode(ContractCodeEntry),
    ConfigSetting(ConfigSettingEntry),
}

impl LedgerEntryData {
    pub const VARIANTS: [LedgerEntryType; 9] = [
        LedgerEntryType::Account,
        LedgerEntryType::Trustline,
        LedgerEntryType::Offer,
        LedgerEntryType::Data,
        LedgerEntryType::ClaimableBalance,
        LedgerEntryType::LiquidityPool,
        LedgerEntryType::ContractData,
        LedgerEntryType::ContractCode,
        LedgerEntryType::ConfigSetting,
    ];
    pub const VARIANTS_STR: [&'static str; 9] = [
        "Account",
        "Trustline",
        "Offer",
        "Data",
        "ClaimableBalance",
        "LiquidityPool",
        "ContractData",
        "ContractCode",
        "ConfigSetting",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Account(_) => "Account",
            Self::Trustline(_) => "Trustline",
            Self::Offer(_) => "Offer",
            Self::Data(_) => "Data",
            Self::ClaimableBalance(_) => "ClaimableBalance",
            Self::LiquidityPool(_) => "LiquidityPool",
            Self::ContractData(_) => "ContractData",
            Self::ContractCode(_) => "ContractCode",
            Self::ConfigSetting(_) => "ConfigSetting",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> LedgerEntryType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Account(_) => LedgerEntryType::Account,
            Self::Trustline(_) => LedgerEntryType::Trustline,
            Self::Offer(_) => LedgerEntryType::Offer,
            Self::Data(_) => LedgerEntryType::Data,
            Self::ClaimableBalance(_) => LedgerEntryType::ClaimableBalance,
            Self::LiquidityPool(_) => LedgerEntryType::LiquidityPool,
            Self::ContractData(_) => LedgerEntryType::ContractData,
            Self::ContractCode(_) => LedgerEntryType::ContractCode,
            Self::ConfigSetting(_) => LedgerEntryType::ConfigSetting,
        }
    }

    #[must_use]
    pub const fn variants() -> [LedgerEntryType; 9] {
        Self::VARIANTS
    }
}

impl Name for LedgerEntryData {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<LedgerEntryType> for LedgerEntryData {
    #[must_use]
    fn discriminant(&self) -> LedgerEntryType {
        Self::discriminant(self)
    }
}

impl Variants<LedgerEntryType> for LedgerEntryData {
    fn variants() -> slice::Iter<'static, LedgerEntryType> {
        Self::VARIANTS.iter()
    }
}

impl Union<LedgerEntryType> for LedgerEntryData {}

impl ReadXdr for LedgerEntryData {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: LedgerEntryType = <LedgerEntryType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            LedgerEntryType::Account => Self::Account(AccountEntry::read_xdr(r)?),
            LedgerEntryType::Trustline => Self::Trustline(TrustLineEntry::read_xdr(r)?),
            LedgerEntryType::Offer => Self::Offer(OfferEntry::read_xdr(r)?),
            LedgerEntryType::Data => Self::Data(DataEntry::read_xdr(r)?),
            LedgerEntryType::ClaimableBalance => {
                Self::ClaimableBalance(ClaimableBalanceEntry::read_xdr(r)?)
            }
            LedgerEntryType::LiquidityPool => Self::LiquidityPool(LiquidityPoolEntry::read_xdr(r)?),
            LedgerEntryType::ContractData => Self::ContractData(ContractDataEntry::read_xdr(r)?),
            LedgerEntryType::ContractCode => Self::ContractCode(ContractCodeEntry::read_xdr(r)?),
            LedgerEntryType::ConfigSetting => Self::ConfigSetting(ConfigSettingEntry::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerEntryData {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Account(v) => v.write_xdr(w)?,
            Self::Trustline(v) => v.write_xdr(w)?,
            Self::Offer(v) => v.write_xdr(w)?,
            Self::Data(v) => v.write_xdr(w)?,
            Self::ClaimableBalance(v) => v.write_xdr(w)?,
            Self::LiquidityPool(v) => v.write_xdr(w)?,
            Self::ContractData(v) => v.write_xdr(w)?,
            Self::ContractCode(v) => v.write_xdr(w)?,
            Self::ConfigSetting(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// LedgerEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            LedgerEntryExtensionV1 v1;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerEntryExt {
    V0,
    V1(LedgerEntryExtensionV1),
}

impl LedgerEntryExt {
    pub const VARIANTS: [i32; 2] = [0, 1];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V1"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::V1(_) => "V1",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
            Self::V1(_) => 1,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for LedgerEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for LedgerEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for LedgerEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for LedgerEntryExt {}

impl ReadXdr for LedgerEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            1 => Self::V1(LedgerEntryExtensionV1::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// LedgerEntry is an XDR Struct defines as:
//
//   struct LedgerEntry
//    {
//        uint32 lastModifiedLedgerSeq; // ledger the LedgerEntry was last changed
//
//        union switch (LedgerEntryType type)
//        {
//        case ACCOUNT:
//            AccountEntry account;
//        case TRUSTLINE:
//            TrustLineEntry trustLine;
//        case OFFER:
//            OfferEntry offer;
//        case DATA:
//            DataEntry data;
//        case CLAIMABLE_BALANCE:
//            ClaimableBalanceEntry claimableBalance;
//        case LIQUIDITY_POOL:
//            LiquidityPoolEntry liquidityPool;
//        case CONTRACT_DATA:
//            ContractDataEntry contractData;
//        case CONTRACT_CODE:
//            ContractCodeEntry contractCode;
//        case CONFIG_SETTING:
//            ConfigSettingEntry configSetting;
//        }
//        data;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            LedgerEntryExtensionV1 v1;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerEntry {
    pub last_modified_ledger_seq: u32,
    pub data: LedgerEntryData,
    pub ext: LedgerEntryExt,
}

impl ReadXdr for LedgerEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            last_modified_ledger_seq: u32::read_xdr(r)?,
            data: LedgerEntryData::read_xdr(r)?,
            ext: LedgerEntryExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.last_modified_ledger_seq.write_xdr(w)?;
        self.data.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKeyAccount is an XDR NestedStruct defines as:
//
//   struct
//        {
//            AccountID accountID;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerKeyAccount {
    pub account_id: AccountId,
}

impl ReadXdr for LedgerKeyAccount {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            account_id: AccountId::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerKeyAccount {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.account_id.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKeyTrustLine is an XDR NestedStruct defines as:
//
//   struct
//        {
//            AccountID accountID;
//            TrustLineAsset asset;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerKeyTrustLine {
    pub account_id: AccountId,
    pub asset: TrustLineAsset,
}

impl ReadXdr for LedgerKeyTrustLine {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            account_id: AccountId::read_xdr(r)?,
            asset: TrustLineAsset::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerKeyTrustLine {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.account_id.write_xdr(w)?;
        self.asset.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKeyOffer is an XDR NestedStruct defines as:
//
//   struct
//        {
//            AccountID sellerID;
//            int64 offerID;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerKeyOffer {
    pub seller_id: AccountId,
    pub offer_id: i64,
}

impl ReadXdr for LedgerKeyOffer {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            seller_id: AccountId::read_xdr(r)?,
            offer_id: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerKeyOffer {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.seller_id.write_xdr(w)?;
        self.offer_id.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKeyData is an XDR NestedStruct defines as:
//
//   struct
//        {
//            AccountID accountID;
//            string64 dataName;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerKeyData {
    pub account_id: AccountId,
    pub data_name: StringM<64>,
}

impl ReadXdr for LedgerKeyData {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            account_id: AccountId::read_xdr(r)?,
            data_name: StringM::<64>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerKeyData {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.account_id.write_xdr(w)?;
        self.data_name.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKeyClaimableBalance is an XDR NestedStruct defines as:
//
//   struct
//        {
//            ClaimableBalanceID balanceID;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerKeyClaimableBalance {
    pub balance_id: ClaimableBalanceId,
}

impl ReadXdr for LedgerKeyClaimableBalance {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            balance_id: ClaimableBalanceId::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerKeyClaimableBalance {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.balance_id.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKeyLiquidityPool is an XDR NestedStruct defines as:
//
//   struct
//        {
//            PoolID liquidityPoolID;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerKeyLiquidityPool {
    pub liquidity_pool_id: PoolId,
}

impl ReadXdr for LedgerKeyLiquidityPool {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            liquidity_pool_id: PoolId::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerKeyLiquidityPool {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.liquidity_pool_id.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKeyContractData is an XDR NestedStruct defines as:
//
//   struct
//        {
//            Hash contractID;
//            SCVal key;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerKeyContractData {
    pub contract_id: Hash,
    pub key: ScVal,
}

impl ReadXdr for LedgerKeyContractData {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            contract_id: Hash::read_xdr(r)?,
            key: ScVal::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerKeyContractData {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.contract_id.write_xdr(w)?;
        self.key.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKeyContractCode is an XDR NestedStruct defines as:
//
//   struct
//        {
//            Hash hash;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerKeyContractCode {
    pub hash: Hash,
}

impl ReadXdr for LedgerKeyContractCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            hash: Hash::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerKeyContractCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.hash.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKeyConfigSetting is an XDR NestedStruct defines as:
//
//   struct
//        {
//            ConfigSettingID configSettingID;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerKeyConfigSetting {
    pub config_setting_id: ConfigSettingId,
}

impl ReadXdr for LedgerKeyConfigSetting {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            config_setting_id: ConfigSettingId::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerKeyConfigSetting {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.config_setting_id.write_xdr(w)?;
        Ok(())
    }
}

// LedgerKey is an XDR Union defines as:
//
//   union LedgerKey switch (LedgerEntryType type)
//    {
//    case ACCOUNT:
//        struct
//        {
//            AccountID accountID;
//        } account;
//
//    case TRUSTLINE:
//        struct
//        {
//            AccountID accountID;
//            TrustLineAsset asset;
//        } trustLine;
//
//    case OFFER:
//        struct
//        {
//            AccountID sellerID;
//            int64 offerID;
//        } offer;
//
//    case DATA:
//        struct
//        {
//            AccountID accountID;
//            string64 dataName;
//        } data;
//
//    case CLAIMABLE_BALANCE:
//        struct
//        {
//            ClaimableBalanceID balanceID;
//        } claimableBalance;
//
//    case LIQUIDITY_POOL:
//        struct
//        {
//            PoolID liquidityPoolID;
//        } liquidityPool;
//    case CONTRACT_DATA:
//        struct
//        {
//            Hash contractID;
//            SCVal key;
//        } contractData;
//    case CONTRACT_CODE:
//        struct
//        {
//            Hash hash;
//        } contractCode;
//    case CONFIG_SETTING:
//        struct
//        {
//            ConfigSettingID configSettingID;
//        } configSetting;
//    };
//
// union with discriminant LedgerEntryType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerKey {
    Account(LedgerKeyAccount),
    Trustline(LedgerKeyTrustLine),
    Offer(LedgerKeyOffer),
    Data(LedgerKeyData),
    ClaimableBalance(LedgerKeyClaimableBalance),
    LiquidityPool(LedgerKeyLiquidityPool),
    ContractData(LedgerKeyContractData),
    ContractCode(LedgerKeyContractCode),
    ConfigSetting(LedgerKeyConfigSetting),
}

impl LedgerKey {
    pub const VARIANTS: [LedgerEntryType; 9] = [
        LedgerEntryType::Account,
        LedgerEntryType::Trustline,
        LedgerEntryType::Offer,
        LedgerEntryType::Data,
        LedgerEntryType::ClaimableBalance,
        LedgerEntryType::LiquidityPool,
        LedgerEntryType::ContractData,
        LedgerEntryType::ContractCode,
        LedgerEntryType::ConfigSetting,
    ];
    pub const VARIANTS_STR: [&'static str; 9] = [
        "Account",
        "Trustline",
        "Offer",
        "Data",
        "ClaimableBalance",
        "LiquidityPool",
        "ContractData",
        "ContractCode",
        "ConfigSetting",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Account(_) => "Account",
            Self::Trustline(_) => "Trustline",
            Self::Offer(_) => "Offer",
            Self::Data(_) => "Data",
            Self::ClaimableBalance(_) => "ClaimableBalance",
            Self::LiquidityPool(_) => "LiquidityPool",
            Self::ContractData(_) => "ContractData",
            Self::ContractCode(_) => "ContractCode",
            Self::ConfigSetting(_) => "ConfigSetting",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> LedgerEntryType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Account(_) => LedgerEntryType::Account,
            Self::Trustline(_) => LedgerEntryType::Trustline,
            Self::Offer(_) => LedgerEntryType::Offer,
            Self::Data(_) => LedgerEntryType::Data,
            Self::ClaimableBalance(_) => LedgerEntryType::ClaimableBalance,
            Self::LiquidityPool(_) => LedgerEntryType::LiquidityPool,
            Self::ContractData(_) => LedgerEntryType::ContractData,
            Self::ContractCode(_) => LedgerEntryType::ContractCode,
            Self::ConfigSetting(_) => LedgerEntryType::ConfigSetting,
        }
    }

    #[must_use]
    pub const fn variants() -> [LedgerEntryType; 9] {
        Self::VARIANTS
    }
}

impl Name for LedgerKey {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<LedgerEntryType> for LedgerKey {
    #[must_use]
    fn discriminant(&self) -> LedgerEntryType {
        Self::discriminant(self)
    }
}

impl Variants<LedgerEntryType> for LedgerKey {
    fn variants() -> slice::Iter<'static, LedgerEntryType> {
        Self::VARIANTS.iter()
    }
}

impl Union<LedgerEntryType> for LedgerKey {}

impl ReadXdr for LedgerKey {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: LedgerEntryType = <LedgerEntryType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            LedgerEntryType::Account => Self::Account(LedgerKeyAccount::read_xdr(r)?),
            LedgerEntryType::Trustline => Self::Trustline(LedgerKeyTrustLine::read_xdr(r)?),
            LedgerEntryType::Offer => Self::Offer(LedgerKeyOffer::read_xdr(r)?),
            LedgerEntryType::Data => Self::Data(LedgerKeyData::read_xdr(r)?),
            LedgerEntryType::ClaimableBalance => {
                Self::ClaimableBalance(LedgerKeyClaimableBalance::read_xdr(r)?)
            }
            LedgerEntryType::LiquidityPool => {
                Self::LiquidityPool(LedgerKeyLiquidityPool::read_xdr(r)?)
            }
            LedgerEntryType::ContractData => {
                Self::ContractData(LedgerKeyContractData::read_xdr(r)?)
            }
            LedgerEntryType::ContractCode => {
                Self::ContractCode(LedgerKeyContractCode::read_xdr(r)?)
            }
            LedgerEntryType::ConfigSetting => {
                Self::ConfigSetting(LedgerKeyConfigSetting::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerKey {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Account(v) => v.write_xdr(w)?,
            Self::Trustline(v) => v.write_xdr(w)?,
            Self::Offer(v) => v.write_xdr(w)?,
            Self::Data(v) => v.write_xdr(w)?,
            Self::ClaimableBalance(v) => v.write_xdr(w)?,
            Self::LiquidityPool(v) => v.write_xdr(w)?,
            Self::ContractData(v) => v.write_xdr(w)?,
            Self::ContractCode(v) => v.write_xdr(w)?,
            Self::ConfigSetting(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// EnvelopeType is an XDR Enum defines as:
//
//   enum EnvelopeType
//    {
//        ENVELOPE_TYPE_TX_V0 = 0,
//        ENVELOPE_TYPE_SCP = 1,
//        ENVELOPE_TYPE_TX = 2,
//        ENVELOPE_TYPE_AUTH = 3,
//        ENVELOPE_TYPE_SCPVALUE = 4,
//        ENVELOPE_TYPE_TX_FEE_BUMP = 5,
//        ENVELOPE_TYPE_OP_ID = 6,
//        ENVELOPE_TYPE_POOL_REVOKE_OP_ID = 7,
//        ENVELOPE_TYPE_CONTRACT_ID_FROM_ED25519 = 8,
//        ENVELOPE_TYPE_CONTRACT_ID_FROM_CONTRACT = 9,
//        ENVELOPE_TYPE_CONTRACT_ID_FROM_ASSET = 10,
//        ENVELOPE_TYPE_CONTRACT_ID_FROM_SOURCE_ACCOUNT = 11,
//        ENVELOPE_TYPE_CREATE_CONTRACT_ARGS = 12
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum EnvelopeType {
    TxV0 = 0,
    Scp = 1,
    Tx = 2,
    Auth = 3,
    Scpvalue = 4,
    TxFeeBump = 5,
    OpId = 6,
    PoolRevokeOpId = 7,
    ContractIdFromEd25519 = 8,
    ContractIdFromContract = 9,
    ContractIdFromAsset = 10,
    ContractIdFromSourceAccount = 11,
    CreateContractArgs = 12,
}

impl EnvelopeType {
    pub const VARIANTS: [EnvelopeType; 13] = [
        EnvelopeType::TxV0,
        EnvelopeType::Scp,
        EnvelopeType::Tx,
        EnvelopeType::Auth,
        EnvelopeType::Scpvalue,
        EnvelopeType::TxFeeBump,
        EnvelopeType::OpId,
        EnvelopeType::PoolRevokeOpId,
        EnvelopeType::ContractIdFromEd25519,
        EnvelopeType::ContractIdFromContract,
        EnvelopeType::ContractIdFromAsset,
        EnvelopeType::ContractIdFromSourceAccount,
        EnvelopeType::CreateContractArgs,
    ];
    pub const VARIANTS_STR: [&'static str; 13] = [
        "TxV0",
        "Scp",
        "Tx",
        "Auth",
        "Scpvalue",
        "TxFeeBump",
        "OpId",
        "PoolRevokeOpId",
        "ContractIdFromEd25519",
        "ContractIdFromContract",
        "ContractIdFromAsset",
        "ContractIdFromSourceAccount",
        "CreateContractArgs",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::TxV0 => "TxV0",
            Self::Scp => "Scp",
            Self::Tx => "Tx",
            Self::Auth => "Auth",
            Self::Scpvalue => "Scpvalue",
            Self::TxFeeBump => "TxFeeBump",
            Self::OpId => "OpId",
            Self::PoolRevokeOpId => "PoolRevokeOpId",
            Self::ContractIdFromEd25519 => "ContractIdFromEd25519",
            Self::ContractIdFromContract => "ContractIdFromContract",
            Self::ContractIdFromAsset => "ContractIdFromAsset",
            Self::ContractIdFromSourceAccount => "ContractIdFromSourceAccount",
            Self::CreateContractArgs => "CreateContractArgs",
        }
    }

    #[must_use]
    pub const fn variants() -> [EnvelopeType; 13] {
        Self::VARIANTS
    }
}

impl Name for EnvelopeType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<EnvelopeType> for EnvelopeType {
    fn variants() -> slice::Iter<'static, EnvelopeType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for EnvelopeType {}

impl fmt::Display for EnvelopeType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for EnvelopeType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => EnvelopeType::TxV0,
            1 => EnvelopeType::Scp,
            2 => EnvelopeType::Tx,
            3 => EnvelopeType::Auth,
            4 => EnvelopeType::Scpvalue,
            5 => EnvelopeType::TxFeeBump,
            6 => EnvelopeType::OpId,
            7 => EnvelopeType::PoolRevokeOpId,
            8 => EnvelopeType::ContractIdFromEd25519,
            9 => EnvelopeType::ContractIdFromContract,
            10 => EnvelopeType::ContractIdFromAsset,
            11 => EnvelopeType::ContractIdFromSourceAccount,
            12 => EnvelopeType::CreateContractArgs,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<EnvelopeType> for i32 {
    #[must_use]
    fn from(e: EnvelopeType) -> Self {
        e as Self
    }
}

impl ReadXdr for EnvelopeType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for EnvelopeType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// UpgradeType is an XDR Typedef defines as:
//
//   typedef opaque UpgradeType<128>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct UpgradeType(pub BytesM<128>);

impl From<UpgradeType> for BytesM<128> {
    #[must_use]
    fn from(x: UpgradeType) -> Self {
        x.0
    }
}

impl From<BytesM<128>> for UpgradeType {
    #[must_use]
    fn from(x: BytesM<128>) -> Self {
        UpgradeType(x)
    }
}

impl AsRef<BytesM<128>> for UpgradeType {
    #[must_use]
    fn as_ref(&self) -> &BytesM<128> {
        &self.0
    }
}

impl ReadXdr for UpgradeType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = BytesM::<128>::read_xdr(r)?;
        let v = UpgradeType(i);
        Ok(v)
    }
}

impl WriteXdr for UpgradeType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for UpgradeType {
    type Target = BytesM<128>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<UpgradeType> for Vec<u8> {
    #[must_use]
    fn from(x: UpgradeType) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<u8>> for UpgradeType {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        Ok(UpgradeType(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for UpgradeType {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        Ok(UpgradeType(x.try_into()?))
    }
}

impl AsRef<Vec<u8>> for UpgradeType {
    #[must_use]
    fn as_ref(&self) -> &Vec<u8> {
        &self.0 .0
    }
}

impl AsRef<[u8]> for UpgradeType {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        self.0 .0
    }
}

// StellarValueType is an XDR Enum defines as:
//
//   enum StellarValueType
//    {
//        STELLAR_VALUE_BASIC = 0,
//        STELLAR_VALUE_SIGNED = 1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum StellarValueType {
    Basic = 0,
    Signed = 1,
}

impl StellarValueType {
    pub const VARIANTS: [StellarValueType; 2] = [StellarValueType::Basic, StellarValueType::Signed];
    pub const VARIANTS_STR: [&'static str; 2] = ["Basic", "Signed"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Basic => "Basic",
            Self::Signed => "Signed",
        }
    }

    #[must_use]
    pub const fn variants() -> [StellarValueType; 2] {
        Self::VARIANTS
    }
}

impl Name for StellarValueType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<StellarValueType> for StellarValueType {
    fn variants() -> slice::Iter<'static, StellarValueType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for StellarValueType {}

impl fmt::Display for StellarValueType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for StellarValueType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => StellarValueType::Basic,
            1 => StellarValueType::Signed,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<StellarValueType> for i32 {
    #[must_use]
    fn from(e: StellarValueType) -> Self {
        e as Self
    }
}

impl ReadXdr for StellarValueType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for StellarValueType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// LedgerCloseValueSignature is an XDR Struct defines as:
//
//   struct LedgerCloseValueSignature
//    {
//        NodeID nodeID;       // which node introduced the value
//        Signature signature; // nodeID's signature
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerCloseValueSignature {
    pub node_id: NodeId,
    pub signature: Signature,
}

impl ReadXdr for LedgerCloseValueSignature {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            node_id: NodeId::read_xdr(r)?,
            signature: Signature::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerCloseValueSignature {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.node_id.write_xdr(w)?;
        self.signature.write_xdr(w)?;
        Ok(())
    }
}

// StellarValueExt is an XDR NestedUnion defines as:
//
//   union switch (StellarValueType v)
//        {
//        case STELLAR_VALUE_BASIC:
//            void;
//        case STELLAR_VALUE_SIGNED:
//            LedgerCloseValueSignature lcValueSignature;
//        }
//
// union with discriminant StellarValueType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum StellarValueExt {
    Basic,
    Signed(LedgerCloseValueSignature),
}

impl StellarValueExt {
    pub const VARIANTS: [StellarValueType; 2] = [StellarValueType::Basic, StellarValueType::Signed];
    pub const VARIANTS_STR: [&'static str; 2] = ["Basic", "Signed"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Basic => "Basic",
            Self::Signed(_) => "Signed",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> StellarValueType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Basic => StellarValueType::Basic,
            Self::Signed(_) => StellarValueType::Signed,
        }
    }

    #[must_use]
    pub const fn variants() -> [StellarValueType; 2] {
        Self::VARIANTS
    }
}

impl Name for StellarValueExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<StellarValueType> for StellarValueExt {
    #[must_use]
    fn discriminant(&self) -> StellarValueType {
        Self::discriminant(self)
    }
}

impl Variants<StellarValueType> for StellarValueExt {
    fn variants() -> slice::Iter<'static, StellarValueType> {
        Self::VARIANTS.iter()
    }
}

impl Union<StellarValueType> for StellarValueExt {}

impl ReadXdr for StellarValueExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: StellarValueType = <StellarValueType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            StellarValueType::Basic => Self::Basic,
            StellarValueType::Signed => Self::Signed(LedgerCloseValueSignature::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for StellarValueExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Basic => ().write_xdr(w)?,
            Self::Signed(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// StellarValue is an XDR Struct defines as:
//
//   struct StellarValue
//    {
//        Hash txSetHash;      // transaction set to apply to previous ledger
//        TimePoint closeTime; // network close time
//
//        // upgrades to apply to the previous ledger (usually empty)
//        // this is a vector of encoded 'LedgerUpgrade' so that nodes can drop
//        // unknown steps during consensus if needed.
//        // see notes below on 'LedgerUpgrade' for more detail
//        // max size is dictated by number of upgrade types (+ room for future)
//        UpgradeType upgrades<6>;
//
//        // reserved for future use
//        union switch (StellarValueType v)
//        {
//        case STELLAR_VALUE_BASIC:
//            void;
//        case STELLAR_VALUE_SIGNED:
//            LedgerCloseValueSignature lcValueSignature;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct StellarValue {
    pub tx_set_hash: Hash,
    pub close_time: TimePoint,
    pub upgrades: VecM<UpgradeType, 6>,
    pub ext: StellarValueExt,
}

impl ReadXdr for StellarValue {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            tx_set_hash: Hash::read_xdr(r)?,
            close_time: TimePoint::read_xdr(r)?,
            upgrades: VecM::<UpgradeType, 6>::read_xdr(r)?,
            ext: StellarValueExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for StellarValue {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.tx_set_hash.write_xdr(w)?;
        self.close_time.write_xdr(w)?;
        self.upgrades.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// MaskLedgerHeaderFlags is an XDR Const defines as:
//
//   const MASK_LEDGER_HEADER_FLAGS = 0x7F;
//
pub const MASK_LEDGER_HEADER_FLAGS: u64 = 0x7F;

// LedgerHeaderFlags is an XDR Enum defines as:
//
//   enum LedgerHeaderFlags
//    {
//        DISABLE_LIQUIDITY_POOL_TRADING_FLAG = 0x1,
//        DISABLE_LIQUIDITY_POOL_DEPOSIT_FLAG = 0x2,
//        DISABLE_LIQUIDITY_POOL_WITHDRAWAL_FLAG = 0x4,
//        DISABLE_CONTRACT_CREATE = 0x8,
//        DISABLE_CONTRACT_UPDATE = 0x10,
//        DISABLE_CONTRACT_REMOVE = 0x20,
//        DISABLE_CONTRACT_INVOKE = 0x40
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum LedgerHeaderFlags {
    LiquidityPoolTradingFlag = 1,
    LiquidityPoolDepositFlag = 2,
    LiquidityPoolWithdrawalFlag = 4,
    ContractCreate = 8,
    ContractUpdate = 16,
    ContractRemove = 32,
    ContractInvoke = 64,
}

impl LedgerHeaderFlags {
    pub const VARIANTS: [LedgerHeaderFlags; 7] = [
        LedgerHeaderFlags::LiquidityPoolTradingFlag,
        LedgerHeaderFlags::LiquidityPoolDepositFlag,
        LedgerHeaderFlags::LiquidityPoolWithdrawalFlag,
        LedgerHeaderFlags::ContractCreate,
        LedgerHeaderFlags::ContractUpdate,
        LedgerHeaderFlags::ContractRemove,
        LedgerHeaderFlags::ContractInvoke,
    ];
    pub const VARIANTS_STR: [&'static str; 7] = [
        "LiquidityPoolTradingFlag",
        "LiquidityPoolDepositFlag",
        "LiquidityPoolWithdrawalFlag",
        "ContractCreate",
        "ContractUpdate",
        "ContractRemove",
        "ContractInvoke",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::LiquidityPoolTradingFlag => "LiquidityPoolTradingFlag",
            Self::LiquidityPoolDepositFlag => "LiquidityPoolDepositFlag",
            Self::LiquidityPoolWithdrawalFlag => "LiquidityPoolWithdrawalFlag",
            Self::ContractCreate => "ContractCreate",
            Self::ContractUpdate => "ContractUpdate",
            Self::ContractRemove => "ContractRemove",
            Self::ContractInvoke => "ContractInvoke",
        }
    }

    #[must_use]
    pub const fn variants() -> [LedgerHeaderFlags; 7] {
        Self::VARIANTS
    }
}

impl Name for LedgerHeaderFlags {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<LedgerHeaderFlags> for LedgerHeaderFlags {
    fn variants() -> slice::Iter<'static, LedgerHeaderFlags> {
        Self::VARIANTS.iter()
    }
}

impl Enum for LedgerHeaderFlags {}

impl fmt::Display for LedgerHeaderFlags {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for LedgerHeaderFlags {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            1 => LedgerHeaderFlags::LiquidityPoolTradingFlag,
            2 => LedgerHeaderFlags::LiquidityPoolDepositFlag,
            4 => LedgerHeaderFlags::LiquidityPoolWithdrawalFlag,
            8 => LedgerHeaderFlags::ContractCreate,
            16 => LedgerHeaderFlags::ContractUpdate,
            32 => LedgerHeaderFlags::ContractRemove,
            64 => LedgerHeaderFlags::ContractInvoke,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<LedgerHeaderFlags> for i32 {
    #[must_use]
    fn from(e: LedgerHeaderFlags) -> Self {
        e as Self
    }
}

impl ReadXdr for LedgerHeaderFlags {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for LedgerHeaderFlags {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// LedgerHeaderExtensionV1Ext is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerHeaderExtensionV1Ext {
    V0,
}

impl LedgerHeaderExtensionV1Ext {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for LedgerHeaderExtensionV1Ext {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for LedgerHeaderExtensionV1Ext {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for LedgerHeaderExtensionV1Ext {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for LedgerHeaderExtensionV1Ext {}

impl ReadXdr for LedgerHeaderExtensionV1Ext {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerHeaderExtensionV1Ext {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// LedgerHeaderExtensionV1 is an XDR Struct defines as:
//
//   struct LedgerHeaderExtensionV1
//    {
//        uint32 flags; // LedgerHeaderFlags
//
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerHeaderExtensionV1 {
    pub flags: u32,
    pub ext: LedgerHeaderExtensionV1Ext,
}

impl ReadXdr for LedgerHeaderExtensionV1 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            flags: u32::read_xdr(r)?,
            ext: LedgerHeaderExtensionV1Ext::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerHeaderExtensionV1 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.flags.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// LedgerHeaderExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            LedgerHeaderExtensionV1 v1;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerHeaderExt {
    V0,
    V1(LedgerHeaderExtensionV1),
}

impl LedgerHeaderExt {
    pub const VARIANTS: [i32; 2] = [0, 1];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V1"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::V1(_) => "V1",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
            Self::V1(_) => 1,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for LedgerHeaderExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for LedgerHeaderExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for LedgerHeaderExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for LedgerHeaderExt {}

impl ReadXdr for LedgerHeaderExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            1 => Self::V1(LedgerHeaderExtensionV1::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerHeaderExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// LedgerHeader is an XDR Struct defines as:
//
//   struct LedgerHeader
//    {
//        uint32 ledgerVersion;    // the protocol version of the ledger
//        Hash previousLedgerHash; // hash of the previous ledger header
//        StellarValue scpValue;   // what consensus agreed to
//        Hash txSetResultHash;    // the TransactionResultSet that led to this ledger
//        Hash bucketListHash;     // hash of the ledger state
//
//        uint32 ledgerSeq; // sequence number of this ledger
//
//        int64 totalCoins; // total number of stroops in existence.
//                          // 10,000,000 stroops in 1 XLM
//
//        int64 feePool;       // fees burned since last inflation run
//        uint32 inflationSeq; // inflation sequence number
//
//        uint64 idPool; // last used global ID, used for generating objects
//
//        uint32 baseFee;     // base fee per operation in stroops
//        uint32 baseReserve; // account base reserve in stroops
//
//        uint32 maxTxSetSize; // maximum size a transaction set can be
//
//        Hash skipList[4]; // hashes of ledgers in the past. allows you to jump back
//                          // in time without walking the chain back ledger by ledger
//                          // each slot contains the oldest ledger that is mod of
//                          // either 50  5000  50000 or 500000 depending on index
//                          // skipList[0] mod(50), skipList[1] mod(5000), etc
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            LedgerHeaderExtensionV1 v1;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerHeader {
    pub ledger_version: u32,
    pub previous_ledger_hash: Hash,
    pub scp_value: StellarValue,
    pub tx_set_result_hash: Hash,
    pub bucket_list_hash: Hash,
    pub ledger_seq: u32,
    pub total_coins: i64,
    pub fee_pool: i64,
    pub inflation_seq: u32,
    pub id_pool: u64,
    pub base_fee: u32,
    pub base_reserve: u32,
    pub max_tx_set_size: u32,
    pub skip_list: [Hash; 4],
    pub ext: LedgerHeaderExt,
}

impl ReadXdr for LedgerHeader {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_version: u32::read_xdr(r)?,
            previous_ledger_hash: Hash::read_xdr(r)?,
            scp_value: StellarValue::read_xdr(r)?,
            tx_set_result_hash: Hash::read_xdr(r)?,
            bucket_list_hash: Hash::read_xdr(r)?,
            ledger_seq: u32::read_xdr(r)?,
            total_coins: i64::read_xdr(r)?,
            fee_pool: i64::read_xdr(r)?,
            inflation_seq: u32::read_xdr(r)?,
            id_pool: u64::read_xdr(r)?,
            base_fee: u32::read_xdr(r)?,
            base_reserve: u32::read_xdr(r)?,
            max_tx_set_size: u32::read_xdr(r)?,
            skip_list: <[Hash; 4]>::read_xdr(r)?,
            ext: LedgerHeaderExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerHeader {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_version.write_xdr(w)?;
        self.previous_ledger_hash.write_xdr(w)?;
        self.scp_value.write_xdr(w)?;
        self.tx_set_result_hash.write_xdr(w)?;
        self.bucket_list_hash.write_xdr(w)?;
        self.ledger_seq.write_xdr(w)?;
        self.total_coins.write_xdr(w)?;
        self.fee_pool.write_xdr(w)?;
        self.inflation_seq.write_xdr(w)?;
        self.id_pool.write_xdr(w)?;
        self.base_fee.write_xdr(w)?;
        self.base_reserve.write_xdr(w)?;
        self.max_tx_set_size.write_xdr(w)?;
        self.skip_list.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// LedgerUpgradeType is an XDR Enum defines as:
//
//   enum LedgerUpgradeType
//    {
//        LEDGER_UPGRADE_VERSION = 1,
//        LEDGER_UPGRADE_BASE_FEE = 2,
//        LEDGER_UPGRADE_MAX_TX_SET_SIZE = 3,
//        LEDGER_UPGRADE_BASE_RESERVE = 4,
//        LEDGER_UPGRADE_FLAGS = 5,
//        LEDGER_UPGRADE_CONFIG = 6
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum LedgerUpgradeType {
    Version = 1,
    BaseFee = 2,
    MaxTxSetSize = 3,
    BaseReserve = 4,
    Flags = 5,
    Config = 6,
}

impl LedgerUpgradeType {
    pub const VARIANTS: [LedgerUpgradeType; 6] = [
        LedgerUpgradeType::Version,
        LedgerUpgradeType::BaseFee,
        LedgerUpgradeType::MaxTxSetSize,
        LedgerUpgradeType::BaseReserve,
        LedgerUpgradeType::Flags,
        LedgerUpgradeType::Config,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Version",
        "BaseFee",
        "MaxTxSetSize",
        "BaseReserve",
        "Flags",
        "Config",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Version => "Version",
            Self::BaseFee => "BaseFee",
            Self::MaxTxSetSize => "MaxTxSetSize",
            Self::BaseReserve => "BaseReserve",
            Self::Flags => "Flags",
            Self::Config => "Config",
        }
    }

    #[must_use]
    pub const fn variants() -> [LedgerUpgradeType; 6] {
        Self::VARIANTS
    }
}

impl Name for LedgerUpgradeType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<LedgerUpgradeType> for LedgerUpgradeType {
    fn variants() -> slice::Iter<'static, LedgerUpgradeType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for LedgerUpgradeType {}

impl fmt::Display for LedgerUpgradeType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for LedgerUpgradeType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            1 => LedgerUpgradeType::Version,
            2 => LedgerUpgradeType::BaseFee,
            3 => LedgerUpgradeType::MaxTxSetSize,
            4 => LedgerUpgradeType::BaseReserve,
            5 => LedgerUpgradeType::Flags,
            6 => LedgerUpgradeType::Config,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<LedgerUpgradeType> for i32 {
    #[must_use]
    fn from(e: LedgerUpgradeType) -> Self {
        e as Self
    }
}

impl ReadXdr for LedgerUpgradeType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for LedgerUpgradeType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// LedgerUpgradeConfigSetting is an XDR NestedStruct defines as:
//
//   struct
//        {
//            ConfigSettingID id; // id to update
//            ConfigSetting setting; // new value
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerUpgradeConfigSetting {
    pub id: ConfigSettingId,
    pub setting: ConfigSetting,
}

impl ReadXdr for LedgerUpgradeConfigSetting {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            id: ConfigSettingId::read_xdr(r)?,
            setting: ConfigSetting::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerUpgradeConfigSetting {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.id.write_xdr(w)?;
        self.setting.write_xdr(w)?;
        Ok(())
    }
}

// LedgerUpgrade is an XDR Union defines as:
//
//   union LedgerUpgrade switch (LedgerUpgradeType type)
//    {
//    case LEDGER_UPGRADE_VERSION:
//        uint32 newLedgerVersion; // update ledgerVersion
//    case LEDGER_UPGRADE_BASE_FEE:
//        uint32 newBaseFee; // update baseFee
//    case LEDGER_UPGRADE_MAX_TX_SET_SIZE:
//        uint32 newMaxTxSetSize; // update maxTxSetSize
//    case LEDGER_UPGRADE_BASE_RESERVE:
//        uint32 newBaseReserve; // update baseReserve
//    case LEDGER_UPGRADE_FLAGS:
//        uint32 newFlags; // update flags
//    case LEDGER_UPGRADE_CONFIG:
//        struct
//        {
//            ConfigSettingID id; // id to update
//            ConfigSetting setting; // new value
//        } configSetting;
//    };
//
// union with discriminant LedgerUpgradeType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerUpgrade {
    Version(u32),
    BaseFee(u32),
    MaxTxSetSize(u32),
    BaseReserve(u32),
    Flags(u32),
    Config(LedgerUpgradeConfigSetting),
}

impl LedgerUpgrade {
    pub const VARIANTS: [LedgerUpgradeType; 6] = [
        LedgerUpgradeType::Version,
        LedgerUpgradeType::BaseFee,
        LedgerUpgradeType::MaxTxSetSize,
        LedgerUpgradeType::BaseReserve,
        LedgerUpgradeType::Flags,
        LedgerUpgradeType::Config,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Version",
        "BaseFee",
        "MaxTxSetSize",
        "BaseReserve",
        "Flags",
        "Config",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Version(_) => "Version",
            Self::BaseFee(_) => "BaseFee",
            Self::MaxTxSetSize(_) => "MaxTxSetSize",
            Self::BaseReserve(_) => "BaseReserve",
            Self::Flags(_) => "Flags",
            Self::Config(_) => "Config",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> LedgerUpgradeType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Version(_) => LedgerUpgradeType::Version,
            Self::BaseFee(_) => LedgerUpgradeType::BaseFee,
            Self::MaxTxSetSize(_) => LedgerUpgradeType::MaxTxSetSize,
            Self::BaseReserve(_) => LedgerUpgradeType::BaseReserve,
            Self::Flags(_) => LedgerUpgradeType::Flags,
            Self::Config(_) => LedgerUpgradeType::Config,
        }
    }

    #[must_use]
    pub const fn variants() -> [LedgerUpgradeType; 6] {
        Self::VARIANTS
    }
}

impl Name for LedgerUpgrade {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<LedgerUpgradeType> for LedgerUpgrade {
    #[must_use]
    fn discriminant(&self) -> LedgerUpgradeType {
        Self::discriminant(self)
    }
}

impl Variants<LedgerUpgradeType> for LedgerUpgrade {
    fn variants() -> slice::Iter<'static, LedgerUpgradeType> {
        Self::VARIANTS.iter()
    }
}

impl Union<LedgerUpgradeType> for LedgerUpgrade {}

impl ReadXdr for LedgerUpgrade {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: LedgerUpgradeType = <LedgerUpgradeType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            LedgerUpgradeType::Version => Self::Version(u32::read_xdr(r)?),
            LedgerUpgradeType::BaseFee => Self::BaseFee(u32::read_xdr(r)?),
            LedgerUpgradeType::MaxTxSetSize => Self::MaxTxSetSize(u32::read_xdr(r)?),
            LedgerUpgradeType::BaseReserve => Self::BaseReserve(u32::read_xdr(r)?),
            LedgerUpgradeType::Flags => Self::Flags(u32::read_xdr(r)?),
            LedgerUpgradeType::Config => Self::Config(LedgerUpgradeConfigSetting::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerUpgrade {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Version(v) => v.write_xdr(w)?,
            Self::BaseFee(v) => v.write_xdr(w)?,
            Self::MaxTxSetSize(v) => v.write_xdr(w)?,
            Self::BaseReserve(v) => v.write_xdr(w)?,
            Self::Flags(v) => v.write_xdr(w)?,
            Self::Config(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// BucketEntryType is an XDR Enum defines as:
//
//   enum BucketEntryType
//    {
//        METAENTRY =
//            -1, // At-and-after protocol 11: bucket metadata, should come first.
//        LIVEENTRY = 0, // Before protocol 11: created-or-updated;
//                       // At-and-after protocol 11: only updated.
//        DEADENTRY = 1,
//        INITENTRY = 2 // At-and-after protocol 11: only created.
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum BucketEntryType {
    Metaentry = -1,
    Liveentry = 0,
    Deadentry = 1,
    Initentry = 2,
}

impl BucketEntryType {
    pub const VARIANTS: [BucketEntryType; 4] = [
        BucketEntryType::Metaentry,
        BucketEntryType::Liveentry,
        BucketEntryType::Deadentry,
        BucketEntryType::Initentry,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Metaentry", "Liveentry", "Deadentry", "Initentry"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Metaentry => "Metaentry",
            Self::Liveentry => "Liveentry",
            Self::Deadentry => "Deadentry",
            Self::Initentry => "Initentry",
        }
    }

    #[must_use]
    pub const fn variants() -> [BucketEntryType; 4] {
        Self::VARIANTS
    }
}

impl Name for BucketEntryType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<BucketEntryType> for BucketEntryType {
    fn variants() -> slice::Iter<'static, BucketEntryType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for BucketEntryType {}

impl fmt::Display for BucketEntryType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for BucketEntryType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            -1 => BucketEntryType::Metaentry,
            0 => BucketEntryType::Liveentry,
            1 => BucketEntryType::Deadentry,
            2 => BucketEntryType::Initentry,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<BucketEntryType> for i32 {
    #[must_use]
    fn from(e: BucketEntryType) -> Self {
        e as Self
    }
}

impl ReadXdr for BucketEntryType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for BucketEntryType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// BucketMetadataExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum BucketMetadataExt {
    V0,
}

impl BucketMetadataExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for BucketMetadataExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for BucketMetadataExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for BucketMetadataExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for BucketMetadataExt {}

impl ReadXdr for BucketMetadataExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for BucketMetadataExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// BucketMetadata is an XDR Struct defines as:
//
//   struct BucketMetadata
//    {
//        // Indicates the protocol version used to create / merge this bucket.
//        uint32 ledgerVersion;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct BucketMetadata {
    pub ledger_version: u32,
    pub ext: BucketMetadataExt,
}

impl ReadXdr for BucketMetadata {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_version: u32::read_xdr(r)?,
            ext: BucketMetadataExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for BucketMetadata {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_version.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// BucketEntry is an XDR Union defines as:
//
//   union BucketEntry switch (BucketEntryType type)
//    {
//    case LIVEENTRY:
//    case INITENTRY:
//        LedgerEntry liveEntry;
//
//    case DEADENTRY:
//        LedgerKey deadEntry;
//    case METAENTRY:
//        BucketMetadata metaEntry;
//    };
//
// union with discriminant BucketEntryType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum BucketEntry {
    Liveentry(LedgerEntry),
    Initentry(LedgerEntry),
    Deadentry(LedgerKey),
    Metaentry(BucketMetadata),
}

impl BucketEntry {
    pub const VARIANTS: [BucketEntryType; 4] = [
        BucketEntryType::Liveentry,
        BucketEntryType::Initentry,
        BucketEntryType::Deadentry,
        BucketEntryType::Metaentry,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Liveentry", "Initentry", "Deadentry", "Metaentry"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Liveentry(_) => "Liveentry",
            Self::Initentry(_) => "Initentry",
            Self::Deadentry(_) => "Deadentry",
            Self::Metaentry(_) => "Metaentry",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> BucketEntryType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Liveentry(_) => BucketEntryType::Liveentry,
            Self::Initentry(_) => BucketEntryType::Initentry,
            Self::Deadentry(_) => BucketEntryType::Deadentry,
            Self::Metaentry(_) => BucketEntryType::Metaentry,
        }
    }

    #[must_use]
    pub const fn variants() -> [BucketEntryType; 4] {
        Self::VARIANTS
    }
}

impl Name for BucketEntry {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<BucketEntryType> for BucketEntry {
    #[must_use]
    fn discriminant(&self) -> BucketEntryType {
        Self::discriminant(self)
    }
}

impl Variants<BucketEntryType> for BucketEntry {
    fn variants() -> slice::Iter<'static, BucketEntryType> {
        Self::VARIANTS.iter()
    }
}

impl Union<BucketEntryType> for BucketEntry {}

impl ReadXdr for BucketEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: BucketEntryType = <BucketEntryType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            BucketEntryType::Liveentry => Self::Liveentry(LedgerEntry::read_xdr(r)?),
            BucketEntryType::Initentry => Self::Initentry(LedgerEntry::read_xdr(r)?),
            BucketEntryType::Deadentry => Self::Deadentry(LedgerKey::read_xdr(r)?),
            BucketEntryType::Metaentry => Self::Metaentry(BucketMetadata::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for BucketEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Liveentry(v) => v.write_xdr(w)?,
            Self::Initentry(v) => v.write_xdr(w)?,
            Self::Deadentry(v) => v.write_xdr(w)?,
            Self::Metaentry(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TxSetComponentType is an XDR Enum defines as:
//
//   enum TxSetComponentType
//    {
//      // txs with effective fee <= bid derived from a base fee (if any).
//      // If base fee is not specified, no discount is applied.
//      TXSET_COMP_TXS_MAYBE_DISCOUNTED_FEE = 0
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum TxSetComponentType {
    TxsetCompTxsMaybeDiscountedFee = 0,
}

impl TxSetComponentType {
    pub const VARIANTS: [TxSetComponentType; 1] =
        [TxSetComponentType::TxsetCompTxsMaybeDiscountedFee];
    pub const VARIANTS_STR: [&'static str; 1] = ["TxsetCompTxsMaybeDiscountedFee"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::TxsetCompTxsMaybeDiscountedFee => "TxsetCompTxsMaybeDiscountedFee",
        }
    }

    #[must_use]
    pub const fn variants() -> [TxSetComponentType; 1] {
        Self::VARIANTS
    }
}

impl Name for TxSetComponentType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<TxSetComponentType> for TxSetComponentType {
    fn variants() -> slice::Iter<'static, TxSetComponentType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for TxSetComponentType {}

impl fmt::Display for TxSetComponentType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for TxSetComponentType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => TxSetComponentType::TxsetCompTxsMaybeDiscountedFee,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<TxSetComponentType> for i32 {
    #[must_use]
    fn from(e: TxSetComponentType) -> Self {
        e as Self
    }
}

impl ReadXdr for TxSetComponentType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for TxSetComponentType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// TxSetComponentTxsMaybeDiscountedFee is an XDR NestedStruct defines as:
//
//   struct
//      {
//        int64* baseFee;
//        TransactionEnvelope txs<>;
//      }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TxSetComponentTxsMaybeDiscountedFee {
    pub base_fee: Option<i64>,
    pub txs: VecM<TransactionEnvelope>,
}

impl ReadXdr for TxSetComponentTxsMaybeDiscountedFee {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            base_fee: Option::<i64>::read_xdr(r)?,
            txs: VecM::<TransactionEnvelope>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TxSetComponentTxsMaybeDiscountedFee {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.base_fee.write_xdr(w)?;
        self.txs.write_xdr(w)?;
        Ok(())
    }
}

// TxSetComponent is an XDR Union defines as:
//
//   union TxSetComponent switch (TxSetComponentType type)
//    {
//    case TXSET_COMP_TXS_MAYBE_DISCOUNTED_FEE:
//      struct
//      {
//        int64* baseFee;
//        TransactionEnvelope txs<>;
//      } txsMaybeDiscountedFee;
//    };
//
// union with discriminant TxSetComponentType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TxSetComponent {
    TxsetCompTxsMaybeDiscountedFee(TxSetComponentTxsMaybeDiscountedFee),
}

impl TxSetComponent {
    pub const VARIANTS: [TxSetComponentType; 1] =
        [TxSetComponentType::TxsetCompTxsMaybeDiscountedFee];
    pub const VARIANTS_STR: [&'static str; 1] = ["TxsetCompTxsMaybeDiscountedFee"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::TxsetCompTxsMaybeDiscountedFee(_) => "TxsetCompTxsMaybeDiscountedFee",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> TxSetComponentType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::TxsetCompTxsMaybeDiscountedFee(_) => {
                TxSetComponentType::TxsetCompTxsMaybeDiscountedFee
            }
        }
    }

    #[must_use]
    pub const fn variants() -> [TxSetComponentType; 1] {
        Self::VARIANTS
    }
}

impl Name for TxSetComponent {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<TxSetComponentType> for TxSetComponent {
    #[must_use]
    fn discriminant(&self) -> TxSetComponentType {
        Self::discriminant(self)
    }
}

impl Variants<TxSetComponentType> for TxSetComponent {
    fn variants() -> slice::Iter<'static, TxSetComponentType> {
        Self::VARIANTS.iter()
    }
}

impl Union<TxSetComponentType> for TxSetComponent {}

impl ReadXdr for TxSetComponent {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: TxSetComponentType = <TxSetComponentType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            TxSetComponentType::TxsetCompTxsMaybeDiscountedFee => {
                Self::TxsetCompTxsMaybeDiscountedFee(TxSetComponentTxsMaybeDiscountedFee::read_xdr(
                    r,
                )?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TxSetComponent {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::TxsetCompTxsMaybeDiscountedFee(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionPhase is an XDR Union defines as:
//
//   union TransactionPhase switch (int v)
//    {
//    case 0:
//        TxSetComponent v0Components<>;
//    };
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionPhase {
    V0(VecM<TxSetComponent>),
}

impl TransactionPhase {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0(_) => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(_) => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for TransactionPhase {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TransactionPhase {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TransactionPhase {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TransactionPhase {}

impl ReadXdr for TransactionPhase {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0(VecM::<TxSetComponent>::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionPhase {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionSet is an XDR Struct defines as:
//
//   struct TransactionSet
//    {
//        Hash previousLedgerHash;
//        TransactionEnvelope txs<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionSet {
    pub previous_ledger_hash: Hash,
    pub txs: VecM<TransactionEnvelope>,
}

impl ReadXdr for TransactionSet {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            previous_ledger_hash: Hash::read_xdr(r)?,
            txs: VecM::<TransactionEnvelope>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionSet {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.previous_ledger_hash.write_xdr(w)?;
        self.txs.write_xdr(w)?;
        Ok(())
    }
}

// TransactionSetV1 is an XDR Struct defines as:
//
//   struct TransactionSetV1
//    {
//        Hash previousLedgerHash;
//        TransactionPhase phases<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionSetV1 {
    pub previous_ledger_hash: Hash,
    pub phases: VecM<TransactionPhase>,
}

impl ReadXdr for TransactionSetV1 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            previous_ledger_hash: Hash::read_xdr(r)?,
            phases: VecM::<TransactionPhase>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionSetV1 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.previous_ledger_hash.write_xdr(w)?;
        self.phases.write_xdr(w)?;
        Ok(())
    }
}

// GeneralizedTransactionSet is an XDR Union defines as:
//
//   union GeneralizedTransactionSet switch (int v)
//    {
//    // We consider the legacy TransactionSet to be v0.
//    case 1:
//        TransactionSetV1 v1TxSet;
//    };
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum GeneralizedTransactionSet {
    V1(TransactionSetV1),
}

impl GeneralizedTransactionSet {
    pub const VARIANTS: [i32; 1] = [1];
    pub const VARIANTS_STR: [&'static str; 1] = ["V1"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V1(_) => "V1",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V1(_) => 1,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for GeneralizedTransactionSet {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for GeneralizedTransactionSet {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for GeneralizedTransactionSet {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for GeneralizedTransactionSet {}

impl ReadXdr for GeneralizedTransactionSet {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            1 => Self::V1(TransactionSetV1::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for GeneralizedTransactionSet {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V1(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionResultPair is an XDR Struct defines as:
//
//   struct TransactionResultPair
//    {
//        Hash transactionHash;
//        TransactionResult result; // result for the transaction
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionResultPair {
    pub transaction_hash: Hash,
    pub result: TransactionResult,
}

impl ReadXdr for TransactionResultPair {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            transaction_hash: Hash::read_xdr(r)?,
            result: TransactionResult::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionResultPair {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.transaction_hash.write_xdr(w)?;
        self.result.write_xdr(w)?;
        Ok(())
    }
}

// TransactionResultSet is an XDR Struct defines as:
//
//   struct TransactionResultSet
//    {
//        TransactionResultPair results<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionResultSet {
    pub results: VecM<TransactionResultPair>,
}

impl ReadXdr for TransactionResultSet {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            results: VecM::<TransactionResultPair>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionResultSet {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.results.write_xdr(w)?;
        Ok(())
    }
}

// TransactionHistoryEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            GeneralizedTransactionSet generalizedTxSet;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionHistoryEntryExt {
    V0,
    V1(GeneralizedTransactionSet),
}

impl TransactionHistoryEntryExt {
    pub const VARIANTS: [i32; 2] = [0, 1];
    pub const VARIANTS_STR: [&'static str; 2] = ["V0", "V1"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::V1(_) => "V1",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
            Self::V1(_) => 1,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 2] {
        Self::VARIANTS
    }
}

impl Name for TransactionHistoryEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TransactionHistoryEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TransactionHistoryEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TransactionHistoryEntryExt {}

impl ReadXdr for TransactionHistoryEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            1 => Self::V1(GeneralizedTransactionSet::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionHistoryEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionHistoryEntry is an XDR Struct defines as:
//
//   struct TransactionHistoryEntry
//    {
//        uint32 ledgerSeq;
//        TransactionSet txSet;
//
//        // when v != 0, txSet must be empty
//        union switch (int v)
//        {
//        case 0:
//            void;
//        case 1:
//            GeneralizedTransactionSet generalizedTxSet;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionHistoryEntry {
    pub ledger_seq: u32,
    pub tx_set: TransactionSet,
    pub ext: TransactionHistoryEntryExt,
}

impl ReadXdr for TransactionHistoryEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_seq: u32::read_xdr(r)?,
            tx_set: TransactionSet::read_xdr(r)?,
            ext: TransactionHistoryEntryExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionHistoryEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_seq.write_xdr(w)?;
        self.tx_set.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// TransactionHistoryResultEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionHistoryResultEntryExt {
    V0,
}

impl TransactionHistoryResultEntryExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for TransactionHistoryResultEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TransactionHistoryResultEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TransactionHistoryResultEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TransactionHistoryResultEntryExt {}

impl ReadXdr for TransactionHistoryResultEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionHistoryResultEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionHistoryResultEntry is an XDR Struct defines as:
//
//   struct TransactionHistoryResultEntry
//    {
//        uint32 ledgerSeq;
//        TransactionResultSet txResultSet;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionHistoryResultEntry {
    pub ledger_seq: u32,
    pub tx_result_set: TransactionResultSet,
    pub ext: TransactionHistoryResultEntryExt,
}

impl ReadXdr for TransactionHistoryResultEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_seq: u32::read_xdr(r)?,
            tx_result_set: TransactionResultSet::read_xdr(r)?,
            ext: TransactionHistoryResultEntryExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionHistoryResultEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_seq.write_xdr(w)?;
        self.tx_result_set.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// TransactionResultPairV2 is an XDR Struct defines as:
//
//   struct TransactionResultPairV2
//    {
//        Hash transactionHash;
//        Hash hashOfMetaHashes; // hash of hashes in TransactionMetaV3
//                               // TransactionResult is in the meta
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionResultPairV2 {
    pub transaction_hash: Hash,
    pub hash_of_meta_hashes: Hash,
}

impl ReadXdr for TransactionResultPairV2 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            transaction_hash: Hash::read_xdr(r)?,
            hash_of_meta_hashes: Hash::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionResultPairV2 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.transaction_hash.write_xdr(w)?;
        self.hash_of_meta_hashes.write_xdr(w)?;
        Ok(())
    }
}

// TransactionResultSetV2 is an XDR Struct defines as:
//
//   struct TransactionResultSetV2
//    {
//        TransactionResultPairV2 results<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionResultSetV2 {
    pub results: VecM<TransactionResultPairV2>,
}

impl ReadXdr for TransactionResultSetV2 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            results: VecM::<TransactionResultPairV2>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionResultSetV2 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.results.write_xdr(w)?;
        Ok(())
    }
}

// TransactionHistoryResultEntryV2Ext is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionHistoryResultEntryV2Ext {
    V0,
}

impl TransactionHistoryResultEntryV2Ext {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for TransactionHistoryResultEntryV2Ext {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TransactionHistoryResultEntryV2Ext {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TransactionHistoryResultEntryV2Ext {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TransactionHistoryResultEntryV2Ext {}

impl ReadXdr for TransactionHistoryResultEntryV2Ext {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionHistoryResultEntryV2Ext {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionHistoryResultEntryV2 is an XDR Struct defines as:
//
//   struct TransactionHistoryResultEntryV2
//    {
//        uint32 ledgerSeq;
//        TransactionResultSetV2 txResultSet;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionHistoryResultEntryV2 {
    pub ledger_seq: u32,
    pub tx_result_set: TransactionResultSetV2,
    pub ext: TransactionHistoryResultEntryV2Ext,
}

impl ReadXdr for TransactionHistoryResultEntryV2 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_seq: u32::read_xdr(r)?,
            tx_result_set: TransactionResultSetV2::read_xdr(r)?,
            ext: TransactionHistoryResultEntryV2Ext::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionHistoryResultEntryV2 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_seq.write_xdr(w)?;
        self.tx_result_set.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// LedgerHeaderHistoryEntryExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerHeaderHistoryEntryExt {
    V0,
}

impl LedgerHeaderHistoryEntryExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for LedgerHeaderHistoryEntryExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for LedgerHeaderHistoryEntryExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for LedgerHeaderHistoryEntryExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for LedgerHeaderHistoryEntryExt {}

impl ReadXdr for LedgerHeaderHistoryEntryExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerHeaderHistoryEntryExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// LedgerHeaderHistoryEntry is an XDR Struct defines as:
//
//   struct LedgerHeaderHistoryEntry
//    {
//        Hash hash;
//        LedgerHeader header;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerHeaderHistoryEntry {
    pub hash: Hash,
    pub header: LedgerHeader,
    pub ext: LedgerHeaderHistoryEntryExt,
}

impl ReadXdr for LedgerHeaderHistoryEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            hash: Hash::read_xdr(r)?,
            header: LedgerHeader::read_xdr(r)?,
            ext: LedgerHeaderHistoryEntryExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerHeaderHistoryEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.hash.write_xdr(w)?;
        self.header.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// LedgerScpMessages is an XDR Struct defines as:
//
//   struct LedgerSCPMessages
//    {
//        uint32 ledgerSeq;
//        SCPEnvelope messages<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerScpMessages {
    pub ledger_seq: u32,
    pub messages: VecM<ScpEnvelope>,
}

impl ReadXdr for LedgerScpMessages {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_seq: u32::read_xdr(r)?,
            messages: VecM::<ScpEnvelope>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerScpMessages {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_seq.write_xdr(w)?;
        self.messages.write_xdr(w)?;
        Ok(())
    }
}

// ScpHistoryEntryV0 is an XDR Struct defines as:
//
//   struct SCPHistoryEntryV0
//    {
//        SCPQuorumSet quorumSets<>; // additional quorum sets used by ledgerMessages
//        LedgerSCPMessages ledgerMessages;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ScpHistoryEntryV0 {
    pub quorum_sets: VecM<ScpQuorumSet>,
    pub ledger_messages: LedgerScpMessages,
}

impl ReadXdr for ScpHistoryEntryV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            quorum_sets: VecM::<ScpQuorumSet>::read_xdr(r)?,
            ledger_messages: LedgerScpMessages::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ScpHistoryEntryV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.quorum_sets.write_xdr(w)?;
        self.ledger_messages.write_xdr(w)?;
        Ok(())
    }
}

// ScpHistoryEntry is an XDR Union defines as:
//
//   union SCPHistoryEntry switch (int v)
//    {
//    case 0:
//        SCPHistoryEntryV0 v0;
//    };
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ScpHistoryEntry {
    V0(ScpHistoryEntryV0),
}

impl ScpHistoryEntry {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0(_) => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(_) => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for ScpHistoryEntry {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for ScpHistoryEntry {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for ScpHistoryEntry {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for ScpHistoryEntry {}

impl ReadXdr for ScpHistoryEntry {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0(ScpHistoryEntryV0::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ScpHistoryEntry {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// LedgerEntryChangeType is an XDR Enum defines as:
//
//   enum LedgerEntryChangeType
//    {
//        LEDGER_ENTRY_CREATED = 0, // entry was added to the ledger
//        LEDGER_ENTRY_UPDATED = 1, // entry was modified in the ledger
//        LEDGER_ENTRY_REMOVED = 2, // entry was removed from the ledger
//        LEDGER_ENTRY_STATE = 3    // value of the entry
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum LedgerEntryChangeType {
    Created = 0,
    Updated = 1,
    Removed = 2,
    State = 3,
}

impl LedgerEntryChangeType {
    pub const VARIANTS: [LedgerEntryChangeType; 4] = [
        LedgerEntryChangeType::Created,
        LedgerEntryChangeType::Updated,
        LedgerEntryChangeType::Removed,
        LedgerEntryChangeType::State,
    ];
    pub const VARIANTS_STR: [&'static str; 4] = ["Created", "Updated", "Removed", "State"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Created => "Created",
            Self::Updated => "Updated",
            Self::Removed => "Removed",
            Self::State => "State",
        }
    }

    #[must_use]
    pub const fn variants() -> [LedgerEntryChangeType; 4] {
        Self::VARIANTS
    }
}

impl Name for LedgerEntryChangeType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<LedgerEntryChangeType> for LedgerEntryChangeType {
    fn variants() -> slice::Iter<'static, LedgerEntryChangeType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for LedgerEntryChangeType {}

impl fmt::Display for LedgerEntryChangeType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for LedgerEntryChangeType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => LedgerEntryChangeType::Created,
            1 => LedgerEntryChangeType::Updated,
            2 => LedgerEntryChangeType::Removed,
            3 => LedgerEntryChangeType::State,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<LedgerEntryChangeType> for i32 {
    #[must_use]
    fn from(e: LedgerEntryChangeType) -> Self {
        e as Self
    }
}

impl ReadXdr for LedgerEntryChangeType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for LedgerEntryChangeType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// LedgerEntryChange is an XDR Union defines as:
//
//   union LedgerEntryChange switch (LedgerEntryChangeType type)
//    {
//    case LEDGER_ENTRY_CREATED:
//        LedgerEntry created;
//    case LEDGER_ENTRY_UPDATED:
//        LedgerEntry updated;
//    case LEDGER_ENTRY_REMOVED:
//        LedgerKey removed;
//    case LEDGER_ENTRY_STATE:
//        LedgerEntry state;
//    };
//
// union with discriminant LedgerEntryChangeType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerEntryChange {
    Created(LedgerEntry),
    Updated(LedgerEntry),
    Removed(LedgerKey),
    State(LedgerEntry),
}

impl LedgerEntryChange {
    pub const VARIANTS: [LedgerEntryChangeType; 4] = [
        LedgerEntryChangeType::Created,
        LedgerEntryChangeType::Updated,
        LedgerEntryChangeType::Removed,
        LedgerEntryChangeType::State,
    ];
    pub const VARIANTS_STR: [&'static str; 4] = ["Created", "Updated", "Removed", "State"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Created(_) => "Created",
            Self::Updated(_) => "Updated",
            Self::Removed(_) => "Removed",
            Self::State(_) => "State",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> LedgerEntryChangeType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Created(_) => LedgerEntryChangeType::Created,
            Self::Updated(_) => LedgerEntryChangeType::Updated,
            Self::Removed(_) => LedgerEntryChangeType::Removed,
            Self::State(_) => LedgerEntryChangeType::State,
        }
    }

    #[must_use]
    pub const fn variants() -> [LedgerEntryChangeType; 4] {
        Self::VARIANTS
    }
}

impl Name for LedgerEntryChange {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<LedgerEntryChangeType> for LedgerEntryChange {
    #[must_use]
    fn discriminant(&self) -> LedgerEntryChangeType {
        Self::discriminant(self)
    }
}

impl Variants<LedgerEntryChangeType> for LedgerEntryChange {
    fn variants() -> slice::Iter<'static, LedgerEntryChangeType> {
        Self::VARIANTS.iter()
    }
}

impl Union<LedgerEntryChangeType> for LedgerEntryChange {}

impl ReadXdr for LedgerEntryChange {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: LedgerEntryChangeType = <LedgerEntryChangeType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            LedgerEntryChangeType::Created => Self::Created(LedgerEntry::read_xdr(r)?),
            LedgerEntryChangeType::Updated => Self::Updated(LedgerEntry::read_xdr(r)?),
            LedgerEntryChangeType::Removed => Self::Removed(LedgerKey::read_xdr(r)?),
            LedgerEntryChangeType::State => Self::State(LedgerEntry::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerEntryChange {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Created(v) => v.write_xdr(w)?,
            Self::Updated(v) => v.write_xdr(w)?,
            Self::Removed(v) => v.write_xdr(w)?,
            Self::State(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// LedgerEntryChanges is an XDR Typedef defines as:
//
//   typedef LedgerEntryChange LedgerEntryChanges<>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerEntryChanges(pub VecM<LedgerEntryChange>);

impl From<LedgerEntryChanges> for VecM<LedgerEntryChange> {
    #[must_use]
    fn from(x: LedgerEntryChanges) -> Self {
        x.0
    }
}

impl From<VecM<LedgerEntryChange>> for LedgerEntryChanges {
    #[must_use]
    fn from(x: VecM<LedgerEntryChange>) -> Self {
        LedgerEntryChanges(x)
    }
}

impl AsRef<VecM<LedgerEntryChange>> for LedgerEntryChanges {
    #[must_use]
    fn as_ref(&self) -> &VecM<LedgerEntryChange> {
        &self.0
    }
}

impl ReadXdr for LedgerEntryChanges {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = VecM::<LedgerEntryChange>::read_xdr(r)?;
        let v = LedgerEntryChanges(i);
        Ok(v)
    }
}

impl WriteXdr for LedgerEntryChanges {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for LedgerEntryChanges {
    type Target = VecM<LedgerEntryChange>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<LedgerEntryChanges> for Vec<LedgerEntryChange> {
    #[must_use]
    fn from(x: LedgerEntryChanges) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<LedgerEntryChange>> for LedgerEntryChanges {
    type Error = Error;
    fn try_from(x: Vec<LedgerEntryChange>) -> Result<Self> {
        Ok(LedgerEntryChanges(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<LedgerEntryChange>> for LedgerEntryChanges {
    type Error = Error;
    fn try_from(x: &Vec<LedgerEntryChange>) -> Result<Self> {
        Ok(LedgerEntryChanges(x.try_into()?))
    }
}

impl AsRef<Vec<LedgerEntryChange>> for LedgerEntryChanges {
    #[must_use]
    fn as_ref(&self) -> &Vec<LedgerEntryChange> {
        &self.0 .0
    }
}

impl AsRef<[LedgerEntryChange]> for LedgerEntryChanges {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[LedgerEntryChange] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[LedgerEntryChange] {
        self.0 .0
    }
}

// OperationMeta is an XDR Struct defines as:
//
//   struct OperationMeta
//    {
//        LedgerEntryChanges changes;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct OperationMeta {
    pub changes: LedgerEntryChanges,
}

impl ReadXdr for OperationMeta {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            changes: LedgerEntryChanges::read_xdr(r)?,
        })
    }
}

impl WriteXdr for OperationMeta {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.changes.write_xdr(w)?;
        Ok(())
    }
}

// TransactionMetaV1 is an XDR Struct defines as:
//
//   struct TransactionMetaV1
//    {
//        LedgerEntryChanges txChanges; // tx level changes if any
//        OperationMeta operations<>;   // meta for each operation
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionMetaV1 {
    pub tx_changes: LedgerEntryChanges,
    pub operations: VecM<OperationMeta>,
}

impl ReadXdr for TransactionMetaV1 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            tx_changes: LedgerEntryChanges::read_xdr(r)?,
            operations: VecM::<OperationMeta>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionMetaV1 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.tx_changes.write_xdr(w)?;
        self.operations.write_xdr(w)?;
        Ok(())
    }
}

// TransactionMetaV2 is an XDR Struct defines as:
//
//   struct TransactionMetaV2
//    {
//        LedgerEntryChanges txChangesBefore; // tx level changes before operations
//                                            // are applied if any
//        OperationMeta operations<>;         // meta for each operation
//        LedgerEntryChanges txChangesAfter;  // tx level changes after operations are
//                                            // applied if any
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionMetaV2 {
    pub tx_changes_before: LedgerEntryChanges,
    pub operations: VecM<OperationMeta>,
    pub tx_changes_after: LedgerEntryChanges,
}

impl ReadXdr for TransactionMetaV2 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            tx_changes_before: LedgerEntryChanges::read_xdr(r)?,
            operations: VecM::<OperationMeta>::read_xdr(r)?,
            tx_changes_after: LedgerEntryChanges::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionMetaV2 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.tx_changes_before.write_xdr(w)?;
        self.operations.write_xdr(w)?;
        self.tx_changes_after.write_xdr(w)?;
        Ok(())
    }
}

// ContractEventType is an XDR Enum defines as:
//
//   enum ContractEventType
//    {
//        SYSTEM = 0,
//        CONTRACT = 1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ContractEventType {
    System = 0,
    Contract = 1,
}

impl ContractEventType {
    pub const VARIANTS: [ContractEventType; 2] =
        [ContractEventType::System, ContractEventType::Contract];
    pub const VARIANTS_STR: [&'static str; 2] = ["System", "Contract"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::System => "System",
            Self::Contract => "Contract",
        }
    }

    #[must_use]
    pub const fn variants() -> [ContractEventType; 2] {
        Self::VARIANTS
    }
}

impl Name for ContractEventType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ContractEventType> for ContractEventType {
    fn variants() -> slice::Iter<'static, ContractEventType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ContractEventType {}

impl fmt::Display for ContractEventType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ContractEventType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ContractEventType::System,
            1 => ContractEventType::Contract,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ContractEventType> for i32 {
    #[must_use]
    fn from(e: ContractEventType) -> Self {
        e as Self
    }
}

impl ReadXdr for ContractEventType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ContractEventType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ContractEventV0 is an XDR NestedStruct defines as:
//
//   struct
//            {
//                SCVec topics;
//                SCVal data;
//            }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ContractEventV0 {
    pub topics: ScVec,
    pub data: ScVal,
}

impl ReadXdr for ContractEventV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            topics: ScVec::read_xdr(r)?,
            data: ScVal::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ContractEventV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.topics.write_xdr(w)?;
        self.data.write_xdr(w)?;
        Ok(())
    }
}

// ContractEventBody is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            struct
//            {
//                SCVec topics;
//                SCVal data;
//            } v0;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ContractEventBody {
    V0(ContractEventV0),
}

impl ContractEventBody {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0(_) => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(_) => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for ContractEventBody {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for ContractEventBody {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for ContractEventBody {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for ContractEventBody {}

impl ReadXdr for ContractEventBody {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0(ContractEventV0::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ContractEventBody {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ContractEvent is an XDR Struct defines as:
//
//   struct ContractEvent
//    {
//        // We can use this to add more fields, or because it
//        // is first, to change ContractEvent into a union.
//        ExtensionPoint ext;
//
//        Hash* contractID;
//        ContractEventType type;
//
//        union switch (int v)
//        {
//        case 0:
//            struct
//            {
//                SCVec topics;
//                SCVal data;
//            } v0;
//        }
//        body;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ContractEvent {
    pub ext: ExtensionPoint,
    pub contract_id: Option<Hash>,
    pub type_: ContractEventType,
    pub body: ContractEventBody,
}

impl ReadXdr for ContractEvent {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ext: ExtensionPoint::read_xdr(r)?,
            contract_id: Option::<Hash>::read_xdr(r)?,
            type_: ContractEventType::read_xdr(r)?,
            body: ContractEventBody::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ContractEvent {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ext.write_xdr(w)?;
        self.contract_id.write_xdr(w)?;
        self.type_.write_xdr(w)?;
        self.body.write_xdr(w)?;
        Ok(())
    }
}

// OperationEvents is an XDR Struct defines as:
//
//   struct OperationEvents
//    {
//        ContractEvent events<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct OperationEvents {
    pub events: VecM<ContractEvent>,
}

impl ReadXdr for OperationEvents {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            events: VecM::<ContractEvent>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for OperationEvents {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.events.write_xdr(w)?;
        Ok(())
    }
}

// TransactionMetaV3 is an XDR Struct defines as:
//
//   struct TransactionMetaV3
//    {
//        LedgerEntryChanges txChangesBefore; // tx level changes before operations
//                                            // are applied if any
//        OperationMeta operations<>;         // meta for each operation
//        LedgerEntryChanges txChangesAfter;  // tx level changes after operations are
//                                            // applied if any
//        OperationEvents events<>;           // custom events populated by the
//                                            // contracts themselves. One list per operation.
//        TransactionResult txResult;
//
//        Hash hashes[3];                     // stores sha256(txChangesBefore, operations, txChangesAfter),
//                                            // sha256(events), and sha256(txResult)
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionMetaV3 {
    pub tx_changes_before: LedgerEntryChanges,
    pub operations: VecM<OperationMeta>,
    pub tx_changes_after: LedgerEntryChanges,
    pub events: VecM<OperationEvents>,
    pub tx_result: TransactionResult,
    pub hashes: [Hash; 3],
}

impl ReadXdr for TransactionMetaV3 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            tx_changes_before: LedgerEntryChanges::read_xdr(r)?,
            operations: VecM::<OperationMeta>::read_xdr(r)?,
            tx_changes_after: LedgerEntryChanges::read_xdr(r)?,
            events: VecM::<OperationEvents>::read_xdr(r)?,
            tx_result: TransactionResult::read_xdr(r)?,
            hashes: <[Hash; 3]>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionMetaV3 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.tx_changes_before.write_xdr(w)?;
        self.operations.write_xdr(w)?;
        self.tx_changes_after.write_xdr(w)?;
        self.events.write_xdr(w)?;
        self.tx_result.write_xdr(w)?;
        self.hashes.write_xdr(w)?;
        Ok(())
    }
}

// TransactionMeta is an XDR Union defines as:
//
//   union TransactionMeta switch (int v)
//    {
//    case 0:
//        OperationMeta operations<>;
//    case 1:
//        TransactionMetaV1 v1;
//    case 2:
//        TransactionMetaV2 v2;
//    case 3:
//        TransactionMetaV3 v3;
//    };
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionMeta {
    V0(VecM<OperationMeta>),
    V1(TransactionMetaV1),
    V2(TransactionMetaV2),
    V3(TransactionMetaV3),
}

impl TransactionMeta {
    pub const VARIANTS: [i32; 4] = [0, 1, 2, 3];
    pub const VARIANTS_STR: [&'static str; 4] = ["V0", "V1", "V2", "V3"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0(_) => "V0",
            Self::V1(_) => "V1",
            Self::V2(_) => "V2",
            Self::V3(_) => "V3",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(_) => 0,
            Self::V1(_) => 1,
            Self::V2(_) => 2,
            Self::V3(_) => 3,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 4] {
        Self::VARIANTS
    }
}

impl Name for TransactionMeta {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TransactionMeta {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TransactionMeta {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TransactionMeta {}

impl ReadXdr for TransactionMeta {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0(VecM::<OperationMeta>::read_xdr(r)?),
            1 => Self::V1(TransactionMetaV1::read_xdr(r)?),
            2 => Self::V2(TransactionMetaV2::read_xdr(r)?),
            3 => Self::V3(TransactionMetaV3::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionMeta {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(v) => v.write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
            Self::V2(v) => v.write_xdr(w)?,
            Self::V3(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionResultMeta is an XDR Struct defines as:
//
//   struct TransactionResultMeta
//    {
//        TransactionResultPair result;
//        LedgerEntryChanges feeProcessing;
//        TransactionMeta txApplyProcessing;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionResultMeta {
    pub result: TransactionResultPair,
    pub fee_processing: LedgerEntryChanges,
    pub tx_apply_processing: TransactionMeta,
}

impl ReadXdr for TransactionResultMeta {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            result: TransactionResultPair::read_xdr(r)?,
            fee_processing: LedgerEntryChanges::read_xdr(r)?,
            tx_apply_processing: TransactionMeta::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionResultMeta {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.result.write_xdr(w)?;
        self.fee_processing.write_xdr(w)?;
        self.tx_apply_processing.write_xdr(w)?;
        Ok(())
    }
}

// TransactionResultMetaV2 is an XDR Struct defines as:
//
//   struct TransactionResultMetaV2
//    {
//        TransactionResultPairV2 result;
//        LedgerEntryChanges feeProcessing;
//        TransactionMeta txApplyProcessing;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionResultMetaV2 {
    pub result: TransactionResultPairV2,
    pub fee_processing: LedgerEntryChanges,
    pub tx_apply_processing: TransactionMeta,
}

impl ReadXdr for TransactionResultMetaV2 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            result: TransactionResultPairV2::read_xdr(r)?,
            fee_processing: LedgerEntryChanges::read_xdr(r)?,
            tx_apply_processing: TransactionMeta::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionResultMetaV2 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.result.write_xdr(w)?;
        self.fee_processing.write_xdr(w)?;
        self.tx_apply_processing.write_xdr(w)?;
        Ok(())
    }
}

// UpgradeEntryMeta is an XDR Struct defines as:
//
//   struct UpgradeEntryMeta
//    {
//        LedgerUpgrade upgrade;
//        LedgerEntryChanges changes;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct UpgradeEntryMeta {
    pub upgrade: LedgerUpgrade,
    pub changes: LedgerEntryChanges,
}

impl ReadXdr for UpgradeEntryMeta {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            upgrade: LedgerUpgrade::read_xdr(r)?,
            changes: LedgerEntryChanges::read_xdr(r)?,
        })
    }
}

impl WriteXdr for UpgradeEntryMeta {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.upgrade.write_xdr(w)?;
        self.changes.write_xdr(w)?;
        Ok(())
    }
}

// LedgerCloseMetaV0 is an XDR Struct defines as:
//
//   struct LedgerCloseMetaV0
//    {
//        LedgerHeaderHistoryEntry ledgerHeader;
//        // NB: txSet is sorted in "Hash order"
//        TransactionSet txSet;
//
//        // NB: transactions are sorted in apply order here
//        // fees for all transactions are processed first
//        // followed by applying transactions
//        TransactionResultMeta txProcessing<>;
//
//        // upgrades are applied last
//        UpgradeEntryMeta upgradesProcessing<>;
//
//        // other misc information attached to the ledger close
//        SCPHistoryEntry scpInfo<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerCloseMetaV0 {
    pub ledger_header: LedgerHeaderHistoryEntry,
    pub tx_set: TransactionSet,
    pub tx_processing: VecM<TransactionResultMeta>,
    pub upgrades_processing: VecM<UpgradeEntryMeta>,
    pub scp_info: VecM<ScpHistoryEntry>,
}

impl ReadXdr for LedgerCloseMetaV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_header: LedgerHeaderHistoryEntry::read_xdr(r)?,
            tx_set: TransactionSet::read_xdr(r)?,
            tx_processing: VecM::<TransactionResultMeta>::read_xdr(r)?,
            upgrades_processing: VecM::<UpgradeEntryMeta>::read_xdr(r)?,
            scp_info: VecM::<ScpHistoryEntry>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerCloseMetaV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_header.write_xdr(w)?;
        self.tx_set.write_xdr(w)?;
        self.tx_processing.write_xdr(w)?;
        self.upgrades_processing.write_xdr(w)?;
        self.scp_info.write_xdr(w)?;
        Ok(())
    }
}

// LedgerCloseMetaV1 is an XDR Struct defines as:
//
//   struct LedgerCloseMetaV1
//    {
//        LedgerHeaderHistoryEntry ledgerHeader;
//
//        GeneralizedTransactionSet txSet;
//
//        // NB: transactions are sorted in apply order here
//        // fees for all transactions are processed first
//        // followed by applying transactions
//        TransactionResultMeta txProcessing<>;
//
//        // upgrades are applied last
//        UpgradeEntryMeta upgradesProcessing<>;
//
//        // other misc information attached to the ledger close
//        SCPHistoryEntry scpInfo<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerCloseMetaV1 {
    pub ledger_header: LedgerHeaderHistoryEntry,
    pub tx_set: GeneralizedTransactionSet,
    pub tx_processing: VecM<TransactionResultMeta>,
    pub upgrades_processing: VecM<UpgradeEntryMeta>,
    pub scp_info: VecM<ScpHistoryEntry>,
}

impl ReadXdr for LedgerCloseMetaV1 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_header: LedgerHeaderHistoryEntry::read_xdr(r)?,
            tx_set: GeneralizedTransactionSet::read_xdr(r)?,
            tx_processing: VecM::<TransactionResultMeta>::read_xdr(r)?,
            upgrades_processing: VecM::<UpgradeEntryMeta>::read_xdr(r)?,
            scp_info: VecM::<ScpHistoryEntry>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerCloseMetaV1 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_header.write_xdr(w)?;
        self.tx_set.write_xdr(w)?;
        self.tx_processing.write_xdr(w)?;
        self.upgrades_processing.write_xdr(w)?;
        self.scp_info.write_xdr(w)?;
        Ok(())
    }
}

// LedgerCloseMetaV2 is an XDR Struct defines as:
//
//   struct LedgerCloseMetaV2
//    {
//        LedgerHeaderHistoryEntry ledgerHeader;
//
//        GeneralizedTransactionSet txSet;
//
//        // NB: transactions are sorted in apply order here
//        // fees for all transactions are processed first
//        // followed by applying transactions
//        TransactionResultMetaV2 txProcessing<>;
//
//        // upgrades are applied last
//        UpgradeEntryMeta upgradesProcessing<>;
//
//        // other misc information attached to the ledger close
//        SCPHistoryEntry scpInfo<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerCloseMetaV2 {
    pub ledger_header: LedgerHeaderHistoryEntry,
    pub tx_set: GeneralizedTransactionSet,
    pub tx_processing: VecM<TransactionResultMetaV2>,
    pub upgrades_processing: VecM<UpgradeEntryMeta>,
    pub scp_info: VecM<ScpHistoryEntry>,
}

impl ReadXdr for LedgerCloseMetaV2 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_header: LedgerHeaderHistoryEntry::read_xdr(r)?,
            tx_set: GeneralizedTransactionSet::read_xdr(r)?,
            tx_processing: VecM::<TransactionResultMetaV2>::read_xdr(r)?,
            upgrades_processing: VecM::<UpgradeEntryMeta>::read_xdr(r)?,
            scp_info: VecM::<ScpHistoryEntry>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerCloseMetaV2 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_header.write_xdr(w)?;
        self.tx_set.write_xdr(w)?;
        self.tx_processing.write_xdr(w)?;
        self.upgrades_processing.write_xdr(w)?;
        self.scp_info.write_xdr(w)?;
        Ok(())
    }
}

// LedgerCloseMeta is an XDR Union defines as:
//
//   union LedgerCloseMeta switch (int v)
//    {
//    case 0:
//        LedgerCloseMetaV0 v0;
//    case 1:
//        LedgerCloseMetaV1 v1;
//    case 2:
//        LedgerCloseMetaV2 v2;
//    };
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LedgerCloseMeta {
    V0(LedgerCloseMetaV0),
    V1(LedgerCloseMetaV1),
    V2(LedgerCloseMetaV2),
}

impl LedgerCloseMeta {
    pub const VARIANTS: [i32; 3] = [0, 1, 2];
    pub const VARIANTS_STR: [&'static str; 3] = ["V0", "V1", "V2"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0(_) => "V0",
            Self::V1(_) => "V1",
            Self::V2(_) => "V2",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(_) => 0,
            Self::V1(_) => 1,
            Self::V2(_) => 2,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 3] {
        Self::VARIANTS
    }
}

impl Name for LedgerCloseMeta {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for LedgerCloseMeta {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for LedgerCloseMeta {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for LedgerCloseMeta {}

impl ReadXdr for LedgerCloseMeta {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0(LedgerCloseMetaV0::read_xdr(r)?),
            1 => Self::V1(LedgerCloseMetaV1::read_xdr(r)?),
            2 => Self::V2(LedgerCloseMetaV2::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LedgerCloseMeta {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(v) => v.write_xdr(w)?,
            Self::V1(v) => v.write_xdr(w)?,
            Self::V2(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ErrorCode is an XDR Enum defines as:
//
//   enum ErrorCode
//    {
//        ERR_MISC = 0, // Unspecific error
//        ERR_DATA = 1, // Malformed data
//        ERR_CONF = 2, // Misconfiguration error
//        ERR_AUTH = 3, // Authentication failure
//        ERR_LOAD = 4  // System overloaded
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ErrorCode {
    Misc = 0,
    Data = 1,
    Conf = 2,
    Auth = 3,
    Load = 4,
}

impl ErrorCode {
    pub const VARIANTS: [ErrorCode; 5] = [
        ErrorCode::Misc,
        ErrorCode::Data,
        ErrorCode::Conf,
        ErrorCode::Auth,
        ErrorCode::Load,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = ["Misc", "Data", "Conf", "Auth", "Load"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Misc => "Misc",
            Self::Data => "Data",
            Self::Conf => "Conf",
            Self::Auth => "Auth",
            Self::Load => "Load",
        }
    }

    #[must_use]
    pub const fn variants() -> [ErrorCode; 5] {
        Self::VARIANTS
    }
}

impl Name for ErrorCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ErrorCode> for ErrorCode {
    fn variants() -> slice::Iter<'static, ErrorCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ErrorCode {}

impl fmt::Display for ErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ErrorCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ErrorCode::Misc,
            1 => ErrorCode::Data,
            2 => ErrorCode::Conf,
            3 => ErrorCode::Auth,
            4 => ErrorCode::Load,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ErrorCode> for i32 {
    #[must_use]
    fn from(e: ErrorCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ErrorCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ErrorCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// SError is an XDR Struct defines as:
//
//   struct Error
//    {
//        ErrorCode code;
//        string msg<100>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SError {
    pub code: ErrorCode,
    pub msg: StringM<100>,
}

impl ReadXdr for SError {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            code: ErrorCode::read_xdr(r)?,
            msg: StringM::<100>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SError {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.code.write_xdr(w)?;
        self.msg.write_xdr(w)?;
        Ok(())
    }
}

// SendMore is an XDR Struct defines as:
//
//   struct SendMore
//    {
//        uint32 numMessages;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SendMore {
    pub num_messages: u32,
}

impl ReadXdr for SendMore {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            num_messages: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SendMore {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.num_messages.write_xdr(w)?;
        Ok(())
    }
}

// AuthCert is an XDR Struct defines as:
//
//   struct AuthCert
//    {
//        Curve25519Public pubkey;
//        uint64 expiration;
//        Signature sig;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AuthCert {
    pub pubkey: Curve25519Public,
    pub expiration: u64,
    pub sig: Signature,
}

impl ReadXdr for AuthCert {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            pubkey: Curve25519Public::read_xdr(r)?,
            expiration: u64::read_xdr(r)?,
            sig: Signature::read_xdr(r)?,
        })
    }
}

impl WriteXdr for AuthCert {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.pubkey.write_xdr(w)?;
        self.expiration.write_xdr(w)?;
        self.sig.write_xdr(w)?;
        Ok(())
    }
}

// Hello is an XDR Struct defines as:
//
//   struct Hello
//    {
//        uint32 ledgerVersion;
//        uint32 overlayVersion;
//        uint32 overlayMinVersion;
//        Hash networkID;
//        string versionStr<100>;
//        int listeningPort;
//        NodeID peerID;
//        AuthCert cert;
//        uint256 nonce;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Hello {
    pub ledger_version: u32,
    pub overlay_version: u32,
    pub overlay_min_version: u32,
    pub network_id: Hash,
    pub version_str: StringM<100>,
    pub listening_port: i32,
    pub peer_id: NodeId,
    pub cert: AuthCert,
    pub nonce: Uint256,
}

impl ReadXdr for Hello {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ledger_version: u32::read_xdr(r)?,
            overlay_version: u32::read_xdr(r)?,
            overlay_min_version: u32::read_xdr(r)?,
            network_id: Hash::read_xdr(r)?,
            version_str: StringM::<100>::read_xdr(r)?,
            listening_port: i32::read_xdr(r)?,
            peer_id: NodeId::read_xdr(r)?,
            cert: AuthCert::read_xdr(r)?,
            nonce: Uint256::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Hello {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ledger_version.write_xdr(w)?;
        self.overlay_version.write_xdr(w)?;
        self.overlay_min_version.write_xdr(w)?;
        self.network_id.write_xdr(w)?;
        self.version_str.write_xdr(w)?;
        self.listening_port.write_xdr(w)?;
        self.peer_id.write_xdr(w)?;
        self.cert.write_xdr(w)?;
        self.nonce.write_xdr(w)?;
        Ok(())
    }
}

// AuthMsgFlagPullModeRequested is an XDR Const defines as:
//
//   const AUTH_MSG_FLAG_PULL_MODE_REQUESTED = 100;
//
pub const AUTH_MSG_FLAG_PULL_MODE_REQUESTED: u64 = 100;

// Auth is an XDR Struct defines as:
//
//   struct Auth
//    {
//        int flags;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Auth {
    pub flags: i32,
}

impl ReadXdr for Auth {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            flags: i32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Auth {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.flags.write_xdr(w)?;
        Ok(())
    }
}

// IpAddrType is an XDR Enum defines as:
//
//   enum IPAddrType
//    {
//        IPv4 = 0,
//        IPv6 = 1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum IpAddrType {
    IPv4 = 0,
    IPv6 = 1,
}

impl IpAddrType {
    pub const VARIANTS: [IpAddrType; 2] = [IpAddrType::IPv4, IpAddrType::IPv6];
    pub const VARIANTS_STR: [&'static str; 2] = ["IPv4", "IPv6"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::IPv4 => "IPv4",
            Self::IPv6 => "IPv6",
        }
    }

    #[must_use]
    pub const fn variants() -> [IpAddrType; 2] {
        Self::VARIANTS
    }
}

impl Name for IpAddrType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<IpAddrType> for IpAddrType {
    fn variants() -> slice::Iter<'static, IpAddrType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for IpAddrType {}

impl fmt::Display for IpAddrType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for IpAddrType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => IpAddrType::IPv4,
            1 => IpAddrType::IPv6,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<IpAddrType> for i32 {
    #[must_use]
    fn from(e: IpAddrType) -> Self {
        e as Self
    }
}

impl ReadXdr for IpAddrType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for IpAddrType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// PeerAddressIp is an XDR NestedUnion defines as:
//
//   union switch (IPAddrType type)
//        {
//        case IPv4:
//            opaque ipv4[4];
//        case IPv6:
//            opaque ipv6[16];
//        }
//
// union with discriminant IpAddrType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum PeerAddressIp {
    IPv4([u8; 4]),
    IPv6([u8; 16]),
}

impl PeerAddressIp {
    pub const VARIANTS: [IpAddrType; 2] = [IpAddrType::IPv4, IpAddrType::IPv6];
    pub const VARIANTS_STR: [&'static str; 2] = ["IPv4", "IPv6"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::IPv4(_) => "IPv4",
            Self::IPv6(_) => "IPv6",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> IpAddrType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::IPv4(_) => IpAddrType::IPv4,
            Self::IPv6(_) => IpAddrType::IPv6,
        }
    }

    #[must_use]
    pub const fn variants() -> [IpAddrType; 2] {
        Self::VARIANTS
    }
}

impl Name for PeerAddressIp {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<IpAddrType> for PeerAddressIp {
    #[must_use]
    fn discriminant(&self) -> IpAddrType {
        Self::discriminant(self)
    }
}

impl Variants<IpAddrType> for PeerAddressIp {
    fn variants() -> slice::Iter<'static, IpAddrType> {
        Self::VARIANTS.iter()
    }
}

impl Union<IpAddrType> for PeerAddressIp {}

impl ReadXdr for PeerAddressIp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: IpAddrType = <IpAddrType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            IpAddrType::IPv4 => Self::IPv4(<[u8; 4]>::read_xdr(r)?),
            IpAddrType::IPv6 => Self::IPv6(<[u8; 16]>::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for PeerAddressIp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::IPv4(v) => v.write_xdr(w)?,
            Self::IPv6(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// PeerAddress is an XDR Struct defines as:
//
//   struct PeerAddress
//    {
//        union switch (IPAddrType type)
//        {
//        case IPv4:
//            opaque ipv4[4];
//        case IPv6:
//            opaque ipv6[16];
//        }
//        ip;
//        uint32 port;
//        uint32 numFailures;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PeerAddress {
    pub ip: PeerAddressIp,
    pub port: u32,
    pub num_failures: u32,
}

impl ReadXdr for PeerAddress {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ip: PeerAddressIp::read_xdr(r)?,
            port: u32::read_xdr(r)?,
            num_failures: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PeerAddress {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ip.write_xdr(w)?;
        self.port.write_xdr(w)?;
        self.num_failures.write_xdr(w)?;
        Ok(())
    }
}

// MessageType is an XDR Enum defines as:
//
//   enum MessageType
//    {
//        ERROR_MSG = 0,
//        AUTH = 2,
//        DONT_HAVE = 3,
//
//        GET_PEERS = 4, // gets a list of peers this guy knows about
//        PEERS = 5,
//
//        GET_TX_SET = 6, // gets a particular txset by hash
//        TX_SET = 7,
//        GENERALIZED_TX_SET = 17,
//
//        TRANSACTION = 8, // pass on a tx you have heard about
//
//        // SCP
//        GET_SCP_QUORUMSET = 9,
//        SCP_QUORUMSET = 10,
//        SCP_MESSAGE = 11,
//        GET_SCP_STATE = 12,
//
//        // new messages
//        HELLO = 13,
//
//        SURVEY_REQUEST = 14,
//        SURVEY_RESPONSE = 15,
//
//        SEND_MORE = 16,
//        FLOOD_ADVERT = 18,
//        FLOOD_DEMAND = 19
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum MessageType {
    ErrorMsg = 0,
    Auth = 2,
    DontHave = 3,
    GetPeers = 4,
    Peers = 5,
    GetTxSet = 6,
    TxSet = 7,
    GeneralizedTxSet = 17,
    Transaction = 8,
    GetScpQuorumset = 9,
    ScpQuorumset = 10,
    ScpMessage = 11,
    GetScpState = 12,
    Hello = 13,
    SurveyRequest = 14,
    SurveyResponse = 15,
    SendMore = 16,
    FloodAdvert = 18,
    FloodDemand = 19,
}

impl MessageType {
    pub const VARIANTS: [MessageType; 19] = [
        MessageType::ErrorMsg,
        MessageType::Auth,
        MessageType::DontHave,
        MessageType::GetPeers,
        MessageType::Peers,
        MessageType::GetTxSet,
        MessageType::TxSet,
        MessageType::GeneralizedTxSet,
        MessageType::Transaction,
        MessageType::GetScpQuorumset,
        MessageType::ScpQuorumset,
        MessageType::ScpMessage,
        MessageType::GetScpState,
        MessageType::Hello,
        MessageType::SurveyRequest,
        MessageType::SurveyResponse,
        MessageType::SendMore,
        MessageType::FloodAdvert,
        MessageType::FloodDemand,
    ];
    pub const VARIANTS_STR: [&'static str; 19] = [
        "ErrorMsg",
        "Auth",
        "DontHave",
        "GetPeers",
        "Peers",
        "GetTxSet",
        "TxSet",
        "GeneralizedTxSet",
        "Transaction",
        "GetScpQuorumset",
        "ScpQuorumset",
        "ScpMessage",
        "GetScpState",
        "Hello",
        "SurveyRequest",
        "SurveyResponse",
        "SendMore",
        "FloodAdvert",
        "FloodDemand",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ErrorMsg => "ErrorMsg",
            Self::Auth => "Auth",
            Self::DontHave => "DontHave",
            Self::GetPeers => "GetPeers",
            Self::Peers => "Peers",
            Self::GetTxSet => "GetTxSet",
            Self::TxSet => "TxSet",
            Self::GeneralizedTxSet => "GeneralizedTxSet",
            Self::Transaction => "Transaction",
            Self::GetScpQuorumset => "GetScpQuorumset",
            Self::ScpQuorumset => "ScpQuorumset",
            Self::ScpMessage => "ScpMessage",
            Self::GetScpState => "GetScpState",
            Self::Hello => "Hello",
            Self::SurveyRequest => "SurveyRequest",
            Self::SurveyResponse => "SurveyResponse",
            Self::SendMore => "SendMore",
            Self::FloodAdvert => "FloodAdvert",
            Self::FloodDemand => "FloodDemand",
        }
    }

    #[must_use]
    pub const fn variants() -> [MessageType; 19] {
        Self::VARIANTS
    }
}

impl Name for MessageType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<MessageType> for MessageType {
    fn variants() -> slice::Iter<'static, MessageType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for MessageType {}

impl fmt::Display for MessageType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for MessageType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => MessageType::ErrorMsg,
            2 => MessageType::Auth,
            3 => MessageType::DontHave,
            4 => MessageType::GetPeers,
            5 => MessageType::Peers,
            6 => MessageType::GetTxSet,
            7 => MessageType::TxSet,
            17 => MessageType::GeneralizedTxSet,
            8 => MessageType::Transaction,
            9 => MessageType::GetScpQuorumset,
            10 => MessageType::ScpQuorumset,
            11 => MessageType::ScpMessage,
            12 => MessageType::GetScpState,
            13 => MessageType::Hello,
            14 => MessageType::SurveyRequest,
            15 => MessageType::SurveyResponse,
            16 => MessageType::SendMore,
            18 => MessageType::FloodAdvert,
            19 => MessageType::FloodDemand,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<MessageType> for i32 {
    #[must_use]
    fn from(e: MessageType) -> Self {
        e as Self
    }
}

impl ReadXdr for MessageType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for MessageType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// DontHave is an XDR Struct defines as:
//
//   struct DontHave
//    {
//        MessageType type;
//        uint256 reqHash;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct DontHave {
    pub type_: MessageType,
    pub req_hash: Uint256,
}

impl ReadXdr for DontHave {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            type_: MessageType::read_xdr(r)?,
            req_hash: Uint256::read_xdr(r)?,
        })
    }
}

impl WriteXdr for DontHave {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.type_.write_xdr(w)?;
        self.req_hash.write_xdr(w)?;
        Ok(())
    }
}

// SurveyMessageCommandType is an XDR Enum defines as:
//
//   enum SurveyMessageCommandType
//    {
//        SURVEY_TOPOLOGY = 0
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum SurveyMessageCommandType {
    SurveyTopology = 0,
}

impl SurveyMessageCommandType {
    pub const VARIANTS: [SurveyMessageCommandType; 1] = [SurveyMessageCommandType::SurveyTopology];
    pub const VARIANTS_STR: [&'static str; 1] = ["SurveyTopology"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::SurveyTopology => "SurveyTopology",
        }
    }

    #[must_use]
    pub const fn variants() -> [SurveyMessageCommandType; 1] {
        Self::VARIANTS
    }
}

impl Name for SurveyMessageCommandType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<SurveyMessageCommandType> for SurveyMessageCommandType {
    fn variants() -> slice::Iter<'static, SurveyMessageCommandType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for SurveyMessageCommandType {}

impl fmt::Display for SurveyMessageCommandType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for SurveyMessageCommandType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => SurveyMessageCommandType::SurveyTopology,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<SurveyMessageCommandType> for i32 {
    #[must_use]
    fn from(e: SurveyMessageCommandType) -> Self {
        e as Self
    }
}

impl ReadXdr for SurveyMessageCommandType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for SurveyMessageCommandType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// SurveyRequestMessage is an XDR Struct defines as:
//
//   struct SurveyRequestMessage
//    {
//        NodeID surveyorPeerID;
//        NodeID surveyedPeerID;
//        uint32 ledgerNum;
//        Curve25519Public encryptionKey;
//        SurveyMessageCommandType commandType;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SurveyRequestMessage {
    pub surveyor_peer_id: NodeId,
    pub surveyed_peer_id: NodeId,
    pub ledger_num: u32,
    pub encryption_key: Curve25519Public,
    pub command_type: SurveyMessageCommandType,
}

impl ReadXdr for SurveyRequestMessage {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            surveyor_peer_id: NodeId::read_xdr(r)?,
            surveyed_peer_id: NodeId::read_xdr(r)?,
            ledger_num: u32::read_xdr(r)?,
            encryption_key: Curve25519Public::read_xdr(r)?,
            command_type: SurveyMessageCommandType::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SurveyRequestMessage {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.surveyor_peer_id.write_xdr(w)?;
        self.surveyed_peer_id.write_xdr(w)?;
        self.ledger_num.write_xdr(w)?;
        self.encryption_key.write_xdr(w)?;
        self.command_type.write_xdr(w)?;
        Ok(())
    }
}

// SignedSurveyRequestMessage is an XDR Struct defines as:
//
//   struct SignedSurveyRequestMessage
//    {
//        Signature requestSignature;
//        SurveyRequestMessage request;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SignedSurveyRequestMessage {
    pub request_signature: Signature,
    pub request: SurveyRequestMessage,
}

impl ReadXdr for SignedSurveyRequestMessage {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            request_signature: Signature::read_xdr(r)?,
            request: SurveyRequestMessage::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SignedSurveyRequestMessage {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.request_signature.write_xdr(w)?;
        self.request.write_xdr(w)?;
        Ok(())
    }
}

// EncryptedBody is an XDR Typedef defines as:
//
//   typedef opaque EncryptedBody<64000>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct EncryptedBody(pub BytesM<64000>);

impl From<EncryptedBody> for BytesM<64000> {
    #[must_use]
    fn from(x: EncryptedBody) -> Self {
        x.0
    }
}

impl From<BytesM<64000>> for EncryptedBody {
    #[must_use]
    fn from(x: BytesM<64000>) -> Self {
        EncryptedBody(x)
    }
}

impl AsRef<BytesM<64000>> for EncryptedBody {
    #[must_use]
    fn as_ref(&self) -> &BytesM<64000> {
        &self.0
    }
}

impl ReadXdr for EncryptedBody {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = BytesM::<64000>::read_xdr(r)?;
        let v = EncryptedBody(i);
        Ok(v)
    }
}

impl WriteXdr for EncryptedBody {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for EncryptedBody {
    type Target = BytesM<64000>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<EncryptedBody> for Vec<u8> {
    #[must_use]
    fn from(x: EncryptedBody) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<u8>> for EncryptedBody {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        Ok(EncryptedBody(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for EncryptedBody {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        Ok(EncryptedBody(x.try_into()?))
    }
}

impl AsRef<Vec<u8>> for EncryptedBody {
    #[must_use]
    fn as_ref(&self) -> &Vec<u8> {
        &self.0 .0
    }
}

impl AsRef<[u8]> for EncryptedBody {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        self.0 .0
    }
}

// SurveyResponseMessage is an XDR Struct defines as:
//
//   struct SurveyResponseMessage
//    {
//        NodeID surveyorPeerID;
//        NodeID surveyedPeerID;
//        uint32 ledgerNum;
//        SurveyMessageCommandType commandType;
//        EncryptedBody encryptedBody;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SurveyResponseMessage {
    pub surveyor_peer_id: NodeId,
    pub surveyed_peer_id: NodeId,
    pub ledger_num: u32,
    pub command_type: SurveyMessageCommandType,
    pub encrypted_body: EncryptedBody,
}

impl ReadXdr for SurveyResponseMessage {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            surveyor_peer_id: NodeId::read_xdr(r)?,
            surveyed_peer_id: NodeId::read_xdr(r)?,
            ledger_num: u32::read_xdr(r)?,
            command_type: SurveyMessageCommandType::read_xdr(r)?,
            encrypted_body: EncryptedBody::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SurveyResponseMessage {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.surveyor_peer_id.write_xdr(w)?;
        self.surveyed_peer_id.write_xdr(w)?;
        self.ledger_num.write_xdr(w)?;
        self.command_type.write_xdr(w)?;
        self.encrypted_body.write_xdr(w)?;
        Ok(())
    }
}

// SignedSurveyResponseMessage is an XDR Struct defines as:
//
//   struct SignedSurveyResponseMessage
//    {
//        Signature responseSignature;
//        SurveyResponseMessage response;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SignedSurveyResponseMessage {
    pub response_signature: Signature,
    pub response: SurveyResponseMessage,
}

impl ReadXdr for SignedSurveyResponseMessage {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            response_signature: Signature::read_xdr(r)?,
            response: SurveyResponseMessage::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SignedSurveyResponseMessage {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.response_signature.write_xdr(w)?;
        self.response.write_xdr(w)?;
        Ok(())
    }
}

// PeerStats is an XDR Struct defines as:
//
//   struct PeerStats
//    {
//        NodeID id;
//        string versionStr<100>;
//        uint64 messagesRead;
//        uint64 messagesWritten;
//        uint64 bytesRead;
//        uint64 bytesWritten;
//        uint64 secondsConnected;
//
//        uint64 uniqueFloodBytesRecv;
//        uint64 duplicateFloodBytesRecv;
//        uint64 uniqueFetchBytesRecv;
//        uint64 duplicateFetchBytesRecv;
//
//        uint64 uniqueFloodMessageRecv;
//        uint64 duplicateFloodMessageRecv;
//        uint64 uniqueFetchMessageRecv;
//        uint64 duplicateFetchMessageRecv;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PeerStats {
    pub id: NodeId,
    pub version_str: StringM<100>,
    pub messages_read: u64,
    pub messages_written: u64,
    pub bytes_read: u64,
    pub bytes_written: u64,
    pub seconds_connected: u64,
    pub unique_flood_bytes_recv: u64,
    pub duplicate_flood_bytes_recv: u64,
    pub unique_fetch_bytes_recv: u64,
    pub duplicate_fetch_bytes_recv: u64,
    pub unique_flood_message_recv: u64,
    pub duplicate_flood_message_recv: u64,
    pub unique_fetch_message_recv: u64,
    pub duplicate_fetch_message_recv: u64,
}

impl ReadXdr for PeerStats {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            id: NodeId::read_xdr(r)?,
            version_str: StringM::<100>::read_xdr(r)?,
            messages_read: u64::read_xdr(r)?,
            messages_written: u64::read_xdr(r)?,
            bytes_read: u64::read_xdr(r)?,
            bytes_written: u64::read_xdr(r)?,
            seconds_connected: u64::read_xdr(r)?,
            unique_flood_bytes_recv: u64::read_xdr(r)?,
            duplicate_flood_bytes_recv: u64::read_xdr(r)?,
            unique_fetch_bytes_recv: u64::read_xdr(r)?,
            duplicate_fetch_bytes_recv: u64::read_xdr(r)?,
            unique_flood_message_recv: u64::read_xdr(r)?,
            duplicate_flood_message_recv: u64::read_xdr(r)?,
            unique_fetch_message_recv: u64::read_xdr(r)?,
            duplicate_fetch_message_recv: u64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PeerStats {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.id.write_xdr(w)?;
        self.version_str.write_xdr(w)?;
        self.messages_read.write_xdr(w)?;
        self.messages_written.write_xdr(w)?;
        self.bytes_read.write_xdr(w)?;
        self.bytes_written.write_xdr(w)?;
        self.seconds_connected.write_xdr(w)?;
        self.unique_flood_bytes_recv.write_xdr(w)?;
        self.duplicate_flood_bytes_recv.write_xdr(w)?;
        self.unique_fetch_bytes_recv.write_xdr(w)?;
        self.duplicate_fetch_bytes_recv.write_xdr(w)?;
        self.unique_flood_message_recv.write_xdr(w)?;
        self.duplicate_flood_message_recv.write_xdr(w)?;
        self.unique_fetch_message_recv.write_xdr(w)?;
        self.duplicate_fetch_message_recv.write_xdr(w)?;
        Ok(())
    }
}

// PeerStatList is an XDR Typedef defines as:
//
//   typedef PeerStats PeerStatList<25>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PeerStatList(pub VecM<PeerStats, 25>);

impl From<PeerStatList> for VecM<PeerStats, 25> {
    #[must_use]
    fn from(x: PeerStatList) -> Self {
        x.0
    }
}

impl From<VecM<PeerStats, 25>> for PeerStatList {
    #[must_use]
    fn from(x: VecM<PeerStats, 25>) -> Self {
        PeerStatList(x)
    }
}

impl AsRef<VecM<PeerStats, 25>> for PeerStatList {
    #[must_use]
    fn as_ref(&self) -> &VecM<PeerStats, 25> {
        &self.0
    }
}

impl ReadXdr for PeerStatList {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = VecM::<PeerStats, 25>::read_xdr(r)?;
        let v = PeerStatList(i);
        Ok(v)
    }
}

impl WriteXdr for PeerStatList {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for PeerStatList {
    type Target = VecM<PeerStats, 25>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<PeerStatList> for Vec<PeerStats> {
    #[must_use]
    fn from(x: PeerStatList) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<PeerStats>> for PeerStatList {
    type Error = Error;
    fn try_from(x: Vec<PeerStats>) -> Result<Self> {
        Ok(PeerStatList(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<PeerStats>> for PeerStatList {
    type Error = Error;
    fn try_from(x: &Vec<PeerStats>) -> Result<Self> {
        Ok(PeerStatList(x.try_into()?))
    }
}

impl AsRef<Vec<PeerStats>> for PeerStatList {
    #[must_use]
    fn as_ref(&self) -> &Vec<PeerStats> {
        &self.0 .0
    }
}

impl AsRef<[PeerStats]> for PeerStatList {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[PeerStats] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[PeerStats] {
        self.0 .0
    }
}

// TopologyResponseBody is an XDR Struct defines as:
//
//   struct TopologyResponseBody
//    {
//        PeerStatList inboundPeers;
//        PeerStatList outboundPeers;
//
//        uint32 totalInboundPeerCount;
//        uint32 totalOutboundPeerCount;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TopologyResponseBody {
    pub inbound_peers: PeerStatList,
    pub outbound_peers: PeerStatList,
    pub total_inbound_peer_count: u32,
    pub total_outbound_peer_count: u32,
}

impl ReadXdr for TopologyResponseBody {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            inbound_peers: PeerStatList::read_xdr(r)?,
            outbound_peers: PeerStatList::read_xdr(r)?,
            total_inbound_peer_count: u32::read_xdr(r)?,
            total_outbound_peer_count: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TopologyResponseBody {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.inbound_peers.write_xdr(w)?;
        self.outbound_peers.write_xdr(w)?;
        self.total_inbound_peer_count.write_xdr(w)?;
        self.total_outbound_peer_count.write_xdr(w)?;
        Ok(())
    }
}

// SurveyResponseBody is an XDR Union defines as:
//
//   union SurveyResponseBody switch (SurveyMessageCommandType type)
//    {
//    case SURVEY_TOPOLOGY:
//        TopologyResponseBody topologyResponseBody;
//    };
//
// union with discriminant SurveyMessageCommandType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum SurveyResponseBody {
    SurveyTopology(TopologyResponseBody),
}

impl SurveyResponseBody {
    pub const VARIANTS: [SurveyMessageCommandType; 1] = [SurveyMessageCommandType::SurveyTopology];
    pub const VARIANTS_STR: [&'static str; 1] = ["SurveyTopology"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::SurveyTopology(_) => "SurveyTopology",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> SurveyMessageCommandType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::SurveyTopology(_) => SurveyMessageCommandType::SurveyTopology,
        }
    }

    #[must_use]
    pub const fn variants() -> [SurveyMessageCommandType; 1] {
        Self::VARIANTS
    }
}

impl Name for SurveyResponseBody {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<SurveyMessageCommandType> for SurveyResponseBody {
    #[must_use]
    fn discriminant(&self) -> SurveyMessageCommandType {
        Self::discriminant(self)
    }
}

impl Variants<SurveyMessageCommandType> for SurveyResponseBody {
    fn variants() -> slice::Iter<'static, SurveyMessageCommandType> {
        Self::VARIANTS.iter()
    }
}

impl Union<SurveyMessageCommandType> for SurveyResponseBody {}

impl ReadXdr for SurveyResponseBody {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: SurveyMessageCommandType = <SurveyMessageCommandType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            SurveyMessageCommandType::SurveyTopology => {
                Self::SurveyTopology(TopologyResponseBody::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for SurveyResponseBody {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::SurveyTopology(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TxAdvertVectorMaxSize is an XDR Const defines as:
//
//   const TX_ADVERT_VECTOR_MAX_SIZE = 1000;
//
pub const TX_ADVERT_VECTOR_MAX_SIZE: u64 = 1000;

// TxAdvertVector is an XDR Typedef defines as:
//
//   typedef Hash TxAdvertVector<TX_ADVERT_VECTOR_MAX_SIZE>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TxAdvertVector(pub VecM<Hash, 1000>);

impl From<TxAdvertVector> for VecM<Hash, 1000> {
    #[must_use]
    fn from(x: TxAdvertVector) -> Self {
        x.0
    }
}

impl From<VecM<Hash, 1000>> for TxAdvertVector {
    #[must_use]
    fn from(x: VecM<Hash, 1000>) -> Self {
        TxAdvertVector(x)
    }
}

impl AsRef<VecM<Hash, 1000>> for TxAdvertVector {
    #[must_use]
    fn as_ref(&self) -> &VecM<Hash, 1000> {
        &self.0
    }
}

impl ReadXdr for TxAdvertVector {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = VecM::<Hash, 1000>::read_xdr(r)?;
        let v = TxAdvertVector(i);
        Ok(v)
    }
}

impl WriteXdr for TxAdvertVector {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for TxAdvertVector {
    type Target = VecM<Hash, 1000>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<TxAdvertVector> for Vec<Hash> {
    #[must_use]
    fn from(x: TxAdvertVector) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<Hash>> for TxAdvertVector {
    type Error = Error;
    fn try_from(x: Vec<Hash>) -> Result<Self> {
        Ok(TxAdvertVector(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<Hash>> for TxAdvertVector {
    type Error = Error;
    fn try_from(x: &Vec<Hash>) -> Result<Self> {
        Ok(TxAdvertVector(x.try_into()?))
    }
}

impl AsRef<Vec<Hash>> for TxAdvertVector {
    #[must_use]
    fn as_ref(&self) -> &Vec<Hash> {
        &self.0 .0
    }
}

impl AsRef<[Hash]> for TxAdvertVector {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[Hash] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[Hash] {
        self.0 .0
    }
}

// FloodAdvert is an XDR Struct defines as:
//
//   struct FloodAdvert
//    {
//        TxAdvertVector txHashes;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct FloodAdvert {
    pub tx_hashes: TxAdvertVector,
}

impl ReadXdr for FloodAdvert {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            tx_hashes: TxAdvertVector::read_xdr(r)?,
        })
    }
}

impl WriteXdr for FloodAdvert {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.tx_hashes.write_xdr(w)?;
        Ok(())
    }
}

// TxDemandVectorMaxSize is an XDR Const defines as:
//
//   const TX_DEMAND_VECTOR_MAX_SIZE = 1000;
//
pub const TX_DEMAND_VECTOR_MAX_SIZE: u64 = 1000;

// TxDemandVector is an XDR Typedef defines as:
//
//   typedef Hash TxDemandVector<TX_DEMAND_VECTOR_MAX_SIZE>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TxDemandVector(pub VecM<Hash, 1000>);

impl From<TxDemandVector> for VecM<Hash, 1000> {
    #[must_use]
    fn from(x: TxDemandVector) -> Self {
        x.0
    }
}

impl From<VecM<Hash, 1000>> for TxDemandVector {
    #[must_use]
    fn from(x: VecM<Hash, 1000>) -> Self {
        TxDemandVector(x)
    }
}

impl AsRef<VecM<Hash, 1000>> for TxDemandVector {
    #[must_use]
    fn as_ref(&self) -> &VecM<Hash, 1000> {
        &self.0
    }
}

impl ReadXdr for TxDemandVector {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = VecM::<Hash, 1000>::read_xdr(r)?;
        let v = TxDemandVector(i);
        Ok(v)
    }
}

impl WriteXdr for TxDemandVector {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for TxDemandVector {
    type Target = VecM<Hash, 1000>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<TxDemandVector> for Vec<Hash> {
    #[must_use]
    fn from(x: TxDemandVector) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<Hash>> for TxDemandVector {
    type Error = Error;
    fn try_from(x: Vec<Hash>) -> Result<Self> {
        Ok(TxDemandVector(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<Hash>> for TxDemandVector {
    type Error = Error;
    fn try_from(x: &Vec<Hash>) -> Result<Self> {
        Ok(TxDemandVector(x.try_into()?))
    }
}

impl AsRef<Vec<Hash>> for TxDemandVector {
    #[must_use]
    fn as_ref(&self) -> &Vec<Hash> {
        &self.0 .0
    }
}

impl AsRef<[Hash]> for TxDemandVector {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[Hash] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[Hash] {
        self.0 .0
    }
}

// FloodDemand is an XDR Struct defines as:
//
//   struct FloodDemand
//    {
//        TxDemandVector txHashes;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct FloodDemand {
    pub tx_hashes: TxDemandVector,
}

impl ReadXdr for FloodDemand {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            tx_hashes: TxDemandVector::read_xdr(r)?,
        })
    }
}

impl WriteXdr for FloodDemand {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.tx_hashes.write_xdr(w)?;
        Ok(())
    }
}

// StellarMessage is an XDR Union defines as:
//
//   union StellarMessage switch (MessageType type)
//    {
//    case ERROR_MSG:
//        Error error;
//    case HELLO:
//        Hello hello;
//    case AUTH:
//        Auth auth;
//    case DONT_HAVE:
//        DontHave dontHave;
//    case GET_PEERS:
//        void;
//    case PEERS:
//        PeerAddress peers<100>;
//
//    case GET_TX_SET:
//        uint256 txSetHash;
//    case TX_SET:
//        TransactionSet txSet;
//    case GENERALIZED_TX_SET:
//        GeneralizedTransactionSet generalizedTxSet;
//
//    case TRANSACTION:
//        TransactionEnvelope transaction;
//
//    case SURVEY_REQUEST:
//        SignedSurveyRequestMessage signedSurveyRequestMessage;
//
//    case SURVEY_RESPONSE:
//        SignedSurveyResponseMessage signedSurveyResponseMessage;
//
//    // SCP
//    case GET_SCP_QUORUMSET:
//        uint256 qSetHash;
//    case SCP_QUORUMSET:
//        SCPQuorumSet qSet;
//    case SCP_MESSAGE:
//        SCPEnvelope envelope;
//    case GET_SCP_STATE:
//        uint32 getSCPLedgerSeq; // ledger seq requested ; if 0, requests the latest
//    case SEND_MORE:
//        SendMore sendMoreMessage;
//
//    // Pull mode
//    case FLOOD_ADVERT:
//         FloodAdvert floodAdvert;
//    case FLOOD_DEMAND:
//         FloodDemand floodDemand;
//    };
//
// union with discriminant MessageType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum StellarMessage {
    ErrorMsg(SError),
    Hello(Hello),
    Auth(Auth),
    DontHave(DontHave),
    GetPeers,
    Peers(VecM<PeerAddress, 100>),
    GetTxSet(Uint256),
    TxSet(TransactionSet),
    GeneralizedTxSet(GeneralizedTransactionSet),
    Transaction(TransactionEnvelope),
    SurveyRequest(SignedSurveyRequestMessage),
    SurveyResponse(SignedSurveyResponseMessage),
    GetScpQuorumset(Uint256),
    ScpQuorumset(ScpQuorumSet),
    ScpMessage(ScpEnvelope),
    GetScpState(u32),
    SendMore(SendMore),
    FloodAdvert(FloodAdvert),
    FloodDemand(FloodDemand),
}

impl StellarMessage {
    pub const VARIANTS: [MessageType; 19] = [
        MessageType::ErrorMsg,
        MessageType::Hello,
        MessageType::Auth,
        MessageType::DontHave,
        MessageType::GetPeers,
        MessageType::Peers,
        MessageType::GetTxSet,
        MessageType::TxSet,
        MessageType::GeneralizedTxSet,
        MessageType::Transaction,
        MessageType::SurveyRequest,
        MessageType::SurveyResponse,
        MessageType::GetScpQuorumset,
        MessageType::ScpQuorumset,
        MessageType::ScpMessage,
        MessageType::GetScpState,
        MessageType::SendMore,
        MessageType::FloodAdvert,
        MessageType::FloodDemand,
    ];
    pub const VARIANTS_STR: [&'static str; 19] = [
        "ErrorMsg",
        "Hello",
        "Auth",
        "DontHave",
        "GetPeers",
        "Peers",
        "GetTxSet",
        "TxSet",
        "GeneralizedTxSet",
        "Transaction",
        "SurveyRequest",
        "SurveyResponse",
        "GetScpQuorumset",
        "ScpQuorumset",
        "ScpMessage",
        "GetScpState",
        "SendMore",
        "FloodAdvert",
        "FloodDemand",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::ErrorMsg(_) => "ErrorMsg",
            Self::Hello(_) => "Hello",
            Self::Auth(_) => "Auth",
            Self::DontHave(_) => "DontHave",
            Self::GetPeers => "GetPeers",
            Self::Peers(_) => "Peers",
            Self::GetTxSet(_) => "GetTxSet",
            Self::TxSet(_) => "TxSet",
            Self::GeneralizedTxSet(_) => "GeneralizedTxSet",
            Self::Transaction(_) => "Transaction",
            Self::SurveyRequest(_) => "SurveyRequest",
            Self::SurveyResponse(_) => "SurveyResponse",
            Self::GetScpQuorumset(_) => "GetScpQuorumset",
            Self::ScpQuorumset(_) => "ScpQuorumset",
            Self::ScpMessage(_) => "ScpMessage",
            Self::GetScpState(_) => "GetScpState",
            Self::SendMore(_) => "SendMore",
            Self::FloodAdvert(_) => "FloodAdvert",
            Self::FloodDemand(_) => "FloodDemand",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> MessageType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ErrorMsg(_) => MessageType::ErrorMsg,
            Self::Hello(_) => MessageType::Hello,
            Self::Auth(_) => MessageType::Auth,
            Self::DontHave(_) => MessageType::DontHave,
            Self::GetPeers => MessageType::GetPeers,
            Self::Peers(_) => MessageType::Peers,
            Self::GetTxSet(_) => MessageType::GetTxSet,
            Self::TxSet(_) => MessageType::TxSet,
            Self::GeneralizedTxSet(_) => MessageType::GeneralizedTxSet,
            Self::Transaction(_) => MessageType::Transaction,
            Self::SurveyRequest(_) => MessageType::SurveyRequest,
            Self::SurveyResponse(_) => MessageType::SurveyResponse,
            Self::GetScpQuorumset(_) => MessageType::GetScpQuorumset,
            Self::ScpQuorumset(_) => MessageType::ScpQuorumset,
            Self::ScpMessage(_) => MessageType::ScpMessage,
            Self::GetScpState(_) => MessageType::GetScpState,
            Self::SendMore(_) => MessageType::SendMore,
            Self::FloodAdvert(_) => MessageType::FloodAdvert,
            Self::FloodDemand(_) => MessageType::FloodDemand,
        }
    }

    #[must_use]
    pub const fn variants() -> [MessageType; 19] {
        Self::VARIANTS
    }
}

impl Name for StellarMessage {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<MessageType> for StellarMessage {
    #[must_use]
    fn discriminant(&self) -> MessageType {
        Self::discriminant(self)
    }
}

impl Variants<MessageType> for StellarMessage {
    fn variants() -> slice::Iter<'static, MessageType> {
        Self::VARIANTS.iter()
    }
}

impl Union<MessageType> for StellarMessage {}

impl ReadXdr for StellarMessage {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: MessageType = <MessageType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            MessageType::ErrorMsg => Self::ErrorMsg(SError::read_xdr(r)?),
            MessageType::Hello => Self::Hello(Hello::read_xdr(r)?),
            MessageType::Auth => Self::Auth(Auth::read_xdr(r)?),
            MessageType::DontHave => Self::DontHave(DontHave::read_xdr(r)?),
            MessageType::GetPeers => Self::GetPeers,
            MessageType::Peers => Self::Peers(VecM::<PeerAddress, 100>::read_xdr(r)?),
            MessageType::GetTxSet => Self::GetTxSet(Uint256::read_xdr(r)?),
            MessageType::TxSet => Self::TxSet(TransactionSet::read_xdr(r)?),
            MessageType::GeneralizedTxSet => {
                Self::GeneralizedTxSet(GeneralizedTransactionSet::read_xdr(r)?)
            }
            MessageType::Transaction => Self::Transaction(TransactionEnvelope::read_xdr(r)?),
            MessageType::SurveyRequest => {
                Self::SurveyRequest(SignedSurveyRequestMessage::read_xdr(r)?)
            }
            MessageType::SurveyResponse => {
                Self::SurveyResponse(SignedSurveyResponseMessage::read_xdr(r)?)
            }
            MessageType::GetScpQuorumset => Self::GetScpQuorumset(Uint256::read_xdr(r)?),
            MessageType::ScpQuorumset => Self::ScpQuorumset(ScpQuorumSet::read_xdr(r)?),
            MessageType::ScpMessage => Self::ScpMessage(ScpEnvelope::read_xdr(r)?),
            MessageType::GetScpState => Self::GetScpState(u32::read_xdr(r)?),
            MessageType::SendMore => Self::SendMore(SendMore::read_xdr(r)?),
            MessageType::FloodAdvert => Self::FloodAdvert(FloodAdvert::read_xdr(r)?),
            MessageType::FloodDemand => Self::FloodDemand(FloodDemand::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for StellarMessage {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::ErrorMsg(v) => v.write_xdr(w)?,
            Self::Hello(v) => v.write_xdr(w)?,
            Self::Auth(v) => v.write_xdr(w)?,
            Self::DontHave(v) => v.write_xdr(w)?,
            Self::GetPeers => ().write_xdr(w)?,
            Self::Peers(v) => v.write_xdr(w)?,
            Self::GetTxSet(v) => v.write_xdr(w)?,
            Self::TxSet(v) => v.write_xdr(w)?,
            Self::GeneralizedTxSet(v) => v.write_xdr(w)?,
            Self::Transaction(v) => v.write_xdr(w)?,
            Self::SurveyRequest(v) => v.write_xdr(w)?,
            Self::SurveyResponse(v) => v.write_xdr(w)?,
            Self::GetScpQuorumset(v) => v.write_xdr(w)?,
            Self::ScpQuorumset(v) => v.write_xdr(w)?,
            Self::ScpMessage(v) => v.write_xdr(w)?,
            Self::GetScpState(v) => v.write_xdr(w)?,
            Self::SendMore(v) => v.write_xdr(w)?,
            Self::FloodAdvert(v) => v.write_xdr(w)?,
            Self::FloodDemand(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// AuthenticatedMessageV0 is an XDR NestedStruct defines as:
//
//   struct
//        {
//            uint64 sequence;
//            StellarMessage message;
//            HmacSha256Mac mac;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AuthenticatedMessageV0 {
    pub sequence: u64,
    pub message: StellarMessage,
    pub mac: HmacSha256Mac,
}

impl ReadXdr for AuthenticatedMessageV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            sequence: u64::read_xdr(r)?,
            message: StellarMessage::read_xdr(r)?,
            mac: HmacSha256Mac::read_xdr(r)?,
        })
    }
}

impl WriteXdr for AuthenticatedMessageV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.sequence.write_xdr(w)?;
        self.message.write_xdr(w)?;
        self.mac.write_xdr(w)?;
        Ok(())
    }
}

// AuthenticatedMessage is an XDR Union defines as:
//
//   union AuthenticatedMessage switch (uint32 v)
//    {
//    case 0:
//        struct
//        {
//            uint64 sequence;
//            StellarMessage message;
//            HmacSha256Mac mac;
//        } v0;
//    };
//
// union with discriminant u32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum AuthenticatedMessage {
    V0(AuthenticatedMessageV0),
}

impl AuthenticatedMessage {
    pub const VARIANTS: [u32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0(_) => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> u32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(_) => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [u32; 1] {
        Self::VARIANTS
    }
}

impl Name for AuthenticatedMessage {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<u32> for AuthenticatedMessage {
    #[must_use]
    fn discriminant(&self) -> u32 {
        Self::discriminant(self)
    }
}

impl Variants<u32> for AuthenticatedMessage {
    fn variants() -> slice::Iter<'static, u32> {
        Self::VARIANTS.iter()
    }
}

impl Union<u32> for AuthenticatedMessage {}

impl ReadXdr for AuthenticatedMessage {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: u32 = <u32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0(AuthenticatedMessageV0::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for AuthenticatedMessage {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// LiquidityPoolParameters is an XDR Union defines as:
//
//   union LiquidityPoolParameters switch (LiquidityPoolType type)
//    {
//    case LIQUIDITY_POOL_CONSTANT_PRODUCT:
//        LiquidityPoolConstantProductParameters constantProduct;
//    };
//
// union with discriminant LiquidityPoolType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LiquidityPoolParameters {
    LiquidityPoolConstantProduct(LiquidityPoolConstantProductParameters),
}

impl LiquidityPoolParameters {
    pub const VARIANTS: [LiquidityPoolType; 1] = [LiquidityPoolType::LiquidityPoolConstantProduct];
    pub const VARIANTS_STR: [&'static str; 1] = ["LiquidityPoolConstantProduct"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::LiquidityPoolConstantProduct(_) => "LiquidityPoolConstantProduct",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> LiquidityPoolType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::LiquidityPoolConstantProduct(_) => {
                LiquidityPoolType::LiquidityPoolConstantProduct
            }
        }
    }

    #[must_use]
    pub const fn variants() -> [LiquidityPoolType; 1] {
        Self::VARIANTS
    }
}

impl Name for LiquidityPoolParameters {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<LiquidityPoolType> for LiquidityPoolParameters {
    #[must_use]
    fn discriminant(&self) -> LiquidityPoolType {
        Self::discriminant(self)
    }
}

impl Variants<LiquidityPoolType> for LiquidityPoolParameters {
    fn variants() -> slice::Iter<'static, LiquidityPoolType> {
        Self::VARIANTS.iter()
    }
}

impl Union<LiquidityPoolType> for LiquidityPoolParameters {}

impl ReadXdr for LiquidityPoolParameters {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: LiquidityPoolType = <LiquidityPoolType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            LiquidityPoolType::LiquidityPoolConstantProduct => Self::LiquidityPoolConstantProduct(
                LiquidityPoolConstantProductParameters::read_xdr(r)?,
            ),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LiquidityPoolParameters {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::LiquidityPoolConstantProduct(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// MuxedAccountMed25519 is an XDR NestedStruct defines as:
//
//   struct
//        {
//            uint64 id;
//            uint256 ed25519;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct MuxedAccountMed25519 {
    pub id: u64,
    pub ed25519: Uint256,
}

impl ReadXdr for MuxedAccountMed25519 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            id: u64::read_xdr(r)?,
            ed25519: Uint256::read_xdr(r)?,
        })
    }
}

impl WriteXdr for MuxedAccountMed25519 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.id.write_xdr(w)?;
        self.ed25519.write_xdr(w)?;
        Ok(())
    }
}

// MuxedAccount is an XDR Union defines as:
//
//   union MuxedAccount switch (CryptoKeyType type)
//    {
//    case KEY_TYPE_ED25519:
//        uint256 ed25519;
//    case KEY_TYPE_MUXED_ED25519:
//        struct
//        {
//            uint64 id;
//            uint256 ed25519;
//        } med25519;
//    };
//
// union with discriminant CryptoKeyType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum MuxedAccount {
    Ed25519(Uint256),
    MuxedEd25519(MuxedAccountMed25519),
}

impl MuxedAccount {
    pub const VARIANTS: [CryptoKeyType; 2] = [CryptoKeyType::Ed25519, CryptoKeyType::MuxedEd25519];
    pub const VARIANTS_STR: [&'static str; 2] = ["Ed25519", "MuxedEd25519"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Ed25519(_) => "Ed25519",
            Self::MuxedEd25519(_) => "MuxedEd25519",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> CryptoKeyType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Ed25519(_) => CryptoKeyType::Ed25519,
            Self::MuxedEd25519(_) => CryptoKeyType::MuxedEd25519,
        }
    }

    #[must_use]
    pub const fn variants() -> [CryptoKeyType; 2] {
        Self::VARIANTS
    }
}

impl Name for MuxedAccount {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<CryptoKeyType> for MuxedAccount {
    #[must_use]
    fn discriminant(&self) -> CryptoKeyType {
        Self::discriminant(self)
    }
}

impl Variants<CryptoKeyType> for MuxedAccount {
    fn variants() -> slice::Iter<'static, CryptoKeyType> {
        Self::VARIANTS.iter()
    }
}

impl Union<CryptoKeyType> for MuxedAccount {}

impl ReadXdr for MuxedAccount {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: CryptoKeyType = <CryptoKeyType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            CryptoKeyType::Ed25519 => Self::Ed25519(Uint256::read_xdr(r)?),
            CryptoKeyType::MuxedEd25519 => Self::MuxedEd25519(MuxedAccountMed25519::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for MuxedAccount {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Ed25519(v) => v.write_xdr(w)?,
            Self::MuxedEd25519(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// DecoratedSignature is an XDR Struct defines as:
//
//   struct DecoratedSignature
//    {
//        SignatureHint hint;  // last 4 bytes of the public key, used as a hint
//        Signature signature; // actual signature
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct DecoratedSignature {
    pub hint: SignatureHint,
    pub signature: Signature,
}

impl ReadXdr for DecoratedSignature {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            hint: SignatureHint::read_xdr(r)?,
            signature: Signature::read_xdr(r)?,
        })
    }
}

impl WriteXdr for DecoratedSignature {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.hint.write_xdr(w)?;
        self.signature.write_xdr(w)?;
        Ok(())
    }
}

// LedgerFootprint is an XDR Struct defines as:
//
//   struct LedgerFootprint
//    {
//        LedgerKey readOnly<>;
//        LedgerKey readWrite<>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerFootprint {
    pub read_only: VecM<LedgerKey>,
    pub read_write: VecM<LedgerKey>,
}

impl ReadXdr for LedgerFootprint {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            read_only: VecM::<LedgerKey>::read_xdr(r)?,
            read_write: VecM::<LedgerKey>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerFootprint {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.read_only.write_xdr(w)?;
        self.read_write.write_xdr(w)?;
        Ok(())
    }
}

// OperationType is an XDR Enum defines as:
//
//   enum OperationType
//    {
//        CREATE_ACCOUNT = 0,
//        PAYMENT = 1,
//        PATH_PAYMENT_STRICT_RECEIVE = 2,
//        MANAGE_SELL_OFFER = 3,
//        CREATE_PASSIVE_SELL_OFFER = 4,
//        SET_OPTIONS = 5,
//        CHANGE_TRUST = 6,
//        ALLOW_TRUST = 7,
//        ACCOUNT_MERGE = 8,
//        INFLATION = 9,
//        MANAGE_DATA = 10,
//        BUMP_SEQUENCE = 11,
//        MANAGE_BUY_OFFER = 12,
//        PATH_PAYMENT_STRICT_SEND = 13,
//        CREATE_CLAIMABLE_BALANCE = 14,
//        CLAIM_CLAIMABLE_BALANCE = 15,
//        BEGIN_SPONSORING_FUTURE_RESERVES = 16,
//        END_SPONSORING_FUTURE_RESERVES = 17,
//        REVOKE_SPONSORSHIP = 18,
//        CLAWBACK = 19,
//        CLAWBACK_CLAIMABLE_BALANCE = 20,
//        SET_TRUST_LINE_FLAGS = 21,
//        LIQUIDITY_POOL_DEPOSIT = 22,
//        LIQUIDITY_POOL_WITHDRAW = 23,
//        INVOKE_HOST_FUNCTION = 24
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum OperationType {
    CreateAccount = 0,
    Payment = 1,
    PathPaymentStrictReceive = 2,
    ManageSellOffer = 3,
    CreatePassiveSellOffer = 4,
    SetOptions = 5,
    ChangeTrust = 6,
    AllowTrust = 7,
    AccountMerge = 8,
    Inflation = 9,
    ManageData = 10,
    BumpSequence = 11,
    ManageBuyOffer = 12,
    PathPaymentStrictSend = 13,
    CreateClaimableBalance = 14,
    ClaimClaimableBalance = 15,
    BeginSponsoringFutureReserves = 16,
    EndSponsoringFutureReserves = 17,
    RevokeSponsorship = 18,
    Clawback = 19,
    ClawbackClaimableBalance = 20,
    SetTrustLineFlags = 21,
    LiquidityPoolDeposit = 22,
    LiquidityPoolWithdraw = 23,
    InvokeHostFunction = 24,
}

impl OperationType {
    pub const VARIANTS: [OperationType; 25] = [
        OperationType::CreateAccount,
        OperationType::Payment,
        OperationType::PathPaymentStrictReceive,
        OperationType::ManageSellOffer,
        OperationType::CreatePassiveSellOffer,
        OperationType::SetOptions,
        OperationType::ChangeTrust,
        OperationType::AllowTrust,
        OperationType::AccountMerge,
        OperationType::Inflation,
        OperationType::ManageData,
        OperationType::BumpSequence,
        OperationType::ManageBuyOffer,
        OperationType::PathPaymentStrictSend,
        OperationType::CreateClaimableBalance,
        OperationType::ClaimClaimableBalance,
        OperationType::BeginSponsoringFutureReserves,
        OperationType::EndSponsoringFutureReserves,
        OperationType::RevokeSponsorship,
        OperationType::Clawback,
        OperationType::ClawbackClaimableBalance,
        OperationType::SetTrustLineFlags,
        OperationType::LiquidityPoolDeposit,
        OperationType::LiquidityPoolWithdraw,
        OperationType::InvokeHostFunction,
    ];
    pub const VARIANTS_STR: [&'static str; 25] = [
        "CreateAccount",
        "Payment",
        "PathPaymentStrictReceive",
        "ManageSellOffer",
        "CreatePassiveSellOffer",
        "SetOptions",
        "ChangeTrust",
        "AllowTrust",
        "AccountMerge",
        "Inflation",
        "ManageData",
        "BumpSequence",
        "ManageBuyOffer",
        "PathPaymentStrictSend",
        "CreateClaimableBalance",
        "ClaimClaimableBalance",
        "BeginSponsoringFutureReserves",
        "EndSponsoringFutureReserves",
        "RevokeSponsorship",
        "Clawback",
        "ClawbackClaimableBalance",
        "SetTrustLineFlags",
        "LiquidityPoolDeposit",
        "LiquidityPoolWithdraw",
        "InvokeHostFunction",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::CreateAccount => "CreateAccount",
            Self::Payment => "Payment",
            Self::PathPaymentStrictReceive => "PathPaymentStrictReceive",
            Self::ManageSellOffer => "ManageSellOffer",
            Self::CreatePassiveSellOffer => "CreatePassiveSellOffer",
            Self::SetOptions => "SetOptions",
            Self::ChangeTrust => "ChangeTrust",
            Self::AllowTrust => "AllowTrust",
            Self::AccountMerge => "AccountMerge",
            Self::Inflation => "Inflation",
            Self::ManageData => "ManageData",
            Self::BumpSequence => "BumpSequence",
            Self::ManageBuyOffer => "ManageBuyOffer",
            Self::PathPaymentStrictSend => "PathPaymentStrictSend",
            Self::CreateClaimableBalance => "CreateClaimableBalance",
            Self::ClaimClaimableBalance => "ClaimClaimableBalance",
            Self::BeginSponsoringFutureReserves => "BeginSponsoringFutureReserves",
            Self::EndSponsoringFutureReserves => "EndSponsoringFutureReserves",
            Self::RevokeSponsorship => "RevokeSponsorship",
            Self::Clawback => "Clawback",
            Self::ClawbackClaimableBalance => "ClawbackClaimableBalance",
            Self::SetTrustLineFlags => "SetTrustLineFlags",
            Self::LiquidityPoolDeposit => "LiquidityPoolDeposit",
            Self::LiquidityPoolWithdraw => "LiquidityPoolWithdraw",
            Self::InvokeHostFunction => "InvokeHostFunction",
        }
    }

    #[must_use]
    pub const fn variants() -> [OperationType; 25] {
        Self::VARIANTS
    }
}

impl Name for OperationType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<OperationType> for OperationType {
    fn variants() -> slice::Iter<'static, OperationType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for OperationType {}

impl fmt::Display for OperationType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for OperationType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => OperationType::CreateAccount,
            1 => OperationType::Payment,
            2 => OperationType::PathPaymentStrictReceive,
            3 => OperationType::ManageSellOffer,
            4 => OperationType::CreatePassiveSellOffer,
            5 => OperationType::SetOptions,
            6 => OperationType::ChangeTrust,
            7 => OperationType::AllowTrust,
            8 => OperationType::AccountMerge,
            9 => OperationType::Inflation,
            10 => OperationType::ManageData,
            11 => OperationType::BumpSequence,
            12 => OperationType::ManageBuyOffer,
            13 => OperationType::PathPaymentStrictSend,
            14 => OperationType::CreateClaimableBalance,
            15 => OperationType::ClaimClaimableBalance,
            16 => OperationType::BeginSponsoringFutureReserves,
            17 => OperationType::EndSponsoringFutureReserves,
            18 => OperationType::RevokeSponsorship,
            19 => OperationType::Clawback,
            20 => OperationType::ClawbackClaimableBalance,
            21 => OperationType::SetTrustLineFlags,
            22 => OperationType::LiquidityPoolDeposit,
            23 => OperationType::LiquidityPoolWithdraw,
            24 => OperationType::InvokeHostFunction,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<OperationType> for i32 {
    #[must_use]
    fn from(e: OperationType) -> Self {
        e as Self
    }
}

impl ReadXdr for OperationType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for OperationType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// CreateAccountOp is an XDR Struct defines as:
//
//   struct CreateAccountOp
//    {
//        AccountID destination; // account to create
//        int64 startingBalance; // amount they end up with
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct CreateAccountOp {
    pub destination: AccountId,
    pub starting_balance: i64,
}

impl ReadXdr for CreateAccountOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            destination: AccountId::read_xdr(r)?,
            starting_balance: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for CreateAccountOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.destination.write_xdr(w)?;
        self.starting_balance.write_xdr(w)?;
        Ok(())
    }
}

// PaymentOp is an XDR Struct defines as:
//
//   struct PaymentOp
//    {
//        MuxedAccount destination; // recipient of the payment
//        Asset asset;              // what they end up with
//        int64 amount;             // amount they end up with
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PaymentOp {
    pub destination: MuxedAccount,
    pub asset: Asset,
    pub amount: i64,
}

impl ReadXdr for PaymentOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            destination: MuxedAccount::read_xdr(r)?,
            asset: Asset::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PaymentOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.destination.write_xdr(w)?;
        self.asset.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        Ok(())
    }
}

// PathPaymentStrictReceiveOp is an XDR Struct defines as:
//
//   struct PathPaymentStrictReceiveOp
//    {
//        Asset sendAsset; // asset we pay with
//        int64 sendMax;   // the maximum amount of sendAsset to
//                         // send (excluding fees).
//                         // The operation will fail if can't be met
//
//        MuxedAccount destination; // recipient of the payment
//        Asset destAsset;          // what they end up with
//        int64 destAmount;         // amount they end up with
//
//        Asset path<5>; // additional hops it must go through to get there
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PathPaymentStrictReceiveOp {
    pub send_asset: Asset,
    pub send_max: i64,
    pub destination: MuxedAccount,
    pub dest_asset: Asset,
    pub dest_amount: i64,
    pub path: VecM<Asset, 5>,
}

impl ReadXdr for PathPaymentStrictReceiveOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            send_asset: Asset::read_xdr(r)?,
            send_max: i64::read_xdr(r)?,
            destination: MuxedAccount::read_xdr(r)?,
            dest_asset: Asset::read_xdr(r)?,
            dest_amount: i64::read_xdr(r)?,
            path: VecM::<Asset, 5>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PathPaymentStrictReceiveOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.send_asset.write_xdr(w)?;
        self.send_max.write_xdr(w)?;
        self.destination.write_xdr(w)?;
        self.dest_asset.write_xdr(w)?;
        self.dest_amount.write_xdr(w)?;
        self.path.write_xdr(w)?;
        Ok(())
    }
}

// PathPaymentStrictSendOp is an XDR Struct defines as:
//
//   struct PathPaymentStrictSendOp
//    {
//        Asset sendAsset;  // asset we pay with
//        int64 sendAmount; // amount of sendAsset to send (excluding fees)
//
//        MuxedAccount destination; // recipient of the payment
//        Asset destAsset;          // what they end up with
//        int64 destMin;            // the minimum amount of dest asset to
//                                  // be received
//                                  // The operation will fail if it can't be met
//
//        Asset path<5>; // additional hops it must go through to get there
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PathPaymentStrictSendOp {
    pub send_asset: Asset,
    pub send_amount: i64,
    pub destination: MuxedAccount,
    pub dest_asset: Asset,
    pub dest_min: i64,
    pub path: VecM<Asset, 5>,
}

impl ReadXdr for PathPaymentStrictSendOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            send_asset: Asset::read_xdr(r)?,
            send_amount: i64::read_xdr(r)?,
            destination: MuxedAccount::read_xdr(r)?,
            dest_asset: Asset::read_xdr(r)?,
            dest_min: i64::read_xdr(r)?,
            path: VecM::<Asset, 5>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PathPaymentStrictSendOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.send_asset.write_xdr(w)?;
        self.send_amount.write_xdr(w)?;
        self.destination.write_xdr(w)?;
        self.dest_asset.write_xdr(w)?;
        self.dest_min.write_xdr(w)?;
        self.path.write_xdr(w)?;
        Ok(())
    }
}

// ManageSellOfferOp is an XDR Struct defines as:
//
//   struct ManageSellOfferOp
//    {
//        Asset selling;
//        Asset buying;
//        int64 amount; // amount being sold. if set to 0, delete the offer
//        Price price;  // price of thing being sold in terms of what you are buying
//
//        // 0=create a new offer, otherwise edit an existing offer
//        int64 offerID;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ManageSellOfferOp {
    pub selling: Asset,
    pub buying: Asset,
    pub amount: i64,
    pub price: Price,
    pub offer_id: i64,
}

impl ReadXdr for ManageSellOfferOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            selling: Asset::read_xdr(r)?,
            buying: Asset::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
            price: Price::read_xdr(r)?,
            offer_id: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ManageSellOfferOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.selling.write_xdr(w)?;
        self.buying.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        self.price.write_xdr(w)?;
        self.offer_id.write_xdr(w)?;
        Ok(())
    }
}

// ManageBuyOfferOp is an XDR Struct defines as:
//
//   struct ManageBuyOfferOp
//    {
//        Asset selling;
//        Asset buying;
//        int64 buyAmount; // amount being bought. if set to 0, delete the offer
//        Price price;     // price of thing being bought in terms of what you are
//                         // selling
//
//        // 0=create a new offer, otherwise edit an existing offer
//        int64 offerID;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ManageBuyOfferOp {
    pub selling: Asset,
    pub buying: Asset,
    pub buy_amount: i64,
    pub price: Price,
    pub offer_id: i64,
}

impl ReadXdr for ManageBuyOfferOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            selling: Asset::read_xdr(r)?,
            buying: Asset::read_xdr(r)?,
            buy_amount: i64::read_xdr(r)?,
            price: Price::read_xdr(r)?,
            offer_id: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ManageBuyOfferOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.selling.write_xdr(w)?;
        self.buying.write_xdr(w)?;
        self.buy_amount.write_xdr(w)?;
        self.price.write_xdr(w)?;
        self.offer_id.write_xdr(w)?;
        Ok(())
    }
}

// CreatePassiveSellOfferOp is an XDR Struct defines as:
//
//   struct CreatePassiveSellOfferOp
//    {
//        Asset selling; // A
//        Asset buying;  // B
//        int64 amount;  // amount taker gets
//        Price price;   // cost of A in terms of B
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct CreatePassiveSellOfferOp {
    pub selling: Asset,
    pub buying: Asset,
    pub amount: i64,
    pub price: Price,
}

impl ReadXdr for CreatePassiveSellOfferOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            selling: Asset::read_xdr(r)?,
            buying: Asset::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
            price: Price::read_xdr(r)?,
        })
    }
}

impl WriteXdr for CreatePassiveSellOfferOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.selling.write_xdr(w)?;
        self.buying.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        self.price.write_xdr(w)?;
        Ok(())
    }
}

// SetOptionsOp is an XDR Struct defines as:
//
//   struct SetOptionsOp
//    {
//        AccountID* inflationDest; // sets the inflation destination
//
//        uint32* clearFlags; // which flags to clear
//        uint32* setFlags;   // which flags to set
//
//        // account threshold manipulation
//        uint32* masterWeight; // weight of the master account
//        uint32* lowThreshold;
//        uint32* medThreshold;
//        uint32* highThreshold;
//
//        string32* homeDomain; // sets the home domain
//
//        // Add, update or remove a signer for the account
//        // signer is deleted if the weight is 0
//        Signer* signer;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SetOptionsOp {
    pub inflation_dest: Option<AccountId>,
    pub clear_flags: Option<u32>,
    pub set_flags: Option<u32>,
    pub master_weight: Option<u32>,
    pub low_threshold: Option<u32>,
    pub med_threshold: Option<u32>,
    pub high_threshold: Option<u32>,
    pub home_domain: Option<StringM<32>>,
    pub signer: Option<Signer>,
}

impl ReadXdr for SetOptionsOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            inflation_dest: Option::<AccountId>::read_xdr(r)?,
            clear_flags: Option::<u32>::read_xdr(r)?,
            set_flags: Option::<u32>::read_xdr(r)?,
            master_weight: Option::<u32>::read_xdr(r)?,
            low_threshold: Option::<u32>::read_xdr(r)?,
            med_threshold: Option::<u32>::read_xdr(r)?,
            high_threshold: Option::<u32>::read_xdr(r)?,
            home_domain: Option::<StringM<32>>::read_xdr(r)?,
            signer: Option::<Signer>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SetOptionsOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.inflation_dest.write_xdr(w)?;
        self.clear_flags.write_xdr(w)?;
        self.set_flags.write_xdr(w)?;
        self.master_weight.write_xdr(w)?;
        self.low_threshold.write_xdr(w)?;
        self.med_threshold.write_xdr(w)?;
        self.high_threshold.write_xdr(w)?;
        self.home_domain.write_xdr(w)?;
        self.signer.write_xdr(w)?;
        Ok(())
    }
}

// ChangeTrustAsset is an XDR Union defines as:
//
//   union ChangeTrustAsset switch (AssetType type)
//    {
//    case ASSET_TYPE_NATIVE: // Not credit
//        void;
//
//    case ASSET_TYPE_CREDIT_ALPHANUM4:
//        AlphaNum4 alphaNum4;
//
//    case ASSET_TYPE_CREDIT_ALPHANUM12:
//        AlphaNum12 alphaNum12;
//
//    case ASSET_TYPE_POOL_SHARE:
//        LiquidityPoolParameters liquidityPool;
//
//        // add other asset types here in the future
//    };
//
// union with discriminant AssetType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ChangeTrustAsset {
    Native,
    CreditAlphanum4(AlphaNum4),
    CreditAlphanum12(AlphaNum12),
    PoolShare(LiquidityPoolParameters),
}

impl ChangeTrustAsset {
    pub const VARIANTS: [AssetType; 4] = [
        AssetType::Native,
        AssetType::CreditAlphanum4,
        AssetType::CreditAlphanum12,
        AssetType::PoolShare,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Native", "CreditAlphanum4", "CreditAlphanum12", "PoolShare"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Native => "Native",
            Self::CreditAlphanum4(_) => "CreditAlphanum4",
            Self::CreditAlphanum12(_) => "CreditAlphanum12",
            Self::PoolShare(_) => "PoolShare",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> AssetType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Native => AssetType::Native,
            Self::CreditAlphanum4(_) => AssetType::CreditAlphanum4,
            Self::CreditAlphanum12(_) => AssetType::CreditAlphanum12,
            Self::PoolShare(_) => AssetType::PoolShare,
        }
    }

    #[must_use]
    pub const fn variants() -> [AssetType; 4] {
        Self::VARIANTS
    }
}

impl Name for ChangeTrustAsset {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<AssetType> for ChangeTrustAsset {
    #[must_use]
    fn discriminant(&self) -> AssetType {
        Self::discriminant(self)
    }
}

impl Variants<AssetType> for ChangeTrustAsset {
    fn variants() -> slice::Iter<'static, AssetType> {
        Self::VARIANTS.iter()
    }
}

impl Union<AssetType> for ChangeTrustAsset {}

impl ReadXdr for ChangeTrustAsset {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: AssetType = <AssetType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            AssetType::Native => Self::Native,
            AssetType::CreditAlphanum4 => Self::CreditAlphanum4(AlphaNum4::read_xdr(r)?),
            AssetType::CreditAlphanum12 => Self::CreditAlphanum12(AlphaNum12::read_xdr(r)?),
            AssetType::PoolShare => Self::PoolShare(LiquidityPoolParameters::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ChangeTrustAsset {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Native => ().write_xdr(w)?,
            Self::CreditAlphanum4(v) => v.write_xdr(w)?,
            Self::CreditAlphanum12(v) => v.write_xdr(w)?,
            Self::PoolShare(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ChangeTrustOp is an XDR Struct defines as:
//
//   struct ChangeTrustOp
//    {
//        ChangeTrustAsset line;
//
//        // if limit is set to 0, deletes the trust line
//        int64 limit;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ChangeTrustOp {
    pub line: ChangeTrustAsset,
    pub limit: i64,
}

impl ReadXdr for ChangeTrustOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            line: ChangeTrustAsset::read_xdr(r)?,
            limit: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ChangeTrustOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.line.write_xdr(w)?;
        self.limit.write_xdr(w)?;
        Ok(())
    }
}

// AllowTrustOp is an XDR Struct defines as:
//
//   struct AllowTrustOp
//    {
//        AccountID trustor;
//        AssetCode asset;
//
//        // One of 0, AUTHORIZED_FLAG, or AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG
//        uint32 authorize;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AllowTrustOp {
    pub trustor: AccountId,
    pub asset: AssetCode,
    pub authorize: u32,
}

impl ReadXdr for AllowTrustOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            trustor: AccountId::read_xdr(r)?,
            asset: AssetCode::read_xdr(r)?,
            authorize: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for AllowTrustOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.trustor.write_xdr(w)?;
        self.asset.write_xdr(w)?;
        self.authorize.write_xdr(w)?;
        Ok(())
    }
}

// ManageDataOp is an XDR Struct defines as:
//
//   struct ManageDataOp
//    {
//        string64 dataName;
//        DataValue* dataValue; // set to null to clear
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ManageDataOp {
    pub data_name: StringM<64>,
    pub data_value: Option<DataValue>,
}

impl ReadXdr for ManageDataOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            data_name: StringM::<64>::read_xdr(r)?,
            data_value: Option::<DataValue>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ManageDataOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.data_name.write_xdr(w)?;
        self.data_value.write_xdr(w)?;
        Ok(())
    }
}

// BumpSequenceOp is an XDR Struct defines as:
//
//   struct BumpSequenceOp
//    {
//        SequenceNumber bumpTo;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct BumpSequenceOp {
    pub bump_to: SequenceNumber,
}

impl ReadXdr for BumpSequenceOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            bump_to: SequenceNumber::read_xdr(r)?,
        })
    }
}

impl WriteXdr for BumpSequenceOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.bump_to.write_xdr(w)?;
        Ok(())
    }
}

// CreateClaimableBalanceOp is an XDR Struct defines as:
//
//   struct CreateClaimableBalanceOp
//    {
//        Asset asset;
//        int64 amount;
//        Claimant claimants<10>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct CreateClaimableBalanceOp {
    pub asset: Asset,
    pub amount: i64,
    pub claimants: VecM<Claimant, 10>,
}

impl ReadXdr for CreateClaimableBalanceOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            asset: Asset::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
            claimants: VecM::<Claimant, 10>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for CreateClaimableBalanceOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.asset.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        self.claimants.write_xdr(w)?;
        Ok(())
    }
}

// ClaimClaimableBalanceOp is an XDR Struct defines as:
//
//   struct ClaimClaimableBalanceOp
//    {
//        ClaimableBalanceID balanceID;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ClaimClaimableBalanceOp {
    pub balance_id: ClaimableBalanceId,
}

impl ReadXdr for ClaimClaimableBalanceOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            balance_id: ClaimableBalanceId::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ClaimClaimableBalanceOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.balance_id.write_xdr(w)?;
        Ok(())
    }
}

// BeginSponsoringFutureReservesOp is an XDR Struct defines as:
//
//   struct BeginSponsoringFutureReservesOp
//    {
//        AccountID sponsoredID;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct BeginSponsoringFutureReservesOp {
    pub sponsored_id: AccountId,
}

impl ReadXdr for BeginSponsoringFutureReservesOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            sponsored_id: AccountId::read_xdr(r)?,
        })
    }
}

impl WriteXdr for BeginSponsoringFutureReservesOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.sponsored_id.write_xdr(w)?;
        Ok(())
    }
}

// RevokeSponsorshipType is an XDR Enum defines as:
//
//   enum RevokeSponsorshipType
//    {
//        REVOKE_SPONSORSHIP_LEDGER_ENTRY = 0,
//        REVOKE_SPONSORSHIP_SIGNER = 1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum RevokeSponsorshipType {
    LedgerEntry = 0,
    Signer = 1,
}

impl RevokeSponsorshipType {
    pub const VARIANTS: [RevokeSponsorshipType; 2] = [
        RevokeSponsorshipType::LedgerEntry,
        RevokeSponsorshipType::Signer,
    ];
    pub const VARIANTS_STR: [&'static str; 2] = ["LedgerEntry", "Signer"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::LedgerEntry => "LedgerEntry",
            Self::Signer => "Signer",
        }
    }

    #[must_use]
    pub const fn variants() -> [RevokeSponsorshipType; 2] {
        Self::VARIANTS
    }
}

impl Name for RevokeSponsorshipType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<RevokeSponsorshipType> for RevokeSponsorshipType {
    fn variants() -> slice::Iter<'static, RevokeSponsorshipType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for RevokeSponsorshipType {}

impl fmt::Display for RevokeSponsorshipType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for RevokeSponsorshipType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => RevokeSponsorshipType::LedgerEntry,
            1 => RevokeSponsorshipType::Signer,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<RevokeSponsorshipType> for i32 {
    #[must_use]
    fn from(e: RevokeSponsorshipType) -> Self {
        e as Self
    }
}

impl ReadXdr for RevokeSponsorshipType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for RevokeSponsorshipType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// RevokeSponsorshipOpSigner is an XDR NestedStruct defines as:
//
//   struct
//        {
//            AccountID accountID;
//            SignerKey signerKey;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct RevokeSponsorshipOpSigner {
    pub account_id: AccountId,
    pub signer_key: SignerKey,
}

impl ReadXdr for RevokeSponsorshipOpSigner {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            account_id: AccountId::read_xdr(r)?,
            signer_key: SignerKey::read_xdr(r)?,
        })
    }
}

impl WriteXdr for RevokeSponsorshipOpSigner {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.account_id.write_xdr(w)?;
        self.signer_key.write_xdr(w)?;
        Ok(())
    }
}

// RevokeSponsorshipOp is an XDR Union defines as:
//
//   union RevokeSponsorshipOp switch (RevokeSponsorshipType type)
//    {
//    case REVOKE_SPONSORSHIP_LEDGER_ENTRY:
//        LedgerKey ledgerKey;
//    case REVOKE_SPONSORSHIP_SIGNER:
//        struct
//        {
//            AccountID accountID;
//            SignerKey signerKey;
//        } signer;
//    };
//
// union with discriminant RevokeSponsorshipType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum RevokeSponsorshipOp {
    LedgerEntry(LedgerKey),
    Signer(RevokeSponsorshipOpSigner),
}

impl RevokeSponsorshipOp {
    pub const VARIANTS: [RevokeSponsorshipType; 2] = [
        RevokeSponsorshipType::LedgerEntry,
        RevokeSponsorshipType::Signer,
    ];
    pub const VARIANTS_STR: [&'static str; 2] = ["LedgerEntry", "Signer"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::LedgerEntry(_) => "LedgerEntry",
            Self::Signer(_) => "Signer",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> RevokeSponsorshipType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::LedgerEntry(_) => RevokeSponsorshipType::LedgerEntry,
            Self::Signer(_) => RevokeSponsorshipType::Signer,
        }
    }

    #[must_use]
    pub const fn variants() -> [RevokeSponsorshipType; 2] {
        Self::VARIANTS
    }
}

impl Name for RevokeSponsorshipOp {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<RevokeSponsorshipType> for RevokeSponsorshipOp {
    #[must_use]
    fn discriminant(&self) -> RevokeSponsorshipType {
        Self::discriminant(self)
    }
}

impl Variants<RevokeSponsorshipType> for RevokeSponsorshipOp {
    fn variants() -> slice::Iter<'static, RevokeSponsorshipType> {
        Self::VARIANTS.iter()
    }
}

impl Union<RevokeSponsorshipType> for RevokeSponsorshipOp {}

impl ReadXdr for RevokeSponsorshipOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: RevokeSponsorshipType = <RevokeSponsorshipType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            RevokeSponsorshipType::LedgerEntry => Self::LedgerEntry(LedgerKey::read_xdr(r)?),
            RevokeSponsorshipType::Signer => Self::Signer(RevokeSponsorshipOpSigner::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for RevokeSponsorshipOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::LedgerEntry(v) => v.write_xdr(w)?,
            Self::Signer(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// ClawbackOp is an XDR Struct defines as:
//
//   struct ClawbackOp
//    {
//        Asset asset;
//        MuxedAccount from;
//        int64 amount;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ClawbackOp {
    pub asset: Asset,
    pub from: MuxedAccount,
    pub amount: i64,
}

impl ReadXdr for ClawbackOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            asset: Asset::read_xdr(r)?,
            from: MuxedAccount::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ClawbackOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.asset.write_xdr(w)?;
        self.from.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        Ok(())
    }
}

// ClawbackClaimableBalanceOp is an XDR Struct defines as:
//
//   struct ClawbackClaimableBalanceOp
//    {
//        ClaimableBalanceID balanceID;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ClawbackClaimableBalanceOp {
    pub balance_id: ClaimableBalanceId,
}

impl ReadXdr for ClawbackClaimableBalanceOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            balance_id: ClaimableBalanceId::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ClawbackClaimableBalanceOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.balance_id.write_xdr(w)?;
        Ok(())
    }
}

// SetTrustLineFlagsOp is an XDR Struct defines as:
//
//   struct SetTrustLineFlagsOp
//    {
//        AccountID trustor;
//        Asset asset;
//
//        uint32 clearFlags; // which flags to clear
//        uint32 setFlags;   // which flags to set
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SetTrustLineFlagsOp {
    pub trustor: AccountId,
    pub asset: Asset,
    pub clear_flags: u32,
    pub set_flags: u32,
}

impl ReadXdr for SetTrustLineFlagsOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            trustor: AccountId::read_xdr(r)?,
            asset: Asset::read_xdr(r)?,
            clear_flags: u32::read_xdr(r)?,
            set_flags: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SetTrustLineFlagsOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.trustor.write_xdr(w)?;
        self.asset.write_xdr(w)?;
        self.clear_flags.write_xdr(w)?;
        self.set_flags.write_xdr(w)?;
        Ok(())
    }
}

// LiquidityPoolFeeV18 is an XDR Const defines as:
//
//   const LIQUIDITY_POOL_FEE_V18 = 30;
//
pub const LIQUIDITY_POOL_FEE_V18: u64 = 30;

// LiquidityPoolDepositOp is an XDR Struct defines as:
//
//   struct LiquidityPoolDepositOp
//    {
//        PoolID liquidityPoolID;
//        int64 maxAmountA; // maximum amount of first asset to deposit
//        int64 maxAmountB; // maximum amount of second asset to deposit
//        Price minPrice;   // minimum depositA/depositB
//        Price maxPrice;   // maximum depositA/depositB
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LiquidityPoolDepositOp {
    pub liquidity_pool_id: PoolId,
    pub max_amount_a: i64,
    pub max_amount_b: i64,
    pub min_price: Price,
    pub max_price: Price,
}

impl ReadXdr for LiquidityPoolDepositOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            liquidity_pool_id: PoolId::read_xdr(r)?,
            max_amount_a: i64::read_xdr(r)?,
            max_amount_b: i64::read_xdr(r)?,
            min_price: Price::read_xdr(r)?,
            max_price: Price::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LiquidityPoolDepositOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.liquidity_pool_id.write_xdr(w)?;
        self.max_amount_a.write_xdr(w)?;
        self.max_amount_b.write_xdr(w)?;
        self.min_price.write_xdr(w)?;
        self.max_price.write_xdr(w)?;
        Ok(())
    }
}

// LiquidityPoolWithdrawOp is an XDR Struct defines as:
//
//   struct LiquidityPoolWithdrawOp
//    {
//        PoolID liquidityPoolID;
//        int64 amount;     // amount of pool shares to withdraw
//        int64 minAmountA; // minimum amount of first asset to withdraw
//        int64 minAmountB; // minimum amount of second asset to withdraw
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LiquidityPoolWithdrawOp {
    pub liquidity_pool_id: PoolId,
    pub amount: i64,
    pub min_amount_a: i64,
    pub min_amount_b: i64,
}

impl ReadXdr for LiquidityPoolWithdrawOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            liquidity_pool_id: PoolId::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
            min_amount_a: i64::read_xdr(r)?,
            min_amount_b: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LiquidityPoolWithdrawOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.liquidity_pool_id.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        self.min_amount_a.write_xdr(w)?;
        self.min_amount_b.write_xdr(w)?;
        Ok(())
    }
}

// HostFunctionType is an XDR Enum defines as:
//
//   enum HostFunctionType
//    {
//        HOST_FUNCTION_TYPE_INVOKE_CONTRACT = 0,
//        HOST_FUNCTION_TYPE_CREATE_CONTRACT = 1,
//        HOST_FUNCTION_TYPE_INSTALL_CONTRACT_CODE = 2
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum HostFunctionType {
    InvokeContract = 0,
    CreateContract = 1,
    InstallContractCode = 2,
}

impl HostFunctionType {
    pub const VARIANTS: [HostFunctionType; 3] = [
        HostFunctionType::InvokeContract,
        HostFunctionType::CreateContract,
        HostFunctionType::InstallContractCode,
    ];
    pub const VARIANTS_STR: [&'static str; 3] =
        ["InvokeContract", "CreateContract", "InstallContractCode"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::InvokeContract => "InvokeContract",
            Self::CreateContract => "CreateContract",
            Self::InstallContractCode => "InstallContractCode",
        }
    }

    #[must_use]
    pub const fn variants() -> [HostFunctionType; 3] {
        Self::VARIANTS
    }
}

impl Name for HostFunctionType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<HostFunctionType> for HostFunctionType {
    fn variants() -> slice::Iter<'static, HostFunctionType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for HostFunctionType {}

impl fmt::Display for HostFunctionType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for HostFunctionType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => HostFunctionType::InvokeContract,
            1 => HostFunctionType::CreateContract,
            2 => HostFunctionType::InstallContractCode,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<HostFunctionType> for i32 {
    #[must_use]
    fn from(e: HostFunctionType) -> Self {
        e as Self
    }
}

impl ReadXdr for HostFunctionType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for HostFunctionType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ContractIdType is an XDR Enum defines as:
//
//   enum ContractIDType
//    {
//        CONTRACT_ID_FROM_SOURCE_ACCOUNT = 0,
//        CONTRACT_ID_FROM_ED25519_PUBLIC_KEY = 1,
//        CONTRACT_ID_FROM_ASSET = 2
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ContractIdType {
    SourceAccount = 0,
    Ed25519PublicKey = 1,
    Asset = 2,
}

impl ContractIdType {
    pub const VARIANTS: [ContractIdType; 3] = [
        ContractIdType::SourceAccount,
        ContractIdType::Ed25519PublicKey,
        ContractIdType::Asset,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["SourceAccount", "Ed25519PublicKey", "Asset"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::SourceAccount => "SourceAccount",
            Self::Ed25519PublicKey => "Ed25519PublicKey",
            Self::Asset => "Asset",
        }
    }

    #[must_use]
    pub const fn variants() -> [ContractIdType; 3] {
        Self::VARIANTS
    }
}

impl Name for ContractIdType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ContractIdType> for ContractIdType {
    fn variants() -> slice::Iter<'static, ContractIdType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ContractIdType {}

impl fmt::Display for ContractIdType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ContractIdType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ContractIdType::SourceAccount,
            1 => ContractIdType::Ed25519PublicKey,
            2 => ContractIdType::Asset,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ContractIdType> for i32 {
    #[must_use]
    fn from(e: ContractIdType) -> Self {
        e as Self
    }
}

impl ReadXdr for ContractIdType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ContractIdType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ContractIdPublicKeyType is an XDR Enum defines as:
//
//   enum ContractIDPublicKeyType
//    {
//        CONTRACT_ID_PUBLIC_KEY_SOURCE_ACCOUNT = 0,
//        CONTRACT_ID_PUBLIC_KEY_ED25519 = 1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ContractIdPublicKeyType {
    SourceAccount = 0,
    Ed25519 = 1,
}

impl ContractIdPublicKeyType {
    pub const VARIANTS: [ContractIdPublicKeyType; 2] = [
        ContractIdPublicKeyType::SourceAccount,
        ContractIdPublicKeyType::Ed25519,
    ];
    pub const VARIANTS_STR: [&'static str; 2] = ["SourceAccount", "Ed25519"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::SourceAccount => "SourceAccount",
            Self::Ed25519 => "Ed25519",
        }
    }

    #[must_use]
    pub const fn variants() -> [ContractIdPublicKeyType; 2] {
        Self::VARIANTS
    }
}

impl Name for ContractIdPublicKeyType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ContractIdPublicKeyType> for ContractIdPublicKeyType {
    fn variants() -> slice::Iter<'static, ContractIdPublicKeyType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ContractIdPublicKeyType {}

impl fmt::Display for ContractIdPublicKeyType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ContractIdPublicKeyType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ContractIdPublicKeyType::SourceAccount,
            1 => ContractIdPublicKeyType::Ed25519,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ContractIdPublicKeyType> for i32 {
    #[must_use]
    fn from(e: ContractIdPublicKeyType) -> Self {
        e as Self
    }
}

impl ReadXdr for ContractIdPublicKeyType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ContractIdPublicKeyType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// InstallContractCodeArgs is an XDR Struct defines as:
//
//   struct InstallContractCodeArgs
//    {
//        opaque code<SCVAL_LIMIT>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct InstallContractCodeArgs {
    pub code: BytesM<256000>,
}

impl ReadXdr for InstallContractCodeArgs {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            code: BytesM::<256000>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for InstallContractCodeArgs {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.code.write_xdr(w)?;
        Ok(())
    }
}

// ContractIdFromEd25519PublicKey is an XDR NestedStruct defines as:
//
//   struct
//        {
//            uint256 key;
//            Signature signature;
//            uint256 salt;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ContractIdFromEd25519PublicKey {
    pub key: Uint256,
    pub signature: Signature,
    pub salt: Uint256,
}

impl ReadXdr for ContractIdFromEd25519PublicKey {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            key: Uint256::read_xdr(r)?,
            signature: Signature::read_xdr(r)?,
            salt: Uint256::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ContractIdFromEd25519PublicKey {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.key.write_xdr(w)?;
        self.signature.write_xdr(w)?;
        self.salt.write_xdr(w)?;
        Ok(())
    }
}

// ContractId is an XDR Union defines as:
//
//   union ContractID switch (ContractIDType type)
//    {
//    case CONTRACT_ID_FROM_SOURCE_ACCOUNT:
//        uint256 salt;
//    case CONTRACT_ID_FROM_ED25519_PUBLIC_KEY:
//        struct
//        {
//            uint256 key;
//            Signature signature;
//            uint256 salt;
//        } fromEd25519PublicKey;
//    case CONTRACT_ID_FROM_ASSET:
//        Asset asset;
//    };
//
// union with discriminant ContractIdType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ContractId {
    SourceAccount(Uint256),
    Ed25519PublicKey(ContractIdFromEd25519PublicKey),
    Asset(Asset),
}

impl ContractId {
    pub const VARIANTS: [ContractIdType; 3] = [
        ContractIdType::SourceAccount,
        ContractIdType::Ed25519PublicKey,
        ContractIdType::Asset,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["SourceAccount", "Ed25519PublicKey", "Asset"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::SourceAccount(_) => "SourceAccount",
            Self::Ed25519PublicKey(_) => "Ed25519PublicKey",
            Self::Asset(_) => "Asset",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ContractIdType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::SourceAccount(_) => ContractIdType::SourceAccount,
            Self::Ed25519PublicKey(_) => ContractIdType::Ed25519PublicKey,
            Self::Asset(_) => ContractIdType::Asset,
        }
    }

    #[must_use]
    pub const fn variants() -> [ContractIdType; 3] {
        Self::VARIANTS
    }
}

impl Name for ContractId {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ContractIdType> for ContractId {
    #[must_use]
    fn discriminant(&self) -> ContractIdType {
        Self::discriminant(self)
    }
}

impl Variants<ContractIdType> for ContractId {
    fn variants() -> slice::Iter<'static, ContractIdType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ContractIdType> for ContractId {}

impl ReadXdr for ContractId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ContractIdType = <ContractIdType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ContractIdType::SourceAccount => Self::SourceAccount(Uint256::read_xdr(r)?),
            ContractIdType::Ed25519PublicKey => {
                Self::Ed25519PublicKey(ContractIdFromEd25519PublicKey::read_xdr(r)?)
            }
            ContractIdType::Asset => Self::Asset(Asset::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ContractId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::SourceAccount(v) => v.write_xdr(w)?,
            Self::Ed25519PublicKey(v) => v.write_xdr(w)?,
            Self::Asset(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// CreateContractArgs is an XDR Struct defines as:
//
//   struct CreateContractArgs
//    {
//        ContractID contractID;
//        SCContractCode source;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct CreateContractArgs {
    pub contract_id: ContractId,
    pub source: ScContractCode,
}

impl ReadXdr for CreateContractArgs {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            contract_id: ContractId::read_xdr(r)?,
            source: ScContractCode::read_xdr(r)?,
        })
    }
}

impl WriteXdr for CreateContractArgs {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.contract_id.write_xdr(w)?;
        self.source.write_xdr(w)?;
        Ok(())
    }
}

// HostFunction is an XDR Union defines as:
//
//   union HostFunction switch (HostFunctionType type)
//    {
//    case HOST_FUNCTION_TYPE_INVOKE_CONTRACT:
//        SCVec invokeArgs;
//    case HOST_FUNCTION_TYPE_CREATE_CONTRACT:
//        CreateContractArgs createContractArgs;
//    case HOST_FUNCTION_TYPE_INSTALL_CONTRACT_CODE:
//        InstallContractCodeArgs installContractCodeArgs;
//    };
//
// union with discriminant HostFunctionType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum HostFunction {
    InvokeContract(ScVec),
    CreateContract(CreateContractArgs),
    InstallContractCode(InstallContractCodeArgs),
}

impl HostFunction {
    pub const VARIANTS: [HostFunctionType; 3] = [
        HostFunctionType::InvokeContract,
        HostFunctionType::CreateContract,
        HostFunctionType::InstallContractCode,
    ];
    pub const VARIANTS_STR: [&'static str; 3] =
        ["InvokeContract", "CreateContract", "InstallContractCode"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::InvokeContract(_) => "InvokeContract",
            Self::CreateContract(_) => "CreateContract",
            Self::InstallContractCode(_) => "InstallContractCode",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> HostFunctionType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::InvokeContract(_) => HostFunctionType::InvokeContract,
            Self::CreateContract(_) => HostFunctionType::CreateContract,
            Self::InstallContractCode(_) => HostFunctionType::InstallContractCode,
        }
    }

    #[must_use]
    pub const fn variants() -> [HostFunctionType; 3] {
        Self::VARIANTS
    }
}

impl Name for HostFunction {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<HostFunctionType> for HostFunction {
    #[must_use]
    fn discriminant(&self) -> HostFunctionType {
        Self::discriminant(self)
    }
}

impl Variants<HostFunctionType> for HostFunction {
    fn variants() -> slice::Iter<'static, HostFunctionType> {
        Self::VARIANTS.iter()
    }
}

impl Union<HostFunctionType> for HostFunction {}

impl ReadXdr for HostFunction {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: HostFunctionType = <HostFunctionType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            HostFunctionType::InvokeContract => Self::InvokeContract(ScVec::read_xdr(r)?),
            HostFunctionType::CreateContract => {
                Self::CreateContract(CreateContractArgs::read_xdr(r)?)
            }
            HostFunctionType::InstallContractCode => {
                Self::InstallContractCode(InstallContractCodeArgs::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for HostFunction {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::InvokeContract(v) => v.write_xdr(w)?,
            Self::CreateContract(v) => v.write_xdr(w)?,
            Self::InstallContractCode(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// InvokeHostFunctionOp is an XDR Struct defines as:
//
//   struct InvokeHostFunctionOp
//    {
//        // The host function to invoke
//        HostFunction function;
//        // The footprint for this invocation
//        LedgerFootprint footprint;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct InvokeHostFunctionOp {
    pub function: HostFunction,
    pub footprint: LedgerFootprint,
}

impl ReadXdr for InvokeHostFunctionOp {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            function: HostFunction::read_xdr(r)?,
            footprint: LedgerFootprint::read_xdr(r)?,
        })
    }
}

impl WriteXdr for InvokeHostFunctionOp {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.function.write_xdr(w)?;
        self.footprint.write_xdr(w)?;
        Ok(())
    }
}

// OperationBody is an XDR NestedUnion defines as:
//
//   union switch (OperationType type)
//        {
//        case CREATE_ACCOUNT:
//            CreateAccountOp createAccountOp;
//        case PAYMENT:
//            PaymentOp paymentOp;
//        case PATH_PAYMENT_STRICT_RECEIVE:
//            PathPaymentStrictReceiveOp pathPaymentStrictReceiveOp;
//        case MANAGE_SELL_OFFER:
//            ManageSellOfferOp manageSellOfferOp;
//        case CREATE_PASSIVE_SELL_OFFER:
//            CreatePassiveSellOfferOp createPassiveSellOfferOp;
//        case SET_OPTIONS:
//            SetOptionsOp setOptionsOp;
//        case CHANGE_TRUST:
//            ChangeTrustOp changeTrustOp;
//        case ALLOW_TRUST:
//            AllowTrustOp allowTrustOp;
//        case ACCOUNT_MERGE:
//            MuxedAccount destination;
//        case INFLATION:
//            void;
//        case MANAGE_DATA:
//            ManageDataOp manageDataOp;
//        case BUMP_SEQUENCE:
//            BumpSequenceOp bumpSequenceOp;
//        case MANAGE_BUY_OFFER:
//            ManageBuyOfferOp manageBuyOfferOp;
//        case PATH_PAYMENT_STRICT_SEND:
//            PathPaymentStrictSendOp pathPaymentStrictSendOp;
//        case CREATE_CLAIMABLE_BALANCE:
//            CreateClaimableBalanceOp createClaimableBalanceOp;
//        case CLAIM_CLAIMABLE_BALANCE:
//            ClaimClaimableBalanceOp claimClaimableBalanceOp;
//        case BEGIN_SPONSORING_FUTURE_RESERVES:
//            BeginSponsoringFutureReservesOp beginSponsoringFutureReservesOp;
//        case END_SPONSORING_FUTURE_RESERVES:
//            void;
//        case REVOKE_SPONSORSHIP:
//            RevokeSponsorshipOp revokeSponsorshipOp;
//        case CLAWBACK:
//            ClawbackOp clawbackOp;
//        case CLAWBACK_CLAIMABLE_BALANCE:
//            ClawbackClaimableBalanceOp clawbackClaimableBalanceOp;
//        case SET_TRUST_LINE_FLAGS:
//            SetTrustLineFlagsOp setTrustLineFlagsOp;
//        case LIQUIDITY_POOL_DEPOSIT:
//            LiquidityPoolDepositOp liquidityPoolDepositOp;
//        case LIQUIDITY_POOL_WITHDRAW:
//            LiquidityPoolWithdrawOp liquidityPoolWithdrawOp;
//        case INVOKE_HOST_FUNCTION:
//            InvokeHostFunctionOp invokeHostFunctionOp;
//        }
//
// union with discriminant OperationType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum OperationBody {
    CreateAccount(CreateAccountOp),
    Payment(PaymentOp),
    PathPaymentStrictReceive(PathPaymentStrictReceiveOp),
    ManageSellOffer(ManageSellOfferOp),
    CreatePassiveSellOffer(CreatePassiveSellOfferOp),
    SetOptions(SetOptionsOp),
    ChangeTrust(ChangeTrustOp),
    AllowTrust(AllowTrustOp),
    AccountMerge(MuxedAccount),
    Inflation,
    ManageData(ManageDataOp),
    BumpSequence(BumpSequenceOp),
    ManageBuyOffer(ManageBuyOfferOp),
    PathPaymentStrictSend(PathPaymentStrictSendOp),
    CreateClaimableBalance(CreateClaimableBalanceOp),
    ClaimClaimableBalance(ClaimClaimableBalanceOp),
    BeginSponsoringFutureReserves(BeginSponsoringFutureReservesOp),
    EndSponsoringFutureReserves,
    RevokeSponsorship(RevokeSponsorshipOp),
    Clawback(ClawbackOp),
    ClawbackClaimableBalance(ClawbackClaimableBalanceOp),
    SetTrustLineFlags(SetTrustLineFlagsOp),
    LiquidityPoolDeposit(LiquidityPoolDepositOp),
    LiquidityPoolWithdraw(LiquidityPoolWithdrawOp),
    InvokeHostFunction(InvokeHostFunctionOp),
}

impl OperationBody {
    pub const VARIANTS: [OperationType; 25] = [
        OperationType::CreateAccount,
        OperationType::Payment,
        OperationType::PathPaymentStrictReceive,
        OperationType::ManageSellOffer,
        OperationType::CreatePassiveSellOffer,
        OperationType::SetOptions,
        OperationType::ChangeTrust,
        OperationType::AllowTrust,
        OperationType::AccountMerge,
        OperationType::Inflation,
        OperationType::ManageData,
        OperationType::BumpSequence,
        OperationType::ManageBuyOffer,
        OperationType::PathPaymentStrictSend,
        OperationType::CreateClaimableBalance,
        OperationType::ClaimClaimableBalance,
        OperationType::BeginSponsoringFutureReserves,
        OperationType::EndSponsoringFutureReserves,
        OperationType::RevokeSponsorship,
        OperationType::Clawback,
        OperationType::ClawbackClaimableBalance,
        OperationType::SetTrustLineFlags,
        OperationType::LiquidityPoolDeposit,
        OperationType::LiquidityPoolWithdraw,
        OperationType::InvokeHostFunction,
    ];
    pub const VARIANTS_STR: [&'static str; 25] = [
        "CreateAccount",
        "Payment",
        "PathPaymentStrictReceive",
        "ManageSellOffer",
        "CreatePassiveSellOffer",
        "SetOptions",
        "ChangeTrust",
        "AllowTrust",
        "AccountMerge",
        "Inflation",
        "ManageData",
        "BumpSequence",
        "ManageBuyOffer",
        "PathPaymentStrictSend",
        "CreateClaimableBalance",
        "ClaimClaimableBalance",
        "BeginSponsoringFutureReserves",
        "EndSponsoringFutureReserves",
        "RevokeSponsorship",
        "Clawback",
        "ClawbackClaimableBalance",
        "SetTrustLineFlags",
        "LiquidityPoolDeposit",
        "LiquidityPoolWithdraw",
        "InvokeHostFunction",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::CreateAccount(_) => "CreateAccount",
            Self::Payment(_) => "Payment",
            Self::PathPaymentStrictReceive(_) => "PathPaymentStrictReceive",
            Self::ManageSellOffer(_) => "ManageSellOffer",
            Self::CreatePassiveSellOffer(_) => "CreatePassiveSellOffer",
            Self::SetOptions(_) => "SetOptions",
            Self::ChangeTrust(_) => "ChangeTrust",
            Self::AllowTrust(_) => "AllowTrust",
            Self::AccountMerge(_) => "AccountMerge",
            Self::Inflation => "Inflation",
            Self::ManageData(_) => "ManageData",
            Self::BumpSequence(_) => "BumpSequence",
            Self::ManageBuyOffer(_) => "ManageBuyOffer",
            Self::PathPaymentStrictSend(_) => "PathPaymentStrictSend",
            Self::CreateClaimableBalance(_) => "CreateClaimableBalance",
            Self::ClaimClaimableBalance(_) => "ClaimClaimableBalance",
            Self::BeginSponsoringFutureReserves(_) => "BeginSponsoringFutureReserves",
            Self::EndSponsoringFutureReserves => "EndSponsoringFutureReserves",
            Self::RevokeSponsorship(_) => "RevokeSponsorship",
            Self::Clawback(_) => "Clawback",
            Self::ClawbackClaimableBalance(_) => "ClawbackClaimableBalance",
            Self::SetTrustLineFlags(_) => "SetTrustLineFlags",
            Self::LiquidityPoolDeposit(_) => "LiquidityPoolDeposit",
            Self::LiquidityPoolWithdraw(_) => "LiquidityPoolWithdraw",
            Self::InvokeHostFunction(_) => "InvokeHostFunction",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> OperationType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::CreateAccount(_) => OperationType::CreateAccount,
            Self::Payment(_) => OperationType::Payment,
            Self::PathPaymentStrictReceive(_) => OperationType::PathPaymentStrictReceive,
            Self::ManageSellOffer(_) => OperationType::ManageSellOffer,
            Self::CreatePassiveSellOffer(_) => OperationType::CreatePassiveSellOffer,
            Self::SetOptions(_) => OperationType::SetOptions,
            Self::ChangeTrust(_) => OperationType::ChangeTrust,
            Self::AllowTrust(_) => OperationType::AllowTrust,
            Self::AccountMerge(_) => OperationType::AccountMerge,
            Self::Inflation => OperationType::Inflation,
            Self::ManageData(_) => OperationType::ManageData,
            Self::BumpSequence(_) => OperationType::BumpSequence,
            Self::ManageBuyOffer(_) => OperationType::ManageBuyOffer,
            Self::PathPaymentStrictSend(_) => OperationType::PathPaymentStrictSend,
            Self::CreateClaimableBalance(_) => OperationType::CreateClaimableBalance,
            Self::ClaimClaimableBalance(_) => OperationType::ClaimClaimableBalance,
            Self::BeginSponsoringFutureReserves(_) => OperationType::BeginSponsoringFutureReserves,
            Self::EndSponsoringFutureReserves => OperationType::EndSponsoringFutureReserves,
            Self::RevokeSponsorship(_) => OperationType::RevokeSponsorship,
            Self::Clawback(_) => OperationType::Clawback,
            Self::ClawbackClaimableBalance(_) => OperationType::ClawbackClaimableBalance,
            Self::SetTrustLineFlags(_) => OperationType::SetTrustLineFlags,
            Self::LiquidityPoolDeposit(_) => OperationType::LiquidityPoolDeposit,
            Self::LiquidityPoolWithdraw(_) => OperationType::LiquidityPoolWithdraw,
            Self::InvokeHostFunction(_) => OperationType::InvokeHostFunction,
        }
    }

    #[must_use]
    pub const fn variants() -> [OperationType; 25] {
        Self::VARIANTS
    }
}

impl Name for OperationBody {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<OperationType> for OperationBody {
    #[must_use]
    fn discriminant(&self) -> OperationType {
        Self::discriminant(self)
    }
}

impl Variants<OperationType> for OperationBody {
    fn variants() -> slice::Iter<'static, OperationType> {
        Self::VARIANTS.iter()
    }
}

impl Union<OperationType> for OperationBody {}

impl ReadXdr for OperationBody {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: OperationType = <OperationType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            OperationType::CreateAccount => Self::CreateAccount(CreateAccountOp::read_xdr(r)?),
            OperationType::Payment => Self::Payment(PaymentOp::read_xdr(r)?),
            OperationType::PathPaymentStrictReceive => {
                Self::PathPaymentStrictReceive(PathPaymentStrictReceiveOp::read_xdr(r)?)
            }
            OperationType::ManageSellOffer => {
                Self::ManageSellOffer(ManageSellOfferOp::read_xdr(r)?)
            }
            OperationType::CreatePassiveSellOffer => {
                Self::CreatePassiveSellOffer(CreatePassiveSellOfferOp::read_xdr(r)?)
            }
            OperationType::SetOptions => Self::SetOptions(SetOptionsOp::read_xdr(r)?),
            OperationType::ChangeTrust => Self::ChangeTrust(ChangeTrustOp::read_xdr(r)?),
            OperationType::AllowTrust => Self::AllowTrust(AllowTrustOp::read_xdr(r)?),
            OperationType::AccountMerge => Self::AccountMerge(MuxedAccount::read_xdr(r)?),
            OperationType::Inflation => Self::Inflation,
            OperationType::ManageData => Self::ManageData(ManageDataOp::read_xdr(r)?),
            OperationType::BumpSequence => Self::BumpSequence(BumpSequenceOp::read_xdr(r)?),
            OperationType::ManageBuyOffer => Self::ManageBuyOffer(ManageBuyOfferOp::read_xdr(r)?),
            OperationType::PathPaymentStrictSend => {
                Self::PathPaymentStrictSend(PathPaymentStrictSendOp::read_xdr(r)?)
            }
            OperationType::CreateClaimableBalance => {
                Self::CreateClaimableBalance(CreateClaimableBalanceOp::read_xdr(r)?)
            }
            OperationType::ClaimClaimableBalance => {
                Self::ClaimClaimableBalance(ClaimClaimableBalanceOp::read_xdr(r)?)
            }
            OperationType::BeginSponsoringFutureReserves => {
                Self::BeginSponsoringFutureReserves(BeginSponsoringFutureReservesOp::read_xdr(r)?)
            }
            OperationType::EndSponsoringFutureReserves => Self::EndSponsoringFutureReserves,
            OperationType::RevokeSponsorship => {
                Self::RevokeSponsorship(RevokeSponsorshipOp::read_xdr(r)?)
            }
            OperationType::Clawback => Self::Clawback(ClawbackOp::read_xdr(r)?),
            OperationType::ClawbackClaimableBalance => {
                Self::ClawbackClaimableBalance(ClawbackClaimableBalanceOp::read_xdr(r)?)
            }
            OperationType::SetTrustLineFlags => {
                Self::SetTrustLineFlags(SetTrustLineFlagsOp::read_xdr(r)?)
            }
            OperationType::LiquidityPoolDeposit => {
                Self::LiquidityPoolDeposit(LiquidityPoolDepositOp::read_xdr(r)?)
            }
            OperationType::LiquidityPoolWithdraw => {
                Self::LiquidityPoolWithdraw(LiquidityPoolWithdrawOp::read_xdr(r)?)
            }
            OperationType::InvokeHostFunction => {
                Self::InvokeHostFunction(InvokeHostFunctionOp::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for OperationBody {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::CreateAccount(v) => v.write_xdr(w)?,
            Self::Payment(v) => v.write_xdr(w)?,
            Self::PathPaymentStrictReceive(v) => v.write_xdr(w)?,
            Self::ManageSellOffer(v) => v.write_xdr(w)?,
            Self::CreatePassiveSellOffer(v) => v.write_xdr(w)?,
            Self::SetOptions(v) => v.write_xdr(w)?,
            Self::ChangeTrust(v) => v.write_xdr(w)?,
            Self::AllowTrust(v) => v.write_xdr(w)?,
            Self::AccountMerge(v) => v.write_xdr(w)?,
            Self::Inflation => ().write_xdr(w)?,
            Self::ManageData(v) => v.write_xdr(w)?,
            Self::BumpSequence(v) => v.write_xdr(w)?,
            Self::ManageBuyOffer(v) => v.write_xdr(w)?,
            Self::PathPaymentStrictSend(v) => v.write_xdr(w)?,
            Self::CreateClaimableBalance(v) => v.write_xdr(w)?,
            Self::ClaimClaimableBalance(v) => v.write_xdr(w)?,
            Self::BeginSponsoringFutureReserves(v) => v.write_xdr(w)?,
            Self::EndSponsoringFutureReserves => ().write_xdr(w)?,
            Self::RevokeSponsorship(v) => v.write_xdr(w)?,
            Self::Clawback(v) => v.write_xdr(w)?,
            Self::ClawbackClaimableBalance(v) => v.write_xdr(w)?,
            Self::SetTrustLineFlags(v) => v.write_xdr(w)?,
            Self::LiquidityPoolDeposit(v) => v.write_xdr(w)?,
            Self::LiquidityPoolWithdraw(v) => v.write_xdr(w)?,
            Self::InvokeHostFunction(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// Operation is an XDR Struct defines as:
//
//   struct Operation
//    {
//        // sourceAccount is the account used to run the operation
//        // if not set, the runtime defaults to "sourceAccount" specified at
//        // the transaction level
//        MuxedAccount* sourceAccount;
//
//        union switch (OperationType type)
//        {
//        case CREATE_ACCOUNT:
//            CreateAccountOp createAccountOp;
//        case PAYMENT:
//            PaymentOp paymentOp;
//        case PATH_PAYMENT_STRICT_RECEIVE:
//            PathPaymentStrictReceiveOp pathPaymentStrictReceiveOp;
//        case MANAGE_SELL_OFFER:
//            ManageSellOfferOp manageSellOfferOp;
//        case CREATE_PASSIVE_SELL_OFFER:
//            CreatePassiveSellOfferOp createPassiveSellOfferOp;
//        case SET_OPTIONS:
//            SetOptionsOp setOptionsOp;
//        case CHANGE_TRUST:
//            ChangeTrustOp changeTrustOp;
//        case ALLOW_TRUST:
//            AllowTrustOp allowTrustOp;
//        case ACCOUNT_MERGE:
//            MuxedAccount destination;
//        case INFLATION:
//            void;
//        case MANAGE_DATA:
//            ManageDataOp manageDataOp;
//        case BUMP_SEQUENCE:
//            BumpSequenceOp bumpSequenceOp;
//        case MANAGE_BUY_OFFER:
//            ManageBuyOfferOp manageBuyOfferOp;
//        case PATH_PAYMENT_STRICT_SEND:
//            PathPaymentStrictSendOp pathPaymentStrictSendOp;
//        case CREATE_CLAIMABLE_BALANCE:
//            CreateClaimableBalanceOp createClaimableBalanceOp;
//        case CLAIM_CLAIMABLE_BALANCE:
//            ClaimClaimableBalanceOp claimClaimableBalanceOp;
//        case BEGIN_SPONSORING_FUTURE_RESERVES:
//            BeginSponsoringFutureReservesOp beginSponsoringFutureReservesOp;
//        case END_SPONSORING_FUTURE_RESERVES:
//            void;
//        case REVOKE_SPONSORSHIP:
//            RevokeSponsorshipOp revokeSponsorshipOp;
//        case CLAWBACK:
//            ClawbackOp clawbackOp;
//        case CLAWBACK_CLAIMABLE_BALANCE:
//            ClawbackClaimableBalanceOp clawbackClaimableBalanceOp;
//        case SET_TRUST_LINE_FLAGS:
//            SetTrustLineFlagsOp setTrustLineFlagsOp;
//        case LIQUIDITY_POOL_DEPOSIT:
//            LiquidityPoolDepositOp liquidityPoolDepositOp;
//        case LIQUIDITY_POOL_WITHDRAW:
//            LiquidityPoolWithdrawOp liquidityPoolWithdrawOp;
//        case INVOKE_HOST_FUNCTION:
//            InvokeHostFunctionOp invokeHostFunctionOp;
//        }
//        body;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Operation {
    pub source_account: Option<MuxedAccount>,
    pub body: OperationBody,
}

impl ReadXdr for Operation {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            source_account: Option::<MuxedAccount>::read_xdr(r)?,
            body: OperationBody::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Operation {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.source_account.write_xdr(w)?;
        self.body.write_xdr(w)?;
        Ok(())
    }
}

// HashIdPreimageOperationId is an XDR NestedStruct defines as:
//
//   struct
//        {
//            AccountID sourceAccount;
//            SequenceNumber seqNum;
//            uint32 opNum;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct HashIdPreimageOperationId {
    pub source_account: AccountId,
    pub seq_num: SequenceNumber,
    pub op_num: u32,
}

impl ReadXdr for HashIdPreimageOperationId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            source_account: AccountId::read_xdr(r)?,
            seq_num: SequenceNumber::read_xdr(r)?,
            op_num: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for HashIdPreimageOperationId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.source_account.write_xdr(w)?;
        self.seq_num.write_xdr(w)?;
        self.op_num.write_xdr(w)?;
        Ok(())
    }
}

// HashIdPreimageRevokeId is an XDR NestedStruct defines as:
//
//   struct
//        {
//            AccountID sourceAccount;
//            SequenceNumber seqNum;
//            uint32 opNum;
//            PoolID liquidityPoolID;
//            Asset asset;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct HashIdPreimageRevokeId {
    pub source_account: AccountId,
    pub seq_num: SequenceNumber,
    pub op_num: u32,
    pub liquidity_pool_id: PoolId,
    pub asset: Asset,
}

impl ReadXdr for HashIdPreimageRevokeId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            source_account: AccountId::read_xdr(r)?,
            seq_num: SequenceNumber::read_xdr(r)?,
            op_num: u32::read_xdr(r)?,
            liquidity_pool_id: PoolId::read_xdr(r)?,
            asset: Asset::read_xdr(r)?,
        })
    }
}

impl WriteXdr for HashIdPreimageRevokeId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.source_account.write_xdr(w)?;
        self.seq_num.write_xdr(w)?;
        self.op_num.write_xdr(w)?;
        self.liquidity_pool_id.write_xdr(w)?;
        self.asset.write_xdr(w)?;
        Ok(())
    }
}

// HashIdPreimageEd25519ContractId is an XDR NestedStruct defines as:
//
//   struct
//        {
//            Hash networkID;
//            uint256 ed25519;
//            uint256 salt;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct HashIdPreimageEd25519ContractId {
    pub network_id: Hash,
    pub ed25519: Uint256,
    pub salt: Uint256,
}

impl ReadXdr for HashIdPreimageEd25519ContractId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            network_id: Hash::read_xdr(r)?,
            ed25519: Uint256::read_xdr(r)?,
            salt: Uint256::read_xdr(r)?,
        })
    }
}

impl WriteXdr for HashIdPreimageEd25519ContractId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.network_id.write_xdr(w)?;
        self.ed25519.write_xdr(w)?;
        self.salt.write_xdr(w)?;
        Ok(())
    }
}

// HashIdPreimageContractId is an XDR NestedStruct defines as:
//
//   struct
//        {
//            Hash networkID;
//            Hash contractID;
//            uint256 salt;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct HashIdPreimageContractId {
    pub network_id: Hash,
    pub contract_id: Hash,
    pub salt: Uint256,
}

impl ReadXdr for HashIdPreimageContractId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            network_id: Hash::read_xdr(r)?,
            contract_id: Hash::read_xdr(r)?,
            salt: Uint256::read_xdr(r)?,
        })
    }
}

impl WriteXdr for HashIdPreimageContractId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.network_id.write_xdr(w)?;
        self.contract_id.write_xdr(w)?;
        self.salt.write_xdr(w)?;
        Ok(())
    }
}

// HashIdPreimageFromAsset is an XDR NestedStruct defines as:
//
//   struct
//        {
//            Hash networkID;
//            Asset asset;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct HashIdPreimageFromAsset {
    pub network_id: Hash,
    pub asset: Asset,
}

impl ReadXdr for HashIdPreimageFromAsset {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            network_id: Hash::read_xdr(r)?,
            asset: Asset::read_xdr(r)?,
        })
    }
}

impl WriteXdr for HashIdPreimageFromAsset {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.network_id.write_xdr(w)?;
        self.asset.write_xdr(w)?;
        Ok(())
    }
}

// HashIdPreimageSourceAccountContractId is an XDR NestedStruct defines as:
//
//   struct
//        {
//            Hash networkID;
//            AccountID sourceAccount;
//            uint256 salt;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct HashIdPreimageSourceAccountContractId {
    pub network_id: Hash,
    pub source_account: AccountId,
    pub salt: Uint256,
}

impl ReadXdr for HashIdPreimageSourceAccountContractId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            network_id: Hash::read_xdr(r)?,
            source_account: AccountId::read_xdr(r)?,
            salt: Uint256::read_xdr(r)?,
        })
    }
}

impl WriteXdr for HashIdPreimageSourceAccountContractId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.network_id.write_xdr(w)?;
        self.source_account.write_xdr(w)?;
        self.salt.write_xdr(w)?;
        Ok(())
    }
}

// HashIdPreimageCreateContractArgs is an XDR NestedStruct defines as:
//
//   struct
//        {
//            Hash networkID;
//            SCContractCode source;
//            uint256 salt;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct HashIdPreimageCreateContractArgs {
    pub network_id: Hash,
    pub source: ScContractCode,
    pub salt: Uint256,
}

impl ReadXdr for HashIdPreimageCreateContractArgs {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            network_id: Hash::read_xdr(r)?,
            source: ScContractCode::read_xdr(r)?,
            salt: Uint256::read_xdr(r)?,
        })
    }
}

impl WriteXdr for HashIdPreimageCreateContractArgs {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.network_id.write_xdr(w)?;
        self.source.write_xdr(w)?;
        self.salt.write_xdr(w)?;
        Ok(())
    }
}

// HashIdPreimage is an XDR Union defines as:
//
//   union HashIDPreimage switch (EnvelopeType type)
//    {
//    case ENVELOPE_TYPE_OP_ID:
//        struct
//        {
//            AccountID sourceAccount;
//            SequenceNumber seqNum;
//            uint32 opNum;
//        } operationID;
//    case ENVELOPE_TYPE_POOL_REVOKE_OP_ID:
//        struct
//        {
//            AccountID sourceAccount;
//            SequenceNumber seqNum;
//            uint32 opNum;
//            PoolID liquidityPoolID;
//            Asset asset;
//        } revokeID;
//    case ENVELOPE_TYPE_CONTRACT_ID_FROM_ED25519:
//        struct
//        {
//            Hash networkID;
//            uint256 ed25519;
//            uint256 salt;
//        } ed25519ContractID;
//    case ENVELOPE_TYPE_CONTRACT_ID_FROM_CONTRACT:
//        struct
//        {
//            Hash networkID;
//            Hash contractID;
//            uint256 salt;
//        } contractID;
//    case ENVELOPE_TYPE_CONTRACT_ID_FROM_ASSET:
//        struct
//        {
//            Hash networkID;
//            Asset asset;
//        } fromAsset;
//    case ENVELOPE_TYPE_CONTRACT_ID_FROM_SOURCE_ACCOUNT:
//        struct
//        {
//            Hash networkID;
//            AccountID sourceAccount;
//            uint256 salt;
//        } sourceAccountContractID;
//    case ENVELOPE_TYPE_CREATE_CONTRACT_ARGS:
//        struct
//        {
//            Hash networkID;
//            SCContractCode source;
//            uint256 salt;
//        } createContractArgs;
//    };
//
// union with discriminant EnvelopeType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum HashIdPreimage {
    OpId(HashIdPreimageOperationId),
    PoolRevokeOpId(HashIdPreimageRevokeId),
    ContractIdFromEd25519(HashIdPreimageEd25519ContractId),
    ContractIdFromContract(HashIdPreimageContractId),
    ContractIdFromAsset(HashIdPreimageFromAsset),
    ContractIdFromSourceAccount(HashIdPreimageSourceAccountContractId),
    CreateContractArgs(HashIdPreimageCreateContractArgs),
}

impl HashIdPreimage {
    pub const VARIANTS: [EnvelopeType; 7] = [
        EnvelopeType::OpId,
        EnvelopeType::PoolRevokeOpId,
        EnvelopeType::ContractIdFromEd25519,
        EnvelopeType::ContractIdFromContract,
        EnvelopeType::ContractIdFromAsset,
        EnvelopeType::ContractIdFromSourceAccount,
        EnvelopeType::CreateContractArgs,
    ];
    pub const VARIANTS_STR: [&'static str; 7] = [
        "OpId",
        "PoolRevokeOpId",
        "ContractIdFromEd25519",
        "ContractIdFromContract",
        "ContractIdFromAsset",
        "ContractIdFromSourceAccount",
        "CreateContractArgs",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::OpId(_) => "OpId",
            Self::PoolRevokeOpId(_) => "PoolRevokeOpId",
            Self::ContractIdFromEd25519(_) => "ContractIdFromEd25519",
            Self::ContractIdFromContract(_) => "ContractIdFromContract",
            Self::ContractIdFromAsset(_) => "ContractIdFromAsset",
            Self::ContractIdFromSourceAccount(_) => "ContractIdFromSourceAccount",
            Self::CreateContractArgs(_) => "CreateContractArgs",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> EnvelopeType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::OpId(_) => EnvelopeType::OpId,
            Self::PoolRevokeOpId(_) => EnvelopeType::PoolRevokeOpId,
            Self::ContractIdFromEd25519(_) => EnvelopeType::ContractIdFromEd25519,
            Self::ContractIdFromContract(_) => EnvelopeType::ContractIdFromContract,
            Self::ContractIdFromAsset(_) => EnvelopeType::ContractIdFromAsset,
            Self::ContractIdFromSourceAccount(_) => EnvelopeType::ContractIdFromSourceAccount,
            Self::CreateContractArgs(_) => EnvelopeType::CreateContractArgs,
        }
    }

    #[must_use]
    pub const fn variants() -> [EnvelopeType; 7] {
        Self::VARIANTS
    }
}

impl Name for HashIdPreimage {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<EnvelopeType> for HashIdPreimage {
    #[must_use]
    fn discriminant(&self) -> EnvelopeType {
        Self::discriminant(self)
    }
}

impl Variants<EnvelopeType> for HashIdPreimage {
    fn variants() -> slice::Iter<'static, EnvelopeType> {
        Self::VARIANTS.iter()
    }
}

impl Union<EnvelopeType> for HashIdPreimage {}

impl ReadXdr for HashIdPreimage {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: EnvelopeType = <EnvelopeType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            EnvelopeType::OpId => Self::OpId(HashIdPreimageOperationId::read_xdr(r)?),
            EnvelopeType::PoolRevokeOpId => {
                Self::PoolRevokeOpId(HashIdPreimageRevokeId::read_xdr(r)?)
            }
            EnvelopeType::ContractIdFromEd25519 => {
                Self::ContractIdFromEd25519(HashIdPreimageEd25519ContractId::read_xdr(r)?)
            }
            EnvelopeType::ContractIdFromContract => {
                Self::ContractIdFromContract(HashIdPreimageContractId::read_xdr(r)?)
            }
            EnvelopeType::ContractIdFromAsset => {
                Self::ContractIdFromAsset(HashIdPreimageFromAsset::read_xdr(r)?)
            }
            EnvelopeType::ContractIdFromSourceAccount => Self::ContractIdFromSourceAccount(
                HashIdPreimageSourceAccountContractId::read_xdr(r)?,
            ),
            EnvelopeType::CreateContractArgs => {
                Self::CreateContractArgs(HashIdPreimageCreateContractArgs::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for HashIdPreimage {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::OpId(v) => v.write_xdr(w)?,
            Self::PoolRevokeOpId(v) => v.write_xdr(w)?,
            Self::ContractIdFromEd25519(v) => v.write_xdr(w)?,
            Self::ContractIdFromContract(v) => v.write_xdr(w)?,
            Self::ContractIdFromAsset(v) => v.write_xdr(w)?,
            Self::ContractIdFromSourceAccount(v) => v.write_xdr(w)?,
            Self::CreateContractArgs(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// MemoType is an XDR Enum defines as:
//
//   enum MemoType
//    {
//        MEMO_NONE = 0,
//        MEMO_TEXT = 1,
//        MEMO_ID = 2,
//        MEMO_HASH = 3,
//        MEMO_RETURN = 4
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum MemoType {
    None = 0,
    Text = 1,
    Id = 2,
    Hash = 3,
    Return = 4,
}

impl MemoType {
    pub const VARIANTS: [MemoType; 5] = [
        MemoType::None,
        MemoType::Text,
        MemoType::Id,
        MemoType::Hash,
        MemoType::Return,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = ["None", "Text", "Id", "Hash", "Return"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::None => "None",
            Self::Text => "Text",
            Self::Id => "Id",
            Self::Hash => "Hash",
            Self::Return => "Return",
        }
    }

    #[must_use]
    pub const fn variants() -> [MemoType; 5] {
        Self::VARIANTS
    }
}

impl Name for MemoType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<MemoType> for MemoType {
    fn variants() -> slice::Iter<'static, MemoType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for MemoType {}

impl fmt::Display for MemoType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for MemoType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => MemoType::None,
            1 => MemoType::Text,
            2 => MemoType::Id,
            3 => MemoType::Hash,
            4 => MemoType::Return,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<MemoType> for i32 {
    #[must_use]
    fn from(e: MemoType) -> Self {
        e as Self
    }
}

impl ReadXdr for MemoType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for MemoType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// Memo is an XDR Union defines as:
//
//   union Memo switch (MemoType type)
//    {
//    case MEMO_NONE:
//        void;
//    case MEMO_TEXT:
//        string text<28>;
//    case MEMO_ID:
//        uint64 id;
//    case MEMO_HASH:
//        Hash hash; // the hash of what to pull from the content server
//    case MEMO_RETURN:
//        Hash retHash; // the hash of the tx you are rejecting
//    };
//
// union with discriminant MemoType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum Memo {
    None,
    Text(StringM<28>),
    Id(u64),
    Hash(Hash),
    Return(Hash),
}

impl Memo {
    pub const VARIANTS: [MemoType; 5] = [
        MemoType::None,
        MemoType::Text,
        MemoType::Id,
        MemoType::Hash,
        MemoType::Return,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = ["None", "Text", "Id", "Hash", "Return"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::None => "None",
            Self::Text(_) => "Text",
            Self::Id(_) => "Id",
            Self::Hash(_) => "Hash",
            Self::Return(_) => "Return",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> MemoType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::None => MemoType::None,
            Self::Text(_) => MemoType::Text,
            Self::Id(_) => MemoType::Id,
            Self::Hash(_) => MemoType::Hash,
            Self::Return(_) => MemoType::Return,
        }
    }

    #[must_use]
    pub const fn variants() -> [MemoType; 5] {
        Self::VARIANTS
    }
}

impl Name for Memo {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<MemoType> for Memo {
    #[must_use]
    fn discriminant(&self) -> MemoType {
        Self::discriminant(self)
    }
}

impl Variants<MemoType> for Memo {
    fn variants() -> slice::Iter<'static, MemoType> {
        Self::VARIANTS.iter()
    }
}

impl Union<MemoType> for Memo {}

impl ReadXdr for Memo {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: MemoType = <MemoType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            MemoType::None => Self::None,
            MemoType::Text => Self::Text(StringM::<28>::read_xdr(r)?),
            MemoType::Id => Self::Id(u64::read_xdr(r)?),
            MemoType::Hash => Self::Hash(Hash::read_xdr(r)?),
            MemoType::Return => Self::Return(Hash::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for Memo {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::None => ().write_xdr(w)?,
            Self::Text(v) => v.write_xdr(w)?,
            Self::Id(v) => v.write_xdr(w)?,
            Self::Hash(v) => v.write_xdr(w)?,
            Self::Return(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TimeBounds is an XDR Struct defines as:
//
//   struct TimeBounds
//    {
//        TimePoint minTime;
//        TimePoint maxTime; // 0 here means no maxTime
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TimeBounds {
    pub min_time: TimePoint,
    pub max_time: TimePoint,
}

impl ReadXdr for TimeBounds {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            min_time: TimePoint::read_xdr(r)?,
            max_time: TimePoint::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TimeBounds {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.min_time.write_xdr(w)?;
        self.max_time.write_xdr(w)?;
        Ok(())
    }
}

// LedgerBounds is an XDR Struct defines as:
//
//   struct LedgerBounds
//    {
//        uint32 minLedger;
//        uint32 maxLedger; // 0 here means no maxLedger
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct LedgerBounds {
    pub min_ledger: u32,
    pub max_ledger: u32,
}

impl ReadXdr for LedgerBounds {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            min_ledger: u32::read_xdr(r)?,
            max_ledger: u32::read_xdr(r)?,
        })
    }
}

impl WriteXdr for LedgerBounds {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.min_ledger.write_xdr(w)?;
        self.max_ledger.write_xdr(w)?;
        Ok(())
    }
}

// PreconditionsV2 is an XDR Struct defines as:
//
//   struct PreconditionsV2
//    {
//        TimeBounds* timeBounds;
//
//        // Transaction only valid for ledger numbers n such that
//        // minLedger <= n < maxLedger (if maxLedger == 0, then
//        // only minLedger is checked)
//        LedgerBounds* ledgerBounds;
//
//        // If NULL, only valid when sourceAccount's sequence number
//        // is seqNum - 1.  Otherwise, valid when sourceAccount's
//        // sequence number n satisfies minSeqNum <= n < tx.seqNum.
//        // Note that after execution the account's sequence number
//        // is always raised to tx.seqNum, and a transaction is not
//        // valid if tx.seqNum is too high to ensure replay protection.
//        SequenceNumber* minSeqNum;
//
//        // For the transaction to be valid, the current ledger time must
//        // be at least minSeqAge greater than sourceAccount's seqTime.
//        Duration minSeqAge;
//
//        // For the transaction to be valid, the current ledger number
//        // must be at least minSeqLedgerGap greater than sourceAccount's
//        // seqLedger.
//        uint32 minSeqLedgerGap;
//
//        // For the transaction to be valid, there must be a signature
//        // corresponding to every Signer in this array, even if the
//        // signature is not otherwise required by the sourceAccount or
//        // operations.
//        SignerKey extraSigners<2>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PreconditionsV2 {
    pub time_bounds: Option<TimeBounds>,
    pub ledger_bounds: Option<LedgerBounds>,
    pub min_seq_num: Option<SequenceNumber>,
    pub min_seq_age: Duration,
    pub min_seq_ledger_gap: u32,
    pub extra_signers: VecM<SignerKey, 2>,
}

impl ReadXdr for PreconditionsV2 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            time_bounds: Option::<TimeBounds>::read_xdr(r)?,
            ledger_bounds: Option::<LedgerBounds>::read_xdr(r)?,
            min_seq_num: Option::<SequenceNumber>::read_xdr(r)?,
            min_seq_age: Duration::read_xdr(r)?,
            min_seq_ledger_gap: u32::read_xdr(r)?,
            extra_signers: VecM::<SignerKey, 2>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PreconditionsV2 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.time_bounds.write_xdr(w)?;
        self.ledger_bounds.write_xdr(w)?;
        self.min_seq_num.write_xdr(w)?;
        self.min_seq_age.write_xdr(w)?;
        self.min_seq_ledger_gap.write_xdr(w)?;
        self.extra_signers.write_xdr(w)?;
        Ok(())
    }
}

// PreconditionType is an XDR Enum defines as:
//
//   enum PreconditionType
//    {
//        PRECOND_NONE = 0,
//        PRECOND_TIME = 1,
//        PRECOND_V2 = 2
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum PreconditionType {
    None = 0,
    Time = 1,
    V2 = 2,
}

impl PreconditionType {
    pub const VARIANTS: [PreconditionType; 3] = [
        PreconditionType::None,
        PreconditionType::Time,
        PreconditionType::V2,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["None", "Time", "V2"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::None => "None",
            Self::Time => "Time",
            Self::V2 => "V2",
        }
    }

    #[must_use]
    pub const fn variants() -> [PreconditionType; 3] {
        Self::VARIANTS
    }
}

impl Name for PreconditionType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<PreconditionType> for PreconditionType {
    fn variants() -> slice::Iter<'static, PreconditionType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for PreconditionType {}

impl fmt::Display for PreconditionType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for PreconditionType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => PreconditionType::None,
            1 => PreconditionType::Time,
            2 => PreconditionType::V2,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<PreconditionType> for i32 {
    #[must_use]
    fn from(e: PreconditionType) -> Self {
        e as Self
    }
}

impl ReadXdr for PreconditionType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for PreconditionType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// Preconditions is an XDR Union defines as:
//
//   union Preconditions switch (PreconditionType type)
//    {
//    case PRECOND_NONE:
//        void;
//    case PRECOND_TIME:
//        TimeBounds timeBounds;
//    case PRECOND_V2:
//        PreconditionsV2 v2;
//    };
//
// union with discriminant PreconditionType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum Preconditions {
    None,
    Time(TimeBounds),
    V2(PreconditionsV2),
}

impl Preconditions {
    pub const VARIANTS: [PreconditionType; 3] = [
        PreconditionType::None,
        PreconditionType::Time,
        PreconditionType::V2,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["None", "Time", "V2"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::None => "None",
            Self::Time(_) => "Time",
            Self::V2(_) => "V2",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> PreconditionType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::None => PreconditionType::None,
            Self::Time(_) => PreconditionType::Time,
            Self::V2(_) => PreconditionType::V2,
        }
    }

    #[must_use]
    pub const fn variants() -> [PreconditionType; 3] {
        Self::VARIANTS
    }
}

impl Name for Preconditions {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<PreconditionType> for Preconditions {
    #[must_use]
    fn discriminant(&self) -> PreconditionType {
        Self::discriminant(self)
    }
}

impl Variants<PreconditionType> for Preconditions {
    fn variants() -> slice::Iter<'static, PreconditionType> {
        Self::VARIANTS.iter()
    }
}

impl Union<PreconditionType> for Preconditions {}

impl ReadXdr for Preconditions {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: PreconditionType = <PreconditionType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            PreconditionType::None => Self::None,
            PreconditionType::Time => Self::Time(TimeBounds::read_xdr(r)?),
            PreconditionType::V2 => Self::V2(PreconditionsV2::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for Preconditions {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::None => ().write_xdr(w)?,
            Self::Time(v) => v.write_xdr(w)?,
            Self::V2(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// MaxOpsPerTx is an XDR Const defines as:
//
//   const MAX_OPS_PER_TX = 100;
//
pub const MAX_OPS_PER_TX: u64 = 100;

// TransactionV0Ext is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionV0Ext {
    V0,
}

impl TransactionV0Ext {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for TransactionV0Ext {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TransactionV0Ext {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TransactionV0Ext {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TransactionV0Ext {}

impl ReadXdr for TransactionV0Ext {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionV0Ext {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionV0 is an XDR Struct defines as:
//
//   struct TransactionV0
//    {
//        uint256 sourceAccountEd25519;
//        uint32 fee;
//        SequenceNumber seqNum;
//        TimeBounds* timeBounds;
//        Memo memo;
//        Operation operations<MAX_OPS_PER_TX>;
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionV0 {
    pub source_account_ed25519: Uint256,
    pub fee: u32,
    pub seq_num: SequenceNumber,
    pub time_bounds: Option<TimeBounds>,
    pub memo: Memo,
    pub operations: VecM<Operation, 100>,
    pub ext: TransactionV0Ext,
}

impl ReadXdr for TransactionV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            source_account_ed25519: Uint256::read_xdr(r)?,
            fee: u32::read_xdr(r)?,
            seq_num: SequenceNumber::read_xdr(r)?,
            time_bounds: Option::<TimeBounds>::read_xdr(r)?,
            memo: Memo::read_xdr(r)?,
            operations: VecM::<Operation, 100>::read_xdr(r)?,
            ext: TransactionV0Ext::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.source_account_ed25519.write_xdr(w)?;
        self.fee.write_xdr(w)?;
        self.seq_num.write_xdr(w)?;
        self.time_bounds.write_xdr(w)?;
        self.memo.write_xdr(w)?;
        self.operations.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// TransactionV0Envelope is an XDR Struct defines as:
//
//   struct TransactionV0Envelope
//    {
//        TransactionV0 tx;
//        /* Each decorated signature is a signature over the SHA256 hash of
//         * a TransactionSignaturePayload */
//        DecoratedSignature signatures<20>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionV0Envelope {
    pub tx: TransactionV0,
    pub signatures: VecM<DecoratedSignature, 20>,
}

impl ReadXdr for TransactionV0Envelope {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            tx: TransactionV0::read_xdr(r)?,
            signatures: VecM::<DecoratedSignature, 20>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionV0Envelope {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.tx.write_xdr(w)?;
        self.signatures.write_xdr(w)?;
        Ok(())
    }
}

// TransactionExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionExt {
    V0,
}

impl TransactionExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for TransactionExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TransactionExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TransactionExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TransactionExt {}

impl ReadXdr for TransactionExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// Transaction is an XDR Struct defines as:
//
//   struct Transaction
//    {
//        // account used to run the transaction
//        MuxedAccount sourceAccount;
//
//        // the fee the sourceAccount will pay
//        uint32 fee;
//
//        // sequence number to consume in the account
//        SequenceNumber seqNum;
//
//        // validity conditions
//        Preconditions cond;
//
//        Memo memo;
//
//        Operation operations<MAX_OPS_PER_TX>;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Transaction {
    pub source_account: MuxedAccount,
    pub fee: u32,
    pub seq_num: SequenceNumber,
    pub cond: Preconditions,
    pub memo: Memo,
    pub operations: VecM<Operation, 100>,
    pub ext: TransactionExt,
}

impl ReadXdr for Transaction {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            source_account: MuxedAccount::read_xdr(r)?,
            fee: u32::read_xdr(r)?,
            seq_num: SequenceNumber::read_xdr(r)?,
            cond: Preconditions::read_xdr(r)?,
            memo: Memo::read_xdr(r)?,
            operations: VecM::<Operation, 100>::read_xdr(r)?,
            ext: TransactionExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Transaction {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.source_account.write_xdr(w)?;
        self.fee.write_xdr(w)?;
        self.seq_num.write_xdr(w)?;
        self.cond.write_xdr(w)?;
        self.memo.write_xdr(w)?;
        self.operations.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// TransactionV1Envelope is an XDR Struct defines as:
//
//   struct TransactionV1Envelope
//    {
//        Transaction tx;
//        /* Each decorated signature is a signature over the SHA256 hash of
//         * a TransactionSignaturePayload */
//        DecoratedSignature signatures<20>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionV1Envelope {
    pub tx: Transaction,
    pub signatures: VecM<DecoratedSignature, 20>,
}

impl ReadXdr for TransactionV1Envelope {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            tx: Transaction::read_xdr(r)?,
            signatures: VecM::<DecoratedSignature, 20>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionV1Envelope {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.tx.write_xdr(w)?;
        self.signatures.write_xdr(w)?;
        Ok(())
    }
}

// FeeBumpTransactionInnerTx is an XDR NestedUnion defines as:
//
//   union switch (EnvelopeType type)
//        {
//        case ENVELOPE_TYPE_TX:
//            TransactionV1Envelope v1;
//        }
//
// union with discriminant EnvelopeType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum FeeBumpTransactionInnerTx {
    Tx(TransactionV1Envelope),
}

impl FeeBumpTransactionInnerTx {
    pub const VARIANTS: [EnvelopeType; 1] = [EnvelopeType::Tx];
    pub const VARIANTS_STR: [&'static str; 1] = ["Tx"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Tx(_) => "Tx",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> EnvelopeType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Tx(_) => EnvelopeType::Tx,
        }
    }

    #[must_use]
    pub const fn variants() -> [EnvelopeType; 1] {
        Self::VARIANTS
    }
}

impl Name for FeeBumpTransactionInnerTx {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<EnvelopeType> for FeeBumpTransactionInnerTx {
    #[must_use]
    fn discriminant(&self) -> EnvelopeType {
        Self::discriminant(self)
    }
}

impl Variants<EnvelopeType> for FeeBumpTransactionInnerTx {
    fn variants() -> slice::Iter<'static, EnvelopeType> {
        Self::VARIANTS.iter()
    }
}

impl Union<EnvelopeType> for FeeBumpTransactionInnerTx {}

impl ReadXdr for FeeBumpTransactionInnerTx {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: EnvelopeType = <EnvelopeType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            EnvelopeType::Tx => Self::Tx(TransactionV1Envelope::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for FeeBumpTransactionInnerTx {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Tx(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// FeeBumpTransactionExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum FeeBumpTransactionExt {
    V0,
}

impl FeeBumpTransactionExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for FeeBumpTransactionExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for FeeBumpTransactionExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for FeeBumpTransactionExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for FeeBumpTransactionExt {}

impl ReadXdr for FeeBumpTransactionExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for FeeBumpTransactionExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// FeeBumpTransaction is an XDR Struct defines as:
//
//   struct FeeBumpTransaction
//    {
//        MuxedAccount feeSource;
//        int64 fee;
//        union switch (EnvelopeType type)
//        {
//        case ENVELOPE_TYPE_TX:
//            TransactionV1Envelope v1;
//        }
//        innerTx;
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct FeeBumpTransaction {
    pub fee_source: MuxedAccount,
    pub fee: i64,
    pub inner_tx: FeeBumpTransactionInnerTx,
    pub ext: FeeBumpTransactionExt,
}

impl ReadXdr for FeeBumpTransaction {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            fee_source: MuxedAccount::read_xdr(r)?,
            fee: i64::read_xdr(r)?,
            inner_tx: FeeBumpTransactionInnerTx::read_xdr(r)?,
            ext: FeeBumpTransactionExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for FeeBumpTransaction {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.fee_source.write_xdr(w)?;
        self.fee.write_xdr(w)?;
        self.inner_tx.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// FeeBumpTransactionEnvelope is an XDR Struct defines as:
//
//   struct FeeBumpTransactionEnvelope
//    {
//        FeeBumpTransaction tx;
//        /* Each decorated signature is a signature over the SHA256 hash of
//         * a TransactionSignaturePayload */
//        DecoratedSignature signatures<20>;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct FeeBumpTransactionEnvelope {
    pub tx: FeeBumpTransaction,
    pub signatures: VecM<DecoratedSignature, 20>,
}

impl ReadXdr for FeeBumpTransactionEnvelope {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            tx: FeeBumpTransaction::read_xdr(r)?,
            signatures: VecM::<DecoratedSignature, 20>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for FeeBumpTransactionEnvelope {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.tx.write_xdr(w)?;
        self.signatures.write_xdr(w)?;
        Ok(())
    }
}

// TransactionEnvelope is an XDR Union defines as:
//
//   union TransactionEnvelope switch (EnvelopeType type)
//    {
//    case ENVELOPE_TYPE_TX_V0:
//        TransactionV0Envelope v0;
//    case ENVELOPE_TYPE_TX:
//        TransactionV1Envelope v1;
//    case ENVELOPE_TYPE_TX_FEE_BUMP:
//        FeeBumpTransactionEnvelope feeBump;
//    };
//
// union with discriminant EnvelopeType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionEnvelope {
    TxV0(TransactionV0Envelope),
    Tx(TransactionV1Envelope),
    TxFeeBump(FeeBumpTransactionEnvelope),
}

impl TransactionEnvelope {
    pub const VARIANTS: [EnvelopeType; 3] = [
        EnvelopeType::TxV0,
        EnvelopeType::Tx,
        EnvelopeType::TxFeeBump,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["TxV0", "Tx", "TxFeeBump"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::TxV0(_) => "TxV0",
            Self::Tx(_) => "Tx",
            Self::TxFeeBump(_) => "TxFeeBump",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> EnvelopeType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::TxV0(_) => EnvelopeType::TxV0,
            Self::Tx(_) => EnvelopeType::Tx,
            Self::TxFeeBump(_) => EnvelopeType::TxFeeBump,
        }
    }

    #[must_use]
    pub const fn variants() -> [EnvelopeType; 3] {
        Self::VARIANTS
    }
}

impl Name for TransactionEnvelope {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<EnvelopeType> for TransactionEnvelope {
    #[must_use]
    fn discriminant(&self) -> EnvelopeType {
        Self::discriminant(self)
    }
}

impl Variants<EnvelopeType> for TransactionEnvelope {
    fn variants() -> slice::Iter<'static, EnvelopeType> {
        Self::VARIANTS.iter()
    }
}

impl Union<EnvelopeType> for TransactionEnvelope {}

impl ReadXdr for TransactionEnvelope {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: EnvelopeType = <EnvelopeType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            EnvelopeType::TxV0 => Self::TxV0(TransactionV0Envelope::read_xdr(r)?),
            EnvelopeType::Tx => Self::Tx(TransactionV1Envelope::read_xdr(r)?),
            EnvelopeType::TxFeeBump => Self::TxFeeBump(FeeBumpTransactionEnvelope::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionEnvelope {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::TxV0(v) => v.write_xdr(w)?,
            Self::Tx(v) => v.write_xdr(w)?,
            Self::TxFeeBump(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionSignaturePayloadTaggedTransaction is an XDR NestedUnion defines as:
//
//   union switch (EnvelopeType type)
//        {
//        // Backwards Compatibility: Use ENVELOPE_TYPE_TX to sign ENVELOPE_TYPE_TX_V0
//        case ENVELOPE_TYPE_TX:
//            Transaction tx;
//        case ENVELOPE_TYPE_TX_FEE_BUMP:
//            FeeBumpTransaction feeBump;
//        }
//
// union with discriminant EnvelopeType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionSignaturePayloadTaggedTransaction {
    Tx(Transaction),
    TxFeeBump(FeeBumpTransaction),
}

impl TransactionSignaturePayloadTaggedTransaction {
    pub const VARIANTS: [EnvelopeType; 2] = [EnvelopeType::Tx, EnvelopeType::TxFeeBump];
    pub const VARIANTS_STR: [&'static str; 2] = ["Tx", "TxFeeBump"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Tx(_) => "Tx",
            Self::TxFeeBump(_) => "TxFeeBump",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> EnvelopeType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Tx(_) => EnvelopeType::Tx,
            Self::TxFeeBump(_) => EnvelopeType::TxFeeBump,
        }
    }

    #[must_use]
    pub const fn variants() -> [EnvelopeType; 2] {
        Self::VARIANTS
    }
}

impl Name for TransactionSignaturePayloadTaggedTransaction {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<EnvelopeType> for TransactionSignaturePayloadTaggedTransaction {
    #[must_use]
    fn discriminant(&self) -> EnvelopeType {
        Self::discriminant(self)
    }
}

impl Variants<EnvelopeType> for TransactionSignaturePayloadTaggedTransaction {
    fn variants() -> slice::Iter<'static, EnvelopeType> {
        Self::VARIANTS.iter()
    }
}

impl Union<EnvelopeType> for TransactionSignaturePayloadTaggedTransaction {}

impl ReadXdr for TransactionSignaturePayloadTaggedTransaction {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: EnvelopeType = <EnvelopeType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            EnvelopeType::Tx => Self::Tx(Transaction::read_xdr(r)?),
            EnvelopeType::TxFeeBump => Self::TxFeeBump(FeeBumpTransaction::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionSignaturePayloadTaggedTransaction {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Tx(v) => v.write_xdr(w)?,
            Self::TxFeeBump(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionSignaturePayload is an XDR Struct defines as:
//
//   struct TransactionSignaturePayload
//    {
//        Hash networkId;
//        union switch (EnvelopeType type)
//        {
//        // Backwards Compatibility: Use ENVELOPE_TYPE_TX to sign ENVELOPE_TYPE_TX_V0
//        case ENVELOPE_TYPE_TX:
//            Transaction tx;
//        case ENVELOPE_TYPE_TX_FEE_BUMP:
//            FeeBumpTransaction feeBump;
//        }
//        taggedTransaction;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionSignaturePayload {
    pub network_id: Hash,
    pub tagged_transaction: TransactionSignaturePayloadTaggedTransaction,
}

impl ReadXdr for TransactionSignaturePayload {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            network_id: Hash::read_xdr(r)?,
            tagged_transaction: TransactionSignaturePayloadTaggedTransaction::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionSignaturePayload {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.network_id.write_xdr(w)?;
        self.tagged_transaction.write_xdr(w)?;
        Ok(())
    }
}

// ClaimAtomType is an XDR Enum defines as:
//
//   enum ClaimAtomType
//    {
//        CLAIM_ATOM_TYPE_V0 = 0,
//        CLAIM_ATOM_TYPE_ORDER_BOOK = 1,
//        CLAIM_ATOM_TYPE_LIQUIDITY_POOL = 2
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ClaimAtomType {
    V0 = 0,
    OrderBook = 1,
    LiquidityPool = 2,
}

impl ClaimAtomType {
    pub const VARIANTS: [ClaimAtomType; 3] = [
        ClaimAtomType::V0,
        ClaimAtomType::OrderBook,
        ClaimAtomType::LiquidityPool,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["V0", "OrderBook", "LiquidityPool"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
            Self::OrderBook => "OrderBook",
            Self::LiquidityPool => "LiquidityPool",
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimAtomType; 3] {
        Self::VARIANTS
    }
}

impl Name for ClaimAtomType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ClaimAtomType> for ClaimAtomType {
    fn variants() -> slice::Iter<'static, ClaimAtomType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ClaimAtomType {}

impl fmt::Display for ClaimAtomType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ClaimAtomType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ClaimAtomType::V0,
            1 => ClaimAtomType::OrderBook,
            2 => ClaimAtomType::LiquidityPool,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ClaimAtomType> for i32 {
    #[must_use]
    fn from(e: ClaimAtomType) -> Self {
        e as Self
    }
}

impl ReadXdr for ClaimAtomType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ClaimAtomType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ClaimOfferAtomV0 is an XDR Struct defines as:
//
//   struct ClaimOfferAtomV0
//    {
//        // emitted to identify the offer
//        uint256 sellerEd25519; // Account that owns the offer
//        int64 offerID;
//
//        // amount and asset taken from the owner
//        Asset assetSold;
//        int64 amountSold;
//
//        // amount and asset sent to the owner
//        Asset assetBought;
//        int64 amountBought;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ClaimOfferAtomV0 {
    pub seller_ed25519: Uint256,
    pub offer_id: i64,
    pub asset_sold: Asset,
    pub amount_sold: i64,
    pub asset_bought: Asset,
    pub amount_bought: i64,
}

impl ReadXdr for ClaimOfferAtomV0 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            seller_ed25519: Uint256::read_xdr(r)?,
            offer_id: i64::read_xdr(r)?,
            asset_sold: Asset::read_xdr(r)?,
            amount_sold: i64::read_xdr(r)?,
            asset_bought: Asset::read_xdr(r)?,
            amount_bought: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ClaimOfferAtomV0 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.seller_ed25519.write_xdr(w)?;
        self.offer_id.write_xdr(w)?;
        self.asset_sold.write_xdr(w)?;
        self.amount_sold.write_xdr(w)?;
        self.asset_bought.write_xdr(w)?;
        self.amount_bought.write_xdr(w)?;
        Ok(())
    }
}

// ClaimOfferAtom is an XDR Struct defines as:
//
//   struct ClaimOfferAtom
//    {
//        // emitted to identify the offer
//        AccountID sellerID; // Account that owns the offer
//        int64 offerID;
//
//        // amount and asset taken from the owner
//        Asset assetSold;
//        int64 amountSold;
//
//        // amount and asset sent to the owner
//        Asset assetBought;
//        int64 amountBought;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ClaimOfferAtom {
    pub seller_id: AccountId,
    pub offer_id: i64,
    pub asset_sold: Asset,
    pub amount_sold: i64,
    pub asset_bought: Asset,
    pub amount_bought: i64,
}

impl ReadXdr for ClaimOfferAtom {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            seller_id: AccountId::read_xdr(r)?,
            offer_id: i64::read_xdr(r)?,
            asset_sold: Asset::read_xdr(r)?,
            amount_sold: i64::read_xdr(r)?,
            asset_bought: Asset::read_xdr(r)?,
            amount_bought: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ClaimOfferAtom {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.seller_id.write_xdr(w)?;
        self.offer_id.write_xdr(w)?;
        self.asset_sold.write_xdr(w)?;
        self.amount_sold.write_xdr(w)?;
        self.asset_bought.write_xdr(w)?;
        self.amount_bought.write_xdr(w)?;
        Ok(())
    }
}

// ClaimLiquidityAtom is an XDR Struct defines as:
//
//   struct ClaimLiquidityAtom
//    {
//        PoolID liquidityPoolID;
//
//        // amount and asset taken from the pool
//        Asset assetSold;
//        int64 amountSold;
//
//        // amount and asset sent to the pool
//        Asset assetBought;
//        int64 amountBought;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ClaimLiquidityAtom {
    pub liquidity_pool_id: PoolId,
    pub asset_sold: Asset,
    pub amount_sold: i64,
    pub asset_bought: Asset,
    pub amount_bought: i64,
}

impl ReadXdr for ClaimLiquidityAtom {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            liquidity_pool_id: PoolId::read_xdr(r)?,
            asset_sold: Asset::read_xdr(r)?,
            amount_sold: i64::read_xdr(r)?,
            asset_bought: Asset::read_xdr(r)?,
            amount_bought: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ClaimLiquidityAtom {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.liquidity_pool_id.write_xdr(w)?;
        self.asset_sold.write_xdr(w)?;
        self.amount_sold.write_xdr(w)?;
        self.asset_bought.write_xdr(w)?;
        self.amount_bought.write_xdr(w)?;
        Ok(())
    }
}

// ClaimAtom is an XDR Union defines as:
//
//   union ClaimAtom switch (ClaimAtomType type)
//    {
//    case CLAIM_ATOM_TYPE_V0:
//        ClaimOfferAtomV0 v0;
//    case CLAIM_ATOM_TYPE_ORDER_BOOK:
//        ClaimOfferAtom orderBook;
//    case CLAIM_ATOM_TYPE_LIQUIDITY_POOL:
//        ClaimLiquidityAtom liquidityPool;
//    };
//
// union with discriminant ClaimAtomType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ClaimAtom {
    V0(ClaimOfferAtomV0),
    OrderBook(ClaimOfferAtom),
    LiquidityPool(ClaimLiquidityAtom),
}

impl ClaimAtom {
    pub const VARIANTS: [ClaimAtomType; 3] = [
        ClaimAtomType::V0,
        ClaimAtomType::OrderBook,
        ClaimAtomType::LiquidityPool,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["V0", "OrderBook", "LiquidityPool"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0(_) => "V0",
            Self::OrderBook(_) => "OrderBook",
            Self::LiquidityPool(_) => "LiquidityPool",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ClaimAtomType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(_) => ClaimAtomType::V0,
            Self::OrderBook(_) => ClaimAtomType::OrderBook,
            Self::LiquidityPool(_) => ClaimAtomType::LiquidityPool,
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimAtomType; 3] {
        Self::VARIANTS
    }
}

impl Name for ClaimAtom {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ClaimAtomType> for ClaimAtom {
    #[must_use]
    fn discriminant(&self) -> ClaimAtomType {
        Self::discriminant(self)
    }
}

impl Variants<ClaimAtomType> for ClaimAtom {
    fn variants() -> slice::Iter<'static, ClaimAtomType> {
        Self::VARIANTS.iter()
    }
}

impl Union<ClaimAtomType> for ClaimAtom {}

impl ReadXdr for ClaimAtom {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ClaimAtomType = <ClaimAtomType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ClaimAtomType::V0 => Self::V0(ClaimOfferAtomV0::read_xdr(r)?),
            ClaimAtomType::OrderBook => Self::OrderBook(ClaimOfferAtom::read_xdr(r)?),
            ClaimAtomType::LiquidityPool => Self::LiquidityPool(ClaimLiquidityAtom::read_xdr(r)?),
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ClaimAtom {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0(v) => v.write_xdr(w)?,
            Self::OrderBook(v) => v.write_xdr(w)?,
            Self::LiquidityPool(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// CreateAccountResultCode is an XDR Enum defines as:
//
//   enum CreateAccountResultCode
//    {
//        // codes considered as "success" for the operation
//        CREATE_ACCOUNT_SUCCESS = 0, // account was created
//
//        // codes considered as "failure" for the operation
//        CREATE_ACCOUNT_MALFORMED = -1,   // invalid destination
//        CREATE_ACCOUNT_UNDERFUNDED = -2, // not enough funds in source account
//        CREATE_ACCOUNT_LOW_RESERVE =
//            -3, // would create an account below the min reserve
//        CREATE_ACCOUNT_ALREADY_EXIST = -4 // account already exists
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum CreateAccountResultCode {
    Success = 0,
    Malformed = -1,
    Underfunded = -2,
    LowReserve = -3,
    AlreadyExist = -4,
}

impl CreateAccountResultCode {
    pub const VARIANTS: [CreateAccountResultCode; 5] = [
        CreateAccountResultCode::Success,
        CreateAccountResultCode::Malformed,
        CreateAccountResultCode::Underfunded,
        CreateAccountResultCode::LowReserve,
        CreateAccountResultCode::AlreadyExist,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "Success",
        "Malformed",
        "Underfunded",
        "LowReserve",
        "AlreadyExist",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::Underfunded => "Underfunded",
            Self::LowReserve => "LowReserve",
            Self::AlreadyExist => "AlreadyExist",
        }
    }

    #[must_use]
    pub const fn variants() -> [CreateAccountResultCode; 5] {
        Self::VARIANTS
    }
}

impl Name for CreateAccountResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<CreateAccountResultCode> for CreateAccountResultCode {
    fn variants() -> slice::Iter<'static, CreateAccountResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for CreateAccountResultCode {}

impl fmt::Display for CreateAccountResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for CreateAccountResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => CreateAccountResultCode::Success,
            -1 => CreateAccountResultCode::Malformed,
            -2 => CreateAccountResultCode::Underfunded,
            -3 => CreateAccountResultCode::LowReserve,
            -4 => CreateAccountResultCode::AlreadyExist,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<CreateAccountResultCode> for i32 {
    #[must_use]
    fn from(e: CreateAccountResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for CreateAccountResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for CreateAccountResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// CreateAccountResult is an XDR Union defines as:
//
//   union CreateAccountResult switch (CreateAccountResultCode code)
//    {
//    case CREATE_ACCOUNT_SUCCESS:
//        void;
//    case CREATE_ACCOUNT_MALFORMED:
//    case CREATE_ACCOUNT_UNDERFUNDED:
//    case CREATE_ACCOUNT_LOW_RESERVE:
//    case CREATE_ACCOUNT_ALREADY_EXIST:
//        void;
//    };
//
// union with discriminant CreateAccountResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum CreateAccountResult {
    Success,
    Malformed,
    Underfunded,
    LowReserve,
    AlreadyExist,
}

impl CreateAccountResult {
    pub const VARIANTS: [CreateAccountResultCode; 5] = [
        CreateAccountResultCode::Success,
        CreateAccountResultCode::Malformed,
        CreateAccountResultCode::Underfunded,
        CreateAccountResultCode::LowReserve,
        CreateAccountResultCode::AlreadyExist,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "Success",
        "Malformed",
        "Underfunded",
        "LowReserve",
        "AlreadyExist",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::Underfunded => "Underfunded",
            Self::LowReserve => "LowReserve",
            Self::AlreadyExist => "AlreadyExist",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> CreateAccountResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => CreateAccountResultCode::Success,
            Self::Malformed => CreateAccountResultCode::Malformed,
            Self::Underfunded => CreateAccountResultCode::Underfunded,
            Self::LowReserve => CreateAccountResultCode::LowReserve,
            Self::AlreadyExist => CreateAccountResultCode::AlreadyExist,
        }
    }

    #[must_use]
    pub const fn variants() -> [CreateAccountResultCode; 5] {
        Self::VARIANTS
    }
}

impl Name for CreateAccountResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<CreateAccountResultCode> for CreateAccountResult {
    #[must_use]
    fn discriminant(&self) -> CreateAccountResultCode {
        Self::discriminant(self)
    }
}

impl Variants<CreateAccountResultCode> for CreateAccountResult {
    fn variants() -> slice::Iter<'static, CreateAccountResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<CreateAccountResultCode> for CreateAccountResult {}

impl ReadXdr for CreateAccountResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: CreateAccountResultCode = <CreateAccountResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            CreateAccountResultCode::Success => Self::Success,
            CreateAccountResultCode::Malformed => Self::Malformed,
            CreateAccountResultCode::Underfunded => Self::Underfunded,
            CreateAccountResultCode::LowReserve => Self::LowReserve,
            CreateAccountResultCode::AlreadyExist => Self::AlreadyExist,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for CreateAccountResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
            Self::AlreadyExist => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// PaymentResultCode is an XDR Enum defines as:
//
//   enum PaymentResultCode
//    {
//        // codes considered as "success" for the operation
//        PAYMENT_SUCCESS = 0, // payment successfully completed
//
//        // codes considered as "failure" for the operation
//        PAYMENT_MALFORMED = -1,          // bad input
//        PAYMENT_UNDERFUNDED = -2,        // not enough funds in source account
//        PAYMENT_SRC_NO_TRUST = -3,       // no trust line on source account
//        PAYMENT_SRC_NOT_AUTHORIZED = -4, // source not authorized to transfer
//        PAYMENT_NO_DESTINATION = -5,     // destination account does not exist
//        PAYMENT_NO_TRUST = -6,       // destination missing a trust line for asset
//        PAYMENT_NOT_AUTHORIZED = -7, // destination not authorized to hold asset
//        PAYMENT_LINE_FULL = -8,      // destination would go above their limit
//        PAYMENT_NO_ISSUER = -9       // missing issuer on asset
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum PaymentResultCode {
    Success = 0,
    Malformed = -1,
    Underfunded = -2,
    SrcNoTrust = -3,
    SrcNotAuthorized = -4,
    NoDestination = -5,
    NoTrust = -6,
    NotAuthorized = -7,
    LineFull = -8,
    NoIssuer = -9,
}

impl PaymentResultCode {
    pub const VARIANTS: [PaymentResultCode; 10] = [
        PaymentResultCode::Success,
        PaymentResultCode::Malformed,
        PaymentResultCode::Underfunded,
        PaymentResultCode::SrcNoTrust,
        PaymentResultCode::SrcNotAuthorized,
        PaymentResultCode::NoDestination,
        PaymentResultCode::NoTrust,
        PaymentResultCode::NotAuthorized,
        PaymentResultCode::LineFull,
        PaymentResultCode::NoIssuer,
    ];
    pub const VARIANTS_STR: [&'static str; 10] = [
        "Success",
        "Malformed",
        "Underfunded",
        "SrcNoTrust",
        "SrcNotAuthorized",
        "NoDestination",
        "NoTrust",
        "NotAuthorized",
        "LineFull",
        "NoIssuer",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::Underfunded => "Underfunded",
            Self::SrcNoTrust => "SrcNoTrust",
            Self::SrcNotAuthorized => "SrcNotAuthorized",
            Self::NoDestination => "NoDestination",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::LineFull => "LineFull",
            Self::NoIssuer => "NoIssuer",
        }
    }

    #[must_use]
    pub const fn variants() -> [PaymentResultCode; 10] {
        Self::VARIANTS
    }
}

impl Name for PaymentResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<PaymentResultCode> for PaymentResultCode {
    fn variants() -> slice::Iter<'static, PaymentResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for PaymentResultCode {}

impl fmt::Display for PaymentResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for PaymentResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => PaymentResultCode::Success,
            -1 => PaymentResultCode::Malformed,
            -2 => PaymentResultCode::Underfunded,
            -3 => PaymentResultCode::SrcNoTrust,
            -4 => PaymentResultCode::SrcNotAuthorized,
            -5 => PaymentResultCode::NoDestination,
            -6 => PaymentResultCode::NoTrust,
            -7 => PaymentResultCode::NotAuthorized,
            -8 => PaymentResultCode::LineFull,
            -9 => PaymentResultCode::NoIssuer,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<PaymentResultCode> for i32 {
    #[must_use]
    fn from(e: PaymentResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for PaymentResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for PaymentResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// PaymentResult is an XDR Union defines as:
//
//   union PaymentResult switch (PaymentResultCode code)
//    {
//    case PAYMENT_SUCCESS:
//        void;
//    case PAYMENT_MALFORMED:
//    case PAYMENT_UNDERFUNDED:
//    case PAYMENT_SRC_NO_TRUST:
//    case PAYMENT_SRC_NOT_AUTHORIZED:
//    case PAYMENT_NO_DESTINATION:
//    case PAYMENT_NO_TRUST:
//    case PAYMENT_NOT_AUTHORIZED:
//    case PAYMENT_LINE_FULL:
//    case PAYMENT_NO_ISSUER:
//        void;
//    };
//
// union with discriminant PaymentResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum PaymentResult {
    Success,
    Malformed,
    Underfunded,
    SrcNoTrust,
    SrcNotAuthorized,
    NoDestination,
    NoTrust,
    NotAuthorized,
    LineFull,
    NoIssuer,
}

impl PaymentResult {
    pub const VARIANTS: [PaymentResultCode; 10] = [
        PaymentResultCode::Success,
        PaymentResultCode::Malformed,
        PaymentResultCode::Underfunded,
        PaymentResultCode::SrcNoTrust,
        PaymentResultCode::SrcNotAuthorized,
        PaymentResultCode::NoDestination,
        PaymentResultCode::NoTrust,
        PaymentResultCode::NotAuthorized,
        PaymentResultCode::LineFull,
        PaymentResultCode::NoIssuer,
    ];
    pub const VARIANTS_STR: [&'static str; 10] = [
        "Success",
        "Malformed",
        "Underfunded",
        "SrcNoTrust",
        "SrcNotAuthorized",
        "NoDestination",
        "NoTrust",
        "NotAuthorized",
        "LineFull",
        "NoIssuer",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::Underfunded => "Underfunded",
            Self::SrcNoTrust => "SrcNoTrust",
            Self::SrcNotAuthorized => "SrcNotAuthorized",
            Self::NoDestination => "NoDestination",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::LineFull => "LineFull",
            Self::NoIssuer => "NoIssuer",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> PaymentResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => PaymentResultCode::Success,
            Self::Malformed => PaymentResultCode::Malformed,
            Self::Underfunded => PaymentResultCode::Underfunded,
            Self::SrcNoTrust => PaymentResultCode::SrcNoTrust,
            Self::SrcNotAuthorized => PaymentResultCode::SrcNotAuthorized,
            Self::NoDestination => PaymentResultCode::NoDestination,
            Self::NoTrust => PaymentResultCode::NoTrust,
            Self::NotAuthorized => PaymentResultCode::NotAuthorized,
            Self::LineFull => PaymentResultCode::LineFull,
            Self::NoIssuer => PaymentResultCode::NoIssuer,
        }
    }

    #[must_use]
    pub const fn variants() -> [PaymentResultCode; 10] {
        Self::VARIANTS
    }
}

impl Name for PaymentResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<PaymentResultCode> for PaymentResult {
    #[must_use]
    fn discriminant(&self) -> PaymentResultCode {
        Self::discriminant(self)
    }
}

impl Variants<PaymentResultCode> for PaymentResult {
    fn variants() -> slice::Iter<'static, PaymentResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<PaymentResultCode> for PaymentResult {}

impl ReadXdr for PaymentResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: PaymentResultCode = <PaymentResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            PaymentResultCode::Success => Self::Success,
            PaymentResultCode::Malformed => Self::Malformed,
            PaymentResultCode::Underfunded => Self::Underfunded,
            PaymentResultCode::SrcNoTrust => Self::SrcNoTrust,
            PaymentResultCode::SrcNotAuthorized => Self::SrcNotAuthorized,
            PaymentResultCode::NoDestination => Self::NoDestination,
            PaymentResultCode::NoTrust => Self::NoTrust,
            PaymentResultCode::NotAuthorized => Self::NotAuthorized,
            PaymentResultCode::LineFull => Self::LineFull,
            PaymentResultCode::NoIssuer => Self::NoIssuer,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for PaymentResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
            Self::SrcNoTrust => ().write_xdr(w)?,
            Self::SrcNotAuthorized => ().write_xdr(w)?,
            Self::NoDestination => ().write_xdr(w)?,
            Self::NoTrust => ().write_xdr(w)?,
            Self::NotAuthorized => ().write_xdr(w)?,
            Self::LineFull => ().write_xdr(w)?,
            Self::NoIssuer => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// PathPaymentStrictReceiveResultCode is an XDR Enum defines as:
//
//   enum PathPaymentStrictReceiveResultCode
//    {
//        // codes considered as "success" for the operation
//        PATH_PAYMENT_STRICT_RECEIVE_SUCCESS = 0, // success
//
//        // codes considered as "failure" for the operation
//        PATH_PAYMENT_STRICT_RECEIVE_MALFORMED = -1, // bad input
//        PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED =
//            -2, // not enough funds in source account
//        PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST =
//            -3, // no trust line on source account
//        PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED =
//            -4, // source not authorized to transfer
//        PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION =
//            -5, // destination account does not exist
//        PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST =
//            -6, // dest missing a trust line for asset
//        PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED =
//            -7, // dest not authorized to hold asset
//        PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL =
//            -8, // dest would go above their limit
//        PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER = -9, // missing issuer on one asset
//        PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS =
//            -10, // not enough offers to satisfy path
//        PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF =
//            -11, // would cross one of its own offers
//        PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX = -12 // could not satisfy sendmax
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum PathPaymentStrictReceiveResultCode {
    Success = 0,
    Malformed = -1,
    Underfunded = -2,
    SrcNoTrust = -3,
    SrcNotAuthorized = -4,
    NoDestination = -5,
    NoTrust = -6,
    NotAuthorized = -7,
    LineFull = -8,
    NoIssuer = -9,
    TooFewOffers = -10,
    OfferCrossSelf = -11,
    OverSendmax = -12,
}

impl PathPaymentStrictReceiveResultCode {
    pub const VARIANTS: [PathPaymentStrictReceiveResultCode; 13] = [
        PathPaymentStrictReceiveResultCode::Success,
        PathPaymentStrictReceiveResultCode::Malformed,
        PathPaymentStrictReceiveResultCode::Underfunded,
        PathPaymentStrictReceiveResultCode::SrcNoTrust,
        PathPaymentStrictReceiveResultCode::SrcNotAuthorized,
        PathPaymentStrictReceiveResultCode::NoDestination,
        PathPaymentStrictReceiveResultCode::NoTrust,
        PathPaymentStrictReceiveResultCode::NotAuthorized,
        PathPaymentStrictReceiveResultCode::LineFull,
        PathPaymentStrictReceiveResultCode::NoIssuer,
        PathPaymentStrictReceiveResultCode::TooFewOffers,
        PathPaymentStrictReceiveResultCode::OfferCrossSelf,
        PathPaymentStrictReceiveResultCode::OverSendmax,
    ];
    pub const VARIANTS_STR: [&'static str; 13] = [
        "Success",
        "Malformed",
        "Underfunded",
        "SrcNoTrust",
        "SrcNotAuthorized",
        "NoDestination",
        "NoTrust",
        "NotAuthorized",
        "LineFull",
        "NoIssuer",
        "TooFewOffers",
        "OfferCrossSelf",
        "OverSendmax",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::Underfunded => "Underfunded",
            Self::SrcNoTrust => "SrcNoTrust",
            Self::SrcNotAuthorized => "SrcNotAuthorized",
            Self::NoDestination => "NoDestination",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::LineFull => "LineFull",
            Self::NoIssuer => "NoIssuer",
            Self::TooFewOffers => "TooFewOffers",
            Self::OfferCrossSelf => "OfferCrossSelf",
            Self::OverSendmax => "OverSendmax",
        }
    }

    #[must_use]
    pub const fn variants() -> [PathPaymentStrictReceiveResultCode; 13] {
        Self::VARIANTS
    }
}

impl Name for PathPaymentStrictReceiveResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<PathPaymentStrictReceiveResultCode> for PathPaymentStrictReceiveResultCode {
    fn variants() -> slice::Iter<'static, PathPaymentStrictReceiveResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for PathPaymentStrictReceiveResultCode {}

impl fmt::Display for PathPaymentStrictReceiveResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for PathPaymentStrictReceiveResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => PathPaymentStrictReceiveResultCode::Success,
            -1 => PathPaymentStrictReceiveResultCode::Malformed,
            -2 => PathPaymentStrictReceiveResultCode::Underfunded,
            -3 => PathPaymentStrictReceiveResultCode::SrcNoTrust,
            -4 => PathPaymentStrictReceiveResultCode::SrcNotAuthorized,
            -5 => PathPaymentStrictReceiveResultCode::NoDestination,
            -6 => PathPaymentStrictReceiveResultCode::NoTrust,
            -7 => PathPaymentStrictReceiveResultCode::NotAuthorized,
            -8 => PathPaymentStrictReceiveResultCode::LineFull,
            -9 => PathPaymentStrictReceiveResultCode::NoIssuer,
            -10 => PathPaymentStrictReceiveResultCode::TooFewOffers,
            -11 => PathPaymentStrictReceiveResultCode::OfferCrossSelf,
            -12 => PathPaymentStrictReceiveResultCode::OverSendmax,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<PathPaymentStrictReceiveResultCode> for i32 {
    #[must_use]
    fn from(e: PathPaymentStrictReceiveResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for PathPaymentStrictReceiveResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for PathPaymentStrictReceiveResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// SimplePaymentResult is an XDR Struct defines as:
//
//   struct SimplePaymentResult
//    {
//        AccountID destination;
//        Asset asset;
//        int64 amount;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SimplePaymentResult {
    pub destination: AccountId,
    pub asset: Asset,
    pub amount: i64,
}

impl ReadXdr for SimplePaymentResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            destination: AccountId::read_xdr(r)?,
            asset: Asset::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SimplePaymentResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.destination.write_xdr(w)?;
        self.asset.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        Ok(())
    }
}

// PathPaymentStrictReceiveResultSuccess is an XDR NestedStruct defines as:
//
//   struct
//        {
//            ClaimAtom offers<>;
//            SimplePaymentResult last;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PathPaymentStrictReceiveResultSuccess {
    pub offers: VecM<ClaimAtom>,
    pub last: SimplePaymentResult,
}

impl ReadXdr for PathPaymentStrictReceiveResultSuccess {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            offers: VecM::<ClaimAtom>::read_xdr(r)?,
            last: SimplePaymentResult::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PathPaymentStrictReceiveResultSuccess {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.offers.write_xdr(w)?;
        self.last.write_xdr(w)?;
        Ok(())
    }
}

// PathPaymentStrictReceiveResult is an XDR Union defines as:
//
//   union PathPaymentStrictReceiveResult switch (
//        PathPaymentStrictReceiveResultCode code)
//    {
//    case PATH_PAYMENT_STRICT_RECEIVE_SUCCESS:
//        struct
//        {
//            ClaimAtom offers<>;
//            SimplePaymentResult last;
//        } success;
//    case PATH_PAYMENT_STRICT_RECEIVE_MALFORMED:
//    case PATH_PAYMENT_STRICT_RECEIVE_UNDERFUNDED:
//    case PATH_PAYMENT_STRICT_RECEIVE_SRC_NO_TRUST:
//    case PATH_PAYMENT_STRICT_RECEIVE_SRC_NOT_AUTHORIZED:
//    case PATH_PAYMENT_STRICT_RECEIVE_NO_DESTINATION:
//    case PATH_PAYMENT_STRICT_RECEIVE_NO_TRUST:
//    case PATH_PAYMENT_STRICT_RECEIVE_NOT_AUTHORIZED:
//    case PATH_PAYMENT_STRICT_RECEIVE_LINE_FULL:
//        void;
//    case PATH_PAYMENT_STRICT_RECEIVE_NO_ISSUER:
//        Asset noIssuer; // the asset that caused the error
//    case PATH_PAYMENT_STRICT_RECEIVE_TOO_FEW_OFFERS:
//    case PATH_PAYMENT_STRICT_RECEIVE_OFFER_CROSS_SELF:
//    case PATH_PAYMENT_STRICT_RECEIVE_OVER_SENDMAX:
//        void;
//    };
//
// union with discriminant PathPaymentStrictReceiveResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum PathPaymentStrictReceiveResult {
    Success(PathPaymentStrictReceiveResultSuccess),
    Malformed,
    Underfunded,
    SrcNoTrust,
    SrcNotAuthorized,
    NoDestination,
    NoTrust,
    NotAuthorized,
    LineFull,
    NoIssuer(Asset),
    TooFewOffers,
    OfferCrossSelf,
    OverSendmax,
}

impl PathPaymentStrictReceiveResult {
    pub const VARIANTS: [PathPaymentStrictReceiveResultCode; 13] = [
        PathPaymentStrictReceiveResultCode::Success,
        PathPaymentStrictReceiveResultCode::Malformed,
        PathPaymentStrictReceiveResultCode::Underfunded,
        PathPaymentStrictReceiveResultCode::SrcNoTrust,
        PathPaymentStrictReceiveResultCode::SrcNotAuthorized,
        PathPaymentStrictReceiveResultCode::NoDestination,
        PathPaymentStrictReceiveResultCode::NoTrust,
        PathPaymentStrictReceiveResultCode::NotAuthorized,
        PathPaymentStrictReceiveResultCode::LineFull,
        PathPaymentStrictReceiveResultCode::NoIssuer,
        PathPaymentStrictReceiveResultCode::TooFewOffers,
        PathPaymentStrictReceiveResultCode::OfferCrossSelf,
        PathPaymentStrictReceiveResultCode::OverSendmax,
    ];
    pub const VARIANTS_STR: [&'static str; 13] = [
        "Success",
        "Malformed",
        "Underfunded",
        "SrcNoTrust",
        "SrcNotAuthorized",
        "NoDestination",
        "NoTrust",
        "NotAuthorized",
        "LineFull",
        "NoIssuer",
        "TooFewOffers",
        "OfferCrossSelf",
        "OverSendmax",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success(_) => "Success",
            Self::Malformed => "Malformed",
            Self::Underfunded => "Underfunded",
            Self::SrcNoTrust => "SrcNoTrust",
            Self::SrcNotAuthorized => "SrcNotAuthorized",
            Self::NoDestination => "NoDestination",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::LineFull => "LineFull",
            Self::NoIssuer(_) => "NoIssuer",
            Self::TooFewOffers => "TooFewOffers",
            Self::OfferCrossSelf => "OfferCrossSelf",
            Self::OverSendmax => "OverSendmax",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> PathPaymentStrictReceiveResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(_) => PathPaymentStrictReceiveResultCode::Success,
            Self::Malformed => PathPaymentStrictReceiveResultCode::Malformed,
            Self::Underfunded => PathPaymentStrictReceiveResultCode::Underfunded,
            Self::SrcNoTrust => PathPaymentStrictReceiveResultCode::SrcNoTrust,
            Self::SrcNotAuthorized => PathPaymentStrictReceiveResultCode::SrcNotAuthorized,
            Self::NoDestination => PathPaymentStrictReceiveResultCode::NoDestination,
            Self::NoTrust => PathPaymentStrictReceiveResultCode::NoTrust,
            Self::NotAuthorized => PathPaymentStrictReceiveResultCode::NotAuthorized,
            Self::LineFull => PathPaymentStrictReceiveResultCode::LineFull,
            Self::NoIssuer(_) => PathPaymentStrictReceiveResultCode::NoIssuer,
            Self::TooFewOffers => PathPaymentStrictReceiveResultCode::TooFewOffers,
            Self::OfferCrossSelf => PathPaymentStrictReceiveResultCode::OfferCrossSelf,
            Self::OverSendmax => PathPaymentStrictReceiveResultCode::OverSendmax,
        }
    }

    #[must_use]
    pub const fn variants() -> [PathPaymentStrictReceiveResultCode; 13] {
        Self::VARIANTS
    }
}

impl Name for PathPaymentStrictReceiveResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<PathPaymentStrictReceiveResultCode> for PathPaymentStrictReceiveResult {
    #[must_use]
    fn discriminant(&self) -> PathPaymentStrictReceiveResultCode {
        Self::discriminant(self)
    }
}

impl Variants<PathPaymentStrictReceiveResultCode> for PathPaymentStrictReceiveResult {
    fn variants() -> slice::Iter<'static, PathPaymentStrictReceiveResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<PathPaymentStrictReceiveResultCode> for PathPaymentStrictReceiveResult {}

impl ReadXdr for PathPaymentStrictReceiveResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: PathPaymentStrictReceiveResultCode =
            <PathPaymentStrictReceiveResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            PathPaymentStrictReceiveResultCode::Success => {
                Self::Success(PathPaymentStrictReceiveResultSuccess::read_xdr(r)?)
            }
            PathPaymentStrictReceiveResultCode::Malformed => Self::Malformed,
            PathPaymentStrictReceiveResultCode::Underfunded => Self::Underfunded,
            PathPaymentStrictReceiveResultCode::SrcNoTrust => Self::SrcNoTrust,
            PathPaymentStrictReceiveResultCode::SrcNotAuthorized => Self::SrcNotAuthorized,
            PathPaymentStrictReceiveResultCode::NoDestination => Self::NoDestination,
            PathPaymentStrictReceiveResultCode::NoTrust => Self::NoTrust,
            PathPaymentStrictReceiveResultCode::NotAuthorized => Self::NotAuthorized,
            PathPaymentStrictReceiveResultCode::LineFull => Self::LineFull,
            PathPaymentStrictReceiveResultCode::NoIssuer => Self::NoIssuer(Asset::read_xdr(r)?),
            PathPaymentStrictReceiveResultCode::TooFewOffers => Self::TooFewOffers,
            PathPaymentStrictReceiveResultCode::OfferCrossSelf => Self::OfferCrossSelf,
            PathPaymentStrictReceiveResultCode::OverSendmax => Self::OverSendmax,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for PathPaymentStrictReceiveResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(v) => v.write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
            Self::SrcNoTrust => ().write_xdr(w)?,
            Self::SrcNotAuthorized => ().write_xdr(w)?,
            Self::NoDestination => ().write_xdr(w)?,
            Self::NoTrust => ().write_xdr(w)?,
            Self::NotAuthorized => ().write_xdr(w)?,
            Self::LineFull => ().write_xdr(w)?,
            Self::NoIssuer(v) => v.write_xdr(w)?,
            Self::TooFewOffers => ().write_xdr(w)?,
            Self::OfferCrossSelf => ().write_xdr(w)?,
            Self::OverSendmax => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// PathPaymentStrictSendResultCode is an XDR Enum defines as:
//
//   enum PathPaymentStrictSendResultCode
//    {
//        // codes considered as "success" for the operation
//        PATH_PAYMENT_STRICT_SEND_SUCCESS = 0, // success
//
//        // codes considered as "failure" for the operation
//        PATH_PAYMENT_STRICT_SEND_MALFORMED = -1, // bad input
//        PATH_PAYMENT_STRICT_SEND_UNDERFUNDED =
//            -2, // not enough funds in source account
//        PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST =
//            -3, // no trust line on source account
//        PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED =
//            -4, // source not authorized to transfer
//        PATH_PAYMENT_STRICT_SEND_NO_DESTINATION =
//            -5, // destination account does not exist
//        PATH_PAYMENT_STRICT_SEND_NO_TRUST =
//            -6, // dest missing a trust line for asset
//        PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED =
//            -7, // dest not authorized to hold asset
//        PATH_PAYMENT_STRICT_SEND_LINE_FULL = -8, // dest would go above their limit
//        PATH_PAYMENT_STRICT_SEND_NO_ISSUER = -9, // missing issuer on one asset
//        PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS =
//            -10, // not enough offers to satisfy path
//        PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF =
//            -11, // would cross one of its own offers
//        PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN = -12 // could not satisfy destMin
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum PathPaymentStrictSendResultCode {
    Success = 0,
    Malformed = -1,
    Underfunded = -2,
    SrcNoTrust = -3,
    SrcNotAuthorized = -4,
    NoDestination = -5,
    NoTrust = -6,
    NotAuthorized = -7,
    LineFull = -8,
    NoIssuer = -9,
    TooFewOffers = -10,
    OfferCrossSelf = -11,
    UnderDestmin = -12,
}

impl PathPaymentStrictSendResultCode {
    pub const VARIANTS: [PathPaymentStrictSendResultCode; 13] = [
        PathPaymentStrictSendResultCode::Success,
        PathPaymentStrictSendResultCode::Malformed,
        PathPaymentStrictSendResultCode::Underfunded,
        PathPaymentStrictSendResultCode::SrcNoTrust,
        PathPaymentStrictSendResultCode::SrcNotAuthorized,
        PathPaymentStrictSendResultCode::NoDestination,
        PathPaymentStrictSendResultCode::NoTrust,
        PathPaymentStrictSendResultCode::NotAuthorized,
        PathPaymentStrictSendResultCode::LineFull,
        PathPaymentStrictSendResultCode::NoIssuer,
        PathPaymentStrictSendResultCode::TooFewOffers,
        PathPaymentStrictSendResultCode::OfferCrossSelf,
        PathPaymentStrictSendResultCode::UnderDestmin,
    ];
    pub const VARIANTS_STR: [&'static str; 13] = [
        "Success",
        "Malformed",
        "Underfunded",
        "SrcNoTrust",
        "SrcNotAuthorized",
        "NoDestination",
        "NoTrust",
        "NotAuthorized",
        "LineFull",
        "NoIssuer",
        "TooFewOffers",
        "OfferCrossSelf",
        "UnderDestmin",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::Underfunded => "Underfunded",
            Self::SrcNoTrust => "SrcNoTrust",
            Self::SrcNotAuthorized => "SrcNotAuthorized",
            Self::NoDestination => "NoDestination",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::LineFull => "LineFull",
            Self::NoIssuer => "NoIssuer",
            Self::TooFewOffers => "TooFewOffers",
            Self::OfferCrossSelf => "OfferCrossSelf",
            Self::UnderDestmin => "UnderDestmin",
        }
    }

    #[must_use]
    pub const fn variants() -> [PathPaymentStrictSendResultCode; 13] {
        Self::VARIANTS
    }
}

impl Name for PathPaymentStrictSendResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<PathPaymentStrictSendResultCode> for PathPaymentStrictSendResultCode {
    fn variants() -> slice::Iter<'static, PathPaymentStrictSendResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for PathPaymentStrictSendResultCode {}

impl fmt::Display for PathPaymentStrictSendResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for PathPaymentStrictSendResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => PathPaymentStrictSendResultCode::Success,
            -1 => PathPaymentStrictSendResultCode::Malformed,
            -2 => PathPaymentStrictSendResultCode::Underfunded,
            -3 => PathPaymentStrictSendResultCode::SrcNoTrust,
            -4 => PathPaymentStrictSendResultCode::SrcNotAuthorized,
            -5 => PathPaymentStrictSendResultCode::NoDestination,
            -6 => PathPaymentStrictSendResultCode::NoTrust,
            -7 => PathPaymentStrictSendResultCode::NotAuthorized,
            -8 => PathPaymentStrictSendResultCode::LineFull,
            -9 => PathPaymentStrictSendResultCode::NoIssuer,
            -10 => PathPaymentStrictSendResultCode::TooFewOffers,
            -11 => PathPaymentStrictSendResultCode::OfferCrossSelf,
            -12 => PathPaymentStrictSendResultCode::UnderDestmin,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<PathPaymentStrictSendResultCode> for i32 {
    #[must_use]
    fn from(e: PathPaymentStrictSendResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for PathPaymentStrictSendResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for PathPaymentStrictSendResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// PathPaymentStrictSendResultSuccess is an XDR NestedStruct defines as:
//
//   struct
//        {
//            ClaimAtom offers<>;
//            SimplePaymentResult last;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct PathPaymentStrictSendResultSuccess {
    pub offers: VecM<ClaimAtom>,
    pub last: SimplePaymentResult,
}

impl ReadXdr for PathPaymentStrictSendResultSuccess {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            offers: VecM::<ClaimAtom>::read_xdr(r)?,
            last: SimplePaymentResult::read_xdr(r)?,
        })
    }
}

impl WriteXdr for PathPaymentStrictSendResultSuccess {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.offers.write_xdr(w)?;
        self.last.write_xdr(w)?;
        Ok(())
    }
}

// PathPaymentStrictSendResult is an XDR Union defines as:
//
//   union PathPaymentStrictSendResult switch (PathPaymentStrictSendResultCode code)
//    {
//    case PATH_PAYMENT_STRICT_SEND_SUCCESS:
//        struct
//        {
//            ClaimAtom offers<>;
//            SimplePaymentResult last;
//        } success;
//    case PATH_PAYMENT_STRICT_SEND_MALFORMED:
//    case PATH_PAYMENT_STRICT_SEND_UNDERFUNDED:
//    case PATH_PAYMENT_STRICT_SEND_SRC_NO_TRUST:
//    case PATH_PAYMENT_STRICT_SEND_SRC_NOT_AUTHORIZED:
//    case PATH_PAYMENT_STRICT_SEND_NO_DESTINATION:
//    case PATH_PAYMENT_STRICT_SEND_NO_TRUST:
//    case PATH_PAYMENT_STRICT_SEND_NOT_AUTHORIZED:
//    case PATH_PAYMENT_STRICT_SEND_LINE_FULL:
//        void;
//    case PATH_PAYMENT_STRICT_SEND_NO_ISSUER:
//        Asset noIssuer; // the asset that caused the error
//    case PATH_PAYMENT_STRICT_SEND_TOO_FEW_OFFERS:
//    case PATH_PAYMENT_STRICT_SEND_OFFER_CROSS_SELF:
//    case PATH_PAYMENT_STRICT_SEND_UNDER_DESTMIN:
//        void;
//    };
//
// union with discriminant PathPaymentStrictSendResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum PathPaymentStrictSendResult {
    Success(PathPaymentStrictSendResultSuccess),
    Malformed,
    Underfunded,
    SrcNoTrust,
    SrcNotAuthorized,
    NoDestination,
    NoTrust,
    NotAuthorized,
    LineFull,
    NoIssuer(Asset),
    TooFewOffers,
    OfferCrossSelf,
    UnderDestmin,
}

impl PathPaymentStrictSendResult {
    pub const VARIANTS: [PathPaymentStrictSendResultCode; 13] = [
        PathPaymentStrictSendResultCode::Success,
        PathPaymentStrictSendResultCode::Malformed,
        PathPaymentStrictSendResultCode::Underfunded,
        PathPaymentStrictSendResultCode::SrcNoTrust,
        PathPaymentStrictSendResultCode::SrcNotAuthorized,
        PathPaymentStrictSendResultCode::NoDestination,
        PathPaymentStrictSendResultCode::NoTrust,
        PathPaymentStrictSendResultCode::NotAuthorized,
        PathPaymentStrictSendResultCode::LineFull,
        PathPaymentStrictSendResultCode::NoIssuer,
        PathPaymentStrictSendResultCode::TooFewOffers,
        PathPaymentStrictSendResultCode::OfferCrossSelf,
        PathPaymentStrictSendResultCode::UnderDestmin,
    ];
    pub const VARIANTS_STR: [&'static str; 13] = [
        "Success",
        "Malformed",
        "Underfunded",
        "SrcNoTrust",
        "SrcNotAuthorized",
        "NoDestination",
        "NoTrust",
        "NotAuthorized",
        "LineFull",
        "NoIssuer",
        "TooFewOffers",
        "OfferCrossSelf",
        "UnderDestmin",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success(_) => "Success",
            Self::Malformed => "Malformed",
            Self::Underfunded => "Underfunded",
            Self::SrcNoTrust => "SrcNoTrust",
            Self::SrcNotAuthorized => "SrcNotAuthorized",
            Self::NoDestination => "NoDestination",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::LineFull => "LineFull",
            Self::NoIssuer(_) => "NoIssuer",
            Self::TooFewOffers => "TooFewOffers",
            Self::OfferCrossSelf => "OfferCrossSelf",
            Self::UnderDestmin => "UnderDestmin",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> PathPaymentStrictSendResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(_) => PathPaymentStrictSendResultCode::Success,
            Self::Malformed => PathPaymentStrictSendResultCode::Malformed,
            Self::Underfunded => PathPaymentStrictSendResultCode::Underfunded,
            Self::SrcNoTrust => PathPaymentStrictSendResultCode::SrcNoTrust,
            Self::SrcNotAuthorized => PathPaymentStrictSendResultCode::SrcNotAuthorized,
            Self::NoDestination => PathPaymentStrictSendResultCode::NoDestination,
            Self::NoTrust => PathPaymentStrictSendResultCode::NoTrust,
            Self::NotAuthorized => PathPaymentStrictSendResultCode::NotAuthorized,
            Self::LineFull => PathPaymentStrictSendResultCode::LineFull,
            Self::NoIssuer(_) => PathPaymentStrictSendResultCode::NoIssuer,
            Self::TooFewOffers => PathPaymentStrictSendResultCode::TooFewOffers,
            Self::OfferCrossSelf => PathPaymentStrictSendResultCode::OfferCrossSelf,
            Self::UnderDestmin => PathPaymentStrictSendResultCode::UnderDestmin,
        }
    }

    #[must_use]
    pub const fn variants() -> [PathPaymentStrictSendResultCode; 13] {
        Self::VARIANTS
    }
}

impl Name for PathPaymentStrictSendResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<PathPaymentStrictSendResultCode> for PathPaymentStrictSendResult {
    #[must_use]
    fn discriminant(&self) -> PathPaymentStrictSendResultCode {
        Self::discriminant(self)
    }
}

impl Variants<PathPaymentStrictSendResultCode> for PathPaymentStrictSendResult {
    fn variants() -> slice::Iter<'static, PathPaymentStrictSendResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<PathPaymentStrictSendResultCode> for PathPaymentStrictSendResult {}

impl ReadXdr for PathPaymentStrictSendResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: PathPaymentStrictSendResultCode =
            <PathPaymentStrictSendResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            PathPaymentStrictSendResultCode::Success => {
                Self::Success(PathPaymentStrictSendResultSuccess::read_xdr(r)?)
            }
            PathPaymentStrictSendResultCode::Malformed => Self::Malformed,
            PathPaymentStrictSendResultCode::Underfunded => Self::Underfunded,
            PathPaymentStrictSendResultCode::SrcNoTrust => Self::SrcNoTrust,
            PathPaymentStrictSendResultCode::SrcNotAuthorized => Self::SrcNotAuthorized,
            PathPaymentStrictSendResultCode::NoDestination => Self::NoDestination,
            PathPaymentStrictSendResultCode::NoTrust => Self::NoTrust,
            PathPaymentStrictSendResultCode::NotAuthorized => Self::NotAuthorized,
            PathPaymentStrictSendResultCode::LineFull => Self::LineFull,
            PathPaymentStrictSendResultCode::NoIssuer => Self::NoIssuer(Asset::read_xdr(r)?),
            PathPaymentStrictSendResultCode::TooFewOffers => Self::TooFewOffers,
            PathPaymentStrictSendResultCode::OfferCrossSelf => Self::OfferCrossSelf,
            PathPaymentStrictSendResultCode::UnderDestmin => Self::UnderDestmin,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for PathPaymentStrictSendResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(v) => v.write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
            Self::SrcNoTrust => ().write_xdr(w)?,
            Self::SrcNotAuthorized => ().write_xdr(w)?,
            Self::NoDestination => ().write_xdr(w)?,
            Self::NoTrust => ().write_xdr(w)?,
            Self::NotAuthorized => ().write_xdr(w)?,
            Self::LineFull => ().write_xdr(w)?,
            Self::NoIssuer(v) => v.write_xdr(w)?,
            Self::TooFewOffers => ().write_xdr(w)?,
            Self::OfferCrossSelf => ().write_xdr(w)?,
            Self::UnderDestmin => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ManageSellOfferResultCode is an XDR Enum defines as:
//
//   enum ManageSellOfferResultCode
//    {
//        // codes considered as "success" for the operation
//        MANAGE_SELL_OFFER_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        MANAGE_SELL_OFFER_MALFORMED = -1, // generated offer would be invalid
//        MANAGE_SELL_OFFER_SELL_NO_TRUST =
//            -2,                              // no trust line for what we're selling
//        MANAGE_SELL_OFFER_BUY_NO_TRUST = -3, // no trust line for what we're buying
//        MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell
//        MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED = -5,  // not authorized to buy
//        MANAGE_SELL_OFFER_LINE_FULL = -6, // can't receive more of what it's buying
//        MANAGE_SELL_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell
//        MANAGE_SELL_OFFER_CROSS_SELF =
//            -8, // would cross an offer from the same user
//        MANAGE_SELL_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling
//        MANAGE_SELL_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying
//
//        // update errors
//        MANAGE_SELL_OFFER_NOT_FOUND =
//            -11, // offerID does not match an existing offer
//
//        MANAGE_SELL_OFFER_LOW_RESERVE =
//            -12 // not enough funds to create a new Offer
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ManageSellOfferResultCode {
    Success = 0,
    Malformed = -1,
    SellNoTrust = -2,
    BuyNoTrust = -3,
    SellNotAuthorized = -4,
    BuyNotAuthorized = -5,
    LineFull = -6,
    Underfunded = -7,
    CrossSelf = -8,
    SellNoIssuer = -9,
    BuyNoIssuer = -10,
    NotFound = -11,
    LowReserve = -12,
}

impl ManageSellOfferResultCode {
    pub const VARIANTS: [ManageSellOfferResultCode; 13] = [
        ManageSellOfferResultCode::Success,
        ManageSellOfferResultCode::Malformed,
        ManageSellOfferResultCode::SellNoTrust,
        ManageSellOfferResultCode::BuyNoTrust,
        ManageSellOfferResultCode::SellNotAuthorized,
        ManageSellOfferResultCode::BuyNotAuthorized,
        ManageSellOfferResultCode::LineFull,
        ManageSellOfferResultCode::Underfunded,
        ManageSellOfferResultCode::CrossSelf,
        ManageSellOfferResultCode::SellNoIssuer,
        ManageSellOfferResultCode::BuyNoIssuer,
        ManageSellOfferResultCode::NotFound,
        ManageSellOfferResultCode::LowReserve,
    ];
    pub const VARIANTS_STR: [&'static str; 13] = [
        "Success",
        "Malformed",
        "SellNoTrust",
        "BuyNoTrust",
        "SellNotAuthorized",
        "BuyNotAuthorized",
        "LineFull",
        "Underfunded",
        "CrossSelf",
        "SellNoIssuer",
        "BuyNoIssuer",
        "NotFound",
        "LowReserve",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::SellNoTrust => "SellNoTrust",
            Self::BuyNoTrust => "BuyNoTrust",
            Self::SellNotAuthorized => "SellNotAuthorized",
            Self::BuyNotAuthorized => "BuyNotAuthorized",
            Self::LineFull => "LineFull",
            Self::Underfunded => "Underfunded",
            Self::CrossSelf => "CrossSelf",
            Self::SellNoIssuer => "SellNoIssuer",
            Self::BuyNoIssuer => "BuyNoIssuer",
            Self::NotFound => "NotFound",
            Self::LowReserve => "LowReserve",
        }
    }

    #[must_use]
    pub const fn variants() -> [ManageSellOfferResultCode; 13] {
        Self::VARIANTS
    }
}

impl Name for ManageSellOfferResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ManageSellOfferResultCode> for ManageSellOfferResultCode {
    fn variants() -> slice::Iter<'static, ManageSellOfferResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ManageSellOfferResultCode {}

impl fmt::Display for ManageSellOfferResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ManageSellOfferResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ManageSellOfferResultCode::Success,
            -1 => ManageSellOfferResultCode::Malformed,
            -2 => ManageSellOfferResultCode::SellNoTrust,
            -3 => ManageSellOfferResultCode::BuyNoTrust,
            -4 => ManageSellOfferResultCode::SellNotAuthorized,
            -5 => ManageSellOfferResultCode::BuyNotAuthorized,
            -6 => ManageSellOfferResultCode::LineFull,
            -7 => ManageSellOfferResultCode::Underfunded,
            -8 => ManageSellOfferResultCode::CrossSelf,
            -9 => ManageSellOfferResultCode::SellNoIssuer,
            -10 => ManageSellOfferResultCode::BuyNoIssuer,
            -11 => ManageSellOfferResultCode::NotFound,
            -12 => ManageSellOfferResultCode::LowReserve,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ManageSellOfferResultCode> for i32 {
    #[must_use]
    fn from(e: ManageSellOfferResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ManageSellOfferResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ManageSellOfferResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ManageOfferEffect is an XDR Enum defines as:
//
//   enum ManageOfferEffect
//    {
//        MANAGE_OFFER_CREATED = 0,
//        MANAGE_OFFER_UPDATED = 1,
//        MANAGE_OFFER_DELETED = 2
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ManageOfferEffect {
    Created = 0,
    Updated = 1,
    Deleted = 2,
}

impl ManageOfferEffect {
    pub const VARIANTS: [ManageOfferEffect; 3] = [
        ManageOfferEffect::Created,
        ManageOfferEffect::Updated,
        ManageOfferEffect::Deleted,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["Created", "Updated", "Deleted"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Created => "Created",
            Self::Updated => "Updated",
            Self::Deleted => "Deleted",
        }
    }

    #[must_use]
    pub const fn variants() -> [ManageOfferEffect; 3] {
        Self::VARIANTS
    }
}

impl Name for ManageOfferEffect {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ManageOfferEffect> for ManageOfferEffect {
    fn variants() -> slice::Iter<'static, ManageOfferEffect> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ManageOfferEffect {}

impl fmt::Display for ManageOfferEffect {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ManageOfferEffect {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ManageOfferEffect::Created,
            1 => ManageOfferEffect::Updated,
            2 => ManageOfferEffect::Deleted,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ManageOfferEffect> for i32 {
    #[must_use]
    fn from(e: ManageOfferEffect) -> Self {
        e as Self
    }
}

impl ReadXdr for ManageOfferEffect {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ManageOfferEffect {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ManageOfferSuccessResultOffer is an XDR NestedUnion defines as:
//
//   union switch (ManageOfferEffect effect)
//        {
//        case MANAGE_OFFER_CREATED:
//        case MANAGE_OFFER_UPDATED:
//            OfferEntry offer;
//        case MANAGE_OFFER_DELETED:
//            void;
//        }
//
// union with discriminant ManageOfferEffect
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ManageOfferSuccessResultOffer {
    Created(OfferEntry),
    Updated(OfferEntry),
    Deleted,
}

impl ManageOfferSuccessResultOffer {
    pub const VARIANTS: [ManageOfferEffect; 3] = [
        ManageOfferEffect::Created,
        ManageOfferEffect::Updated,
        ManageOfferEffect::Deleted,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["Created", "Updated", "Deleted"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Created(_) => "Created",
            Self::Updated(_) => "Updated",
            Self::Deleted => "Deleted",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ManageOfferEffect {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Created(_) => ManageOfferEffect::Created,
            Self::Updated(_) => ManageOfferEffect::Updated,
            Self::Deleted => ManageOfferEffect::Deleted,
        }
    }

    #[must_use]
    pub const fn variants() -> [ManageOfferEffect; 3] {
        Self::VARIANTS
    }
}

impl Name for ManageOfferSuccessResultOffer {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ManageOfferEffect> for ManageOfferSuccessResultOffer {
    #[must_use]
    fn discriminant(&self) -> ManageOfferEffect {
        Self::discriminant(self)
    }
}

impl Variants<ManageOfferEffect> for ManageOfferSuccessResultOffer {
    fn variants() -> slice::Iter<'static, ManageOfferEffect> {
        Self::VARIANTS.iter()
    }
}

impl Union<ManageOfferEffect> for ManageOfferSuccessResultOffer {}

impl ReadXdr for ManageOfferSuccessResultOffer {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ManageOfferEffect = <ManageOfferEffect as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ManageOfferEffect::Created => Self::Created(OfferEntry::read_xdr(r)?),
            ManageOfferEffect::Updated => Self::Updated(OfferEntry::read_xdr(r)?),
            ManageOfferEffect::Deleted => Self::Deleted,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ManageOfferSuccessResultOffer {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Created(v) => v.write_xdr(w)?,
            Self::Updated(v) => v.write_xdr(w)?,
            Self::Deleted => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ManageOfferSuccessResult is an XDR Struct defines as:
//
//   struct ManageOfferSuccessResult
//    {
//        // offers that got claimed while creating this offer
//        ClaimAtom offersClaimed<>;
//
//        union switch (ManageOfferEffect effect)
//        {
//        case MANAGE_OFFER_CREATED:
//        case MANAGE_OFFER_UPDATED:
//            OfferEntry offer;
//        case MANAGE_OFFER_DELETED:
//            void;
//        }
//        offer;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct ManageOfferSuccessResult {
    pub offers_claimed: VecM<ClaimAtom>,
    pub offer: ManageOfferSuccessResultOffer,
}

impl ReadXdr for ManageOfferSuccessResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            offers_claimed: VecM::<ClaimAtom>::read_xdr(r)?,
            offer: ManageOfferSuccessResultOffer::read_xdr(r)?,
        })
    }
}

impl WriteXdr for ManageOfferSuccessResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.offers_claimed.write_xdr(w)?;
        self.offer.write_xdr(w)?;
        Ok(())
    }
}

// ManageSellOfferResult is an XDR Union defines as:
//
//   union ManageSellOfferResult switch (ManageSellOfferResultCode code)
//    {
//    case MANAGE_SELL_OFFER_SUCCESS:
//        ManageOfferSuccessResult success;
//    case MANAGE_SELL_OFFER_MALFORMED:
//    case MANAGE_SELL_OFFER_SELL_NO_TRUST:
//    case MANAGE_SELL_OFFER_BUY_NO_TRUST:
//    case MANAGE_SELL_OFFER_SELL_NOT_AUTHORIZED:
//    case MANAGE_SELL_OFFER_BUY_NOT_AUTHORIZED:
//    case MANAGE_SELL_OFFER_LINE_FULL:
//    case MANAGE_SELL_OFFER_UNDERFUNDED:
//    case MANAGE_SELL_OFFER_CROSS_SELF:
//    case MANAGE_SELL_OFFER_SELL_NO_ISSUER:
//    case MANAGE_SELL_OFFER_BUY_NO_ISSUER:
//    case MANAGE_SELL_OFFER_NOT_FOUND:
//    case MANAGE_SELL_OFFER_LOW_RESERVE:
//        void;
//    };
//
// union with discriminant ManageSellOfferResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ManageSellOfferResult {
    Success(ManageOfferSuccessResult),
    Malformed,
    SellNoTrust,
    BuyNoTrust,
    SellNotAuthorized,
    BuyNotAuthorized,
    LineFull,
    Underfunded,
    CrossSelf,
    SellNoIssuer,
    BuyNoIssuer,
    NotFound,
    LowReserve,
}

impl ManageSellOfferResult {
    pub const VARIANTS: [ManageSellOfferResultCode; 13] = [
        ManageSellOfferResultCode::Success,
        ManageSellOfferResultCode::Malformed,
        ManageSellOfferResultCode::SellNoTrust,
        ManageSellOfferResultCode::BuyNoTrust,
        ManageSellOfferResultCode::SellNotAuthorized,
        ManageSellOfferResultCode::BuyNotAuthorized,
        ManageSellOfferResultCode::LineFull,
        ManageSellOfferResultCode::Underfunded,
        ManageSellOfferResultCode::CrossSelf,
        ManageSellOfferResultCode::SellNoIssuer,
        ManageSellOfferResultCode::BuyNoIssuer,
        ManageSellOfferResultCode::NotFound,
        ManageSellOfferResultCode::LowReserve,
    ];
    pub const VARIANTS_STR: [&'static str; 13] = [
        "Success",
        "Malformed",
        "SellNoTrust",
        "BuyNoTrust",
        "SellNotAuthorized",
        "BuyNotAuthorized",
        "LineFull",
        "Underfunded",
        "CrossSelf",
        "SellNoIssuer",
        "BuyNoIssuer",
        "NotFound",
        "LowReserve",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success(_) => "Success",
            Self::Malformed => "Malformed",
            Self::SellNoTrust => "SellNoTrust",
            Self::BuyNoTrust => "BuyNoTrust",
            Self::SellNotAuthorized => "SellNotAuthorized",
            Self::BuyNotAuthorized => "BuyNotAuthorized",
            Self::LineFull => "LineFull",
            Self::Underfunded => "Underfunded",
            Self::CrossSelf => "CrossSelf",
            Self::SellNoIssuer => "SellNoIssuer",
            Self::BuyNoIssuer => "BuyNoIssuer",
            Self::NotFound => "NotFound",
            Self::LowReserve => "LowReserve",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ManageSellOfferResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(_) => ManageSellOfferResultCode::Success,
            Self::Malformed => ManageSellOfferResultCode::Malformed,
            Self::SellNoTrust => ManageSellOfferResultCode::SellNoTrust,
            Self::BuyNoTrust => ManageSellOfferResultCode::BuyNoTrust,
            Self::SellNotAuthorized => ManageSellOfferResultCode::SellNotAuthorized,
            Self::BuyNotAuthorized => ManageSellOfferResultCode::BuyNotAuthorized,
            Self::LineFull => ManageSellOfferResultCode::LineFull,
            Self::Underfunded => ManageSellOfferResultCode::Underfunded,
            Self::CrossSelf => ManageSellOfferResultCode::CrossSelf,
            Self::SellNoIssuer => ManageSellOfferResultCode::SellNoIssuer,
            Self::BuyNoIssuer => ManageSellOfferResultCode::BuyNoIssuer,
            Self::NotFound => ManageSellOfferResultCode::NotFound,
            Self::LowReserve => ManageSellOfferResultCode::LowReserve,
        }
    }

    #[must_use]
    pub const fn variants() -> [ManageSellOfferResultCode; 13] {
        Self::VARIANTS
    }
}

impl Name for ManageSellOfferResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ManageSellOfferResultCode> for ManageSellOfferResult {
    #[must_use]
    fn discriminant(&self) -> ManageSellOfferResultCode {
        Self::discriminant(self)
    }
}

impl Variants<ManageSellOfferResultCode> for ManageSellOfferResult {
    fn variants() -> slice::Iter<'static, ManageSellOfferResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<ManageSellOfferResultCode> for ManageSellOfferResult {}

impl ReadXdr for ManageSellOfferResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ManageSellOfferResultCode = <ManageSellOfferResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ManageSellOfferResultCode::Success => {
                Self::Success(ManageOfferSuccessResult::read_xdr(r)?)
            }
            ManageSellOfferResultCode::Malformed => Self::Malformed,
            ManageSellOfferResultCode::SellNoTrust => Self::SellNoTrust,
            ManageSellOfferResultCode::BuyNoTrust => Self::BuyNoTrust,
            ManageSellOfferResultCode::SellNotAuthorized => Self::SellNotAuthorized,
            ManageSellOfferResultCode::BuyNotAuthorized => Self::BuyNotAuthorized,
            ManageSellOfferResultCode::LineFull => Self::LineFull,
            ManageSellOfferResultCode::Underfunded => Self::Underfunded,
            ManageSellOfferResultCode::CrossSelf => Self::CrossSelf,
            ManageSellOfferResultCode::SellNoIssuer => Self::SellNoIssuer,
            ManageSellOfferResultCode::BuyNoIssuer => Self::BuyNoIssuer,
            ManageSellOfferResultCode::NotFound => Self::NotFound,
            ManageSellOfferResultCode::LowReserve => Self::LowReserve,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ManageSellOfferResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(v) => v.write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::SellNoTrust => ().write_xdr(w)?,
            Self::BuyNoTrust => ().write_xdr(w)?,
            Self::SellNotAuthorized => ().write_xdr(w)?,
            Self::BuyNotAuthorized => ().write_xdr(w)?,
            Self::LineFull => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
            Self::CrossSelf => ().write_xdr(w)?,
            Self::SellNoIssuer => ().write_xdr(w)?,
            Self::BuyNoIssuer => ().write_xdr(w)?,
            Self::NotFound => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ManageBuyOfferResultCode is an XDR Enum defines as:
//
//   enum ManageBuyOfferResultCode
//    {
//        // codes considered as "success" for the operation
//        MANAGE_BUY_OFFER_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        MANAGE_BUY_OFFER_MALFORMED = -1,     // generated offer would be invalid
//        MANAGE_BUY_OFFER_SELL_NO_TRUST = -2, // no trust line for what we're selling
//        MANAGE_BUY_OFFER_BUY_NO_TRUST = -3,  // no trust line for what we're buying
//        MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED = -4, // not authorized to sell
//        MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED = -5,  // not authorized to buy
//        MANAGE_BUY_OFFER_LINE_FULL = -6,   // can't receive more of what it's buying
//        MANAGE_BUY_OFFER_UNDERFUNDED = -7, // doesn't hold what it's trying to sell
//        MANAGE_BUY_OFFER_CROSS_SELF = -8, // would cross an offer from the same user
//        MANAGE_BUY_OFFER_SELL_NO_ISSUER = -9, // no issuer for what we're selling
//        MANAGE_BUY_OFFER_BUY_NO_ISSUER = -10, // no issuer for what we're buying
//
//        // update errors
//        MANAGE_BUY_OFFER_NOT_FOUND =
//            -11, // offerID does not match an existing offer
//
//        MANAGE_BUY_OFFER_LOW_RESERVE = -12 // not enough funds to create a new Offer
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ManageBuyOfferResultCode {
    Success = 0,
    Malformed = -1,
    SellNoTrust = -2,
    BuyNoTrust = -3,
    SellNotAuthorized = -4,
    BuyNotAuthorized = -5,
    LineFull = -6,
    Underfunded = -7,
    CrossSelf = -8,
    SellNoIssuer = -9,
    BuyNoIssuer = -10,
    NotFound = -11,
    LowReserve = -12,
}

impl ManageBuyOfferResultCode {
    pub const VARIANTS: [ManageBuyOfferResultCode; 13] = [
        ManageBuyOfferResultCode::Success,
        ManageBuyOfferResultCode::Malformed,
        ManageBuyOfferResultCode::SellNoTrust,
        ManageBuyOfferResultCode::BuyNoTrust,
        ManageBuyOfferResultCode::SellNotAuthorized,
        ManageBuyOfferResultCode::BuyNotAuthorized,
        ManageBuyOfferResultCode::LineFull,
        ManageBuyOfferResultCode::Underfunded,
        ManageBuyOfferResultCode::CrossSelf,
        ManageBuyOfferResultCode::SellNoIssuer,
        ManageBuyOfferResultCode::BuyNoIssuer,
        ManageBuyOfferResultCode::NotFound,
        ManageBuyOfferResultCode::LowReserve,
    ];
    pub const VARIANTS_STR: [&'static str; 13] = [
        "Success",
        "Malformed",
        "SellNoTrust",
        "BuyNoTrust",
        "SellNotAuthorized",
        "BuyNotAuthorized",
        "LineFull",
        "Underfunded",
        "CrossSelf",
        "SellNoIssuer",
        "BuyNoIssuer",
        "NotFound",
        "LowReserve",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::SellNoTrust => "SellNoTrust",
            Self::BuyNoTrust => "BuyNoTrust",
            Self::SellNotAuthorized => "SellNotAuthorized",
            Self::BuyNotAuthorized => "BuyNotAuthorized",
            Self::LineFull => "LineFull",
            Self::Underfunded => "Underfunded",
            Self::CrossSelf => "CrossSelf",
            Self::SellNoIssuer => "SellNoIssuer",
            Self::BuyNoIssuer => "BuyNoIssuer",
            Self::NotFound => "NotFound",
            Self::LowReserve => "LowReserve",
        }
    }

    #[must_use]
    pub const fn variants() -> [ManageBuyOfferResultCode; 13] {
        Self::VARIANTS
    }
}

impl Name for ManageBuyOfferResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ManageBuyOfferResultCode> for ManageBuyOfferResultCode {
    fn variants() -> slice::Iter<'static, ManageBuyOfferResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ManageBuyOfferResultCode {}

impl fmt::Display for ManageBuyOfferResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ManageBuyOfferResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ManageBuyOfferResultCode::Success,
            -1 => ManageBuyOfferResultCode::Malformed,
            -2 => ManageBuyOfferResultCode::SellNoTrust,
            -3 => ManageBuyOfferResultCode::BuyNoTrust,
            -4 => ManageBuyOfferResultCode::SellNotAuthorized,
            -5 => ManageBuyOfferResultCode::BuyNotAuthorized,
            -6 => ManageBuyOfferResultCode::LineFull,
            -7 => ManageBuyOfferResultCode::Underfunded,
            -8 => ManageBuyOfferResultCode::CrossSelf,
            -9 => ManageBuyOfferResultCode::SellNoIssuer,
            -10 => ManageBuyOfferResultCode::BuyNoIssuer,
            -11 => ManageBuyOfferResultCode::NotFound,
            -12 => ManageBuyOfferResultCode::LowReserve,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ManageBuyOfferResultCode> for i32 {
    #[must_use]
    fn from(e: ManageBuyOfferResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ManageBuyOfferResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ManageBuyOfferResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ManageBuyOfferResult is an XDR Union defines as:
//
//   union ManageBuyOfferResult switch (ManageBuyOfferResultCode code)
//    {
//    case MANAGE_BUY_OFFER_SUCCESS:
//        ManageOfferSuccessResult success;
//    case MANAGE_BUY_OFFER_MALFORMED:
//    case MANAGE_BUY_OFFER_SELL_NO_TRUST:
//    case MANAGE_BUY_OFFER_BUY_NO_TRUST:
//    case MANAGE_BUY_OFFER_SELL_NOT_AUTHORIZED:
//    case MANAGE_BUY_OFFER_BUY_NOT_AUTHORIZED:
//    case MANAGE_BUY_OFFER_LINE_FULL:
//    case MANAGE_BUY_OFFER_UNDERFUNDED:
//    case MANAGE_BUY_OFFER_CROSS_SELF:
//    case MANAGE_BUY_OFFER_SELL_NO_ISSUER:
//    case MANAGE_BUY_OFFER_BUY_NO_ISSUER:
//    case MANAGE_BUY_OFFER_NOT_FOUND:
//    case MANAGE_BUY_OFFER_LOW_RESERVE:
//        void;
//    };
//
// union with discriminant ManageBuyOfferResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ManageBuyOfferResult {
    Success(ManageOfferSuccessResult),
    Malformed,
    SellNoTrust,
    BuyNoTrust,
    SellNotAuthorized,
    BuyNotAuthorized,
    LineFull,
    Underfunded,
    CrossSelf,
    SellNoIssuer,
    BuyNoIssuer,
    NotFound,
    LowReserve,
}

impl ManageBuyOfferResult {
    pub const VARIANTS: [ManageBuyOfferResultCode; 13] = [
        ManageBuyOfferResultCode::Success,
        ManageBuyOfferResultCode::Malformed,
        ManageBuyOfferResultCode::SellNoTrust,
        ManageBuyOfferResultCode::BuyNoTrust,
        ManageBuyOfferResultCode::SellNotAuthorized,
        ManageBuyOfferResultCode::BuyNotAuthorized,
        ManageBuyOfferResultCode::LineFull,
        ManageBuyOfferResultCode::Underfunded,
        ManageBuyOfferResultCode::CrossSelf,
        ManageBuyOfferResultCode::SellNoIssuer,
        ManageBuyOfferResultCode::BuyNoIssuer,
        ManageBuyOfferResultCode::NotFound,
        ManageBuyOfferResultCode::LowReserve,
    ];
    pub const VARIANTS_STR: [&'static str; 13] = [
        "Success",
        "Malformed",
        "SellNoTrust",
        "BuyNoTrust",
        "SellNotAuthorized",
        "BuyNotAuthorized",
        "LineFull",
        "Underfunded",
        "CrossSelf",
        "SellNoIssuer",
        "BuyNoIssuer",
        "NotFound",
        "LowReserve",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success(_) => "Success",
            Self::Malformed => "Malformed",
            Self::SellNoTrust => "SellNoTrust",
            Self::BuyNoTrust => "BuyNoTrust",
            Self::SellNotAuthorized => "SellNotAuthorized",
            Self::BuyNotAuthorized => "BuyNotAuthorized",
            Self::LineFull => "LineFull",
            Self::Underfunded => "Underfunded",
            Self::CrossSelf => "CrossSelf",
            Self::SellNoIssuer => "SellNoIssuer",
            Self::BuyNoIssuer => "BuyNoIssuer",
            Self::NotFound => "NotFound",
            Self::LowReserve => "LowReserve",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ManageBuyOfferResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(_) => ManageBuyOfferResultCode::Success,
            Self::Malformed => ManageBuyOfferResultCode::Malformed,
            Self::SellNoTrust => ManageBuyOfferResultCode::SellNoTrust,
            Self::BuyNoTrust => ManageBuyOfferResultCode::BuyNoTrust,
            Self::SellNotAuthorized => ManageBuyOfferResultCode::SellNotAuthorized,
            Self::BuyNotAuthorized => ManageBuyOfferResultCode::BuyNotAuthorized,
            Self::LineFull => ManageBuyOfferResultCode::LineFull,
            Self::Underfunded => ManageBuyOfferResultCode::Underfunded,
            Self::CrossSelf => ManageBuyOfferResultCode::CrossSelf,
            Self::SellNoIssuer => ManageBuyOfferResultCode::SellNoIssuer,
            Self::BuyNoIssuer => ManageBuyOfferResultCode::BuyNoIssuer,
            Self::NotFound => ManageBuyOfferResultCode::NotFound,
            Self::LowReserve => ManageBuyOfferResultCode::LowReserve,
        }
    }

    #[must_use]
    pub const fn variants() -> [ManageBuyOfferResultCode; 13] {
        Self::VARIANTS
    }
}

impl Name for ManageBuyOfferResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ManageBuyOfferResultCode> for ManageBuyOfferResult {
    #[must_use]
    fn discriminant(&self) -> ManageBuyOfferResultCode {
        Self::discriminant(self)
    }
}

impl Variants<ManageBuyOfferResultCode> for ManageBuyOfferResult {
    fn variants() -> slice::Iter<'static, ManageBuyOfferResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<ManageBuyOfferResultCode> for ManageBuyOfferResult {}

impl ReadXdr for ManageBuyOfferResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ManageBuyOfferResultCode = <ManageBuyOfferResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ManageBuyOfferResultCode::Success => {
                Self::Success(ManageOfferSuccessResult::read_xdr(r)?)
            }
            ManageBuyOfferResultCode::Malformed => Self::Malformed,
            ManageBuyOfferResultCode::SellNoTrust => Self::SellNoTrust,
            ManageBuyOfferResultCode::BuyNoTrust => Self::BuyNoTrust,
            ManageBuyOfferResultCode::SellNotAuthorized => Self::SellNotAuthorized,
            ManageBuyOfferResultCode::BuyNotAuthorized => Self::BuyNotAuthorized,
            ManageBuyOfferResultCode::LineFull => Self::LineFull,
            ManageBuyOfferResultCode::Underfunded => Self::Underfunded,
            ManageBuyOfferResultCode::CrossSelf => Self::CrossSelf,
            ManageBuyOfferResultCode::SellNoIssuer => Self::SellNoIssuer,
            ManageBuyOfferResultCode::BuyNoIssuer => Self::BuyNoIssuer,
            ManageBuyOfferResultCode::NotFound => Self::NotFound,
            ManageBuyOfferResultCode::LowReserve => Self::LowReserve,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ManageBuyOfferResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(v) => v.write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::SellNoTrust => ().write_xdr(w)?,
            Self::BuyNoTrust => ().write_xdr(w)?,
            Self::SellNotAuthorized => ().write_xdr(w)?,
            Self::BuyNotAuthorized => ().write_xdr(w)?,
            Self::LineFull => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
            Self::CrossSelf => ().write_xdr(w)?,
            Self::SellNoIssuer => ().write_xdr(w)?,
            Self::BuyNoIssuer => ().write_xdr(w)?,
            Self::NotFound => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// SetOptionsResultCode is an XDR Enum defines as:
//
//   enum SetOptionsResultCode
//    {
//        // codes considered as "success" for the operation
//        SET_OPTIONS_SUCCESS = 0,
//        // codes considered as "failure" for the operation
//        SET_OPTIONS_LOW_RESERVE = -1,      // not enough funds to add a signer
//        SET_OPTIONS_TOO_MANY_SIGNERS = -2, // max number of signers already reached
//        SET_OPTIONS_BAD_FLAGS = -3,        // invalid combination of clear/set flags
//        SET_OPTIONS_INVALID_INFLATION = -4,      // inflation account does not exist
//        SET_OPTIONS_CANT_CHANGE = -5,            // can no longer change this option
//        SET_OPTIONS_UNKNOWN_FLAG = -6,           // can't set an unknown flag
//        SET_OPTIONS_THRESHOLD_OUT_OF_RANGE = -7, // bad value for weight/threshold
//        SET_OPTIONS_BAD_SIGNER = -8,             // signer cannot be masterkey
//        SET_OPTIONS_INVALID_HOME_DOMAIN = -9,    // malformed home domain
//        SET_OPTIONS_AUTH_REVOCABLE_REQUIRED =
//            -10 // auth revocable is required for clawback
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum SetOptionsResultCode {
    Success = 0,
    LowReserve = -1,
    TooManySigners = -2,
    BadFlags = -3,
    InvalidInflation = -4,
    CantChange = -5,
    UnknownFlag = -6,
    ThresholdOutOfRange = -7,
    BadSigner = -8,
    InvalidHomeDomain = -9,
    AuthRevocableRequired = -10,
}

impl SetOptionsResultCode {
    pub const VARIANTS: [SetOptionsResultCode; 11] = [
        SetOptionsResultCode::Success,
        SetOptionsResultCode::LowReserve,
        SetOptionsResultCode::TooManySigners,
        SetOptionsResultCode::BadFlags,
        SetOptionsResultCode::InvalidInflation,
        SetOptionsResultCode::CantChange,
        SetOptionsResultCode::UnknownFlag,
        SetOptionsResultCode::ThresholdOutOfRange,
        SetOptionsResultCode::BadSigner,
        SetOptionsResultCode::InvalidHomeDomain,
        SetOptionsResultCode::AuthRevocableRequired,
    ];
    pub const VARIANTS_STR: [&'static str; 11] = [
        "Success",
        "LowReserve",
        "TooManySigners",
        "BadFlags",
        "InvalidInflation",
        "CantChange",
        "UnknownFlag",
        "ThresholdOutOfRange",
        "BadSigner",
        "InvalidHomeDomain",
        "AuthRevocableRequired",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::LowReserve => "LowReserve",
            Self::TooManySigners => "TooManySigners",
            Self::BadFlags => "BadFlags",
            Self::InvalidInflation => "InvalidInflation",
            Self::CantChange => "CantChange",
            Self::UnknownFlag => "UnknownFlag",
            Self::ThresholdOutOfRange => "ThresholdOutOfRange",
            Self::BadSigner => "BadSigner",
            Self::InvalidHomeDomain => "InvalidHomeDomain",
            Self::AuthRevocableRequired => "AuthRevocableRequired",
        }
    }

    #[must_use]
    pub const fn variants() -> [SetOptionsResultCode; 11] {
        Self::VARIANTS
    }
}

impl Name for SetOptionsResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<SetOptionsResultCode> for SetOptionsResultCode {
    fn variants() -> slice::Iter<'static, SetOptionsResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for SetOptionsResultCode {}

impl fmt::Display for SetOptionsResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for SetOptionsResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => SetOptionsResultCode::Success,
            -1 => SetOptionsResultCode::LowReserve,
            -2 => SetOptionsResultCode::TooManySigners,
            -3 => SetOptionsResultCode::BadFlags,
            -4 => SetOptionsResultCode::InvalidInflation,
            -5 => SetOptionsResultCode::CantChange,
            -6 => SetOptionsResultCode::UnknownFlag,
            -7 => SetOptionsResultCode::ThresholdOutOfRange,
            -8 => SetOptionsResultCode::BadSigner,
            -9 => SetOptionsResultCode::InvalidHomeDomain,
            -10 => SetOptionsResultCode::AuthRevocableRequired,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<SetOptionsResultCode> for i32 {
    #[must_use]
    fn from(e: SetOptionsResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for SetOptionsResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for SetOptionsResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// SetOptionsResult is an XDR Union defines as:
//
//   union SetOptionsResult switch (SetOptionsResultCode code)
//    {
//    case SET_OPTIONS_SUCCESS:
//        void;
//    case SET_OPTIONS_LOW_RESERVE:
//    case SET_OPTIONS_TOO_MANY_SIGNERS:
//    case SET_OPTIONS_BAD_FLAGS:
//    case SET_OPTIONS_INVALID_INFLATION:
//    case SET_OPTIONS_CANT_CHANGE:
//    case SET_OPTIONS_UNKNOWN_FLAG:
//    case SET_OPTIONS_THRESHOLD_OUT_OF_RANGE:
//    case SET_OPTIONS_BAD_SIGNER:
//    case SET_OPTIONS_INVALID_HOME_DOMAIN:
//    case SET_OPTIONS_AUTH_REVOCABLE_REQUIRED:
//        void;
//    };
//
// union with discriminant SetOptionsResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum SetOptionsResult {
    Success,
    LowReserve,
    TooManySigners,
    BadFlags,
    InvalidInflation,
    CantChange,
    UnknownFlag,
    ThresholdOutOfRange,
    BadSigner,
    InvalidHomeDomain,
    AuthRevocableRequired,
}

impl SetOptionsResult {
    pub const VARIANTS: [SetOptionsResultCode; 11] = [
        SetOptionsResultCode::Success,
        SetOptionsResultCode::LowReserve,
        SetOptionsResultCode::TooManySigners,
        SetOptionsResultCode::BadFlags,
        SetOptionsResultCode::InvalidInflation,
        SetOptionsResultCode::CantChange,
        SetOptionsResultCode::UnknownFlag,
        SetOptionsResultCode::ThresholdOutOfRange,
        SetOptionsResultCode::BadSigner,
        SetOptionsResultCode::InvalidHomeDomain,
        SetOptionsResultCode::AuthRevocableRequired,
    ];
    pub const VARIANTS_STR: [&'static str; 11] = [
        "Success",
        "LowReserve",
        "TooManySigners",
        "BadFlags",
        "InvalidInflation",
        "CantChange",
        "UnknownFlag",
        "ThresholdOutOfRange",
        "BadSigner",
        "InvalidHomeDomain",
        "AuthRevocableRequired",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::LowReserve => "LowReserve",
            Self::TooManySigners => "TooManySigners",
            Self::BadFlags => "BadFlags",
            Self::InvalidInflation => "InvalidInflation",
            Self::CantChange => "CantChange",
            Self::UnknownFlag => "UnknownFlag",
            Self::ThresholdOutOfRange => "ThresholdOutOfRange",
            Self::BadSigner => "BadSigner",
            Self::InvalidHomeDomain => "InvalidHomeDomain",
            Self::AuthRevocableRequired => "AuthRevocableRequired",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> SetOptionsResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => SetOptionsResultCode::Success,
            Self::LowReserve => SetOptionsResultCode::LowReserve,
            Self::TooManySigners => SetOptionsResultCode::TooManySigners,
            Self::BadFlags => SetOptionsResultCode::BadFlags,
            Self::InvalidInflation => SetOptionsResultCode::InvalidInflation,
            Self::CantChange => SetOptionsResultCode::CantChange,
            Self::UnknownFlag => SetOptionsResultCode::UnknownFlag,
            Self::ThresholdOutOfRange => SetOptionsResultCode::ThresholdOutOfRange,
            Self::BadSigner => SetOptionsResultCode::BadSigner,
            Self::InvalidHomeDomain => SetOptionsResultCode::InvalidHomeDomain,
            Self::AuthRevocableRequired => SetOptionsResultCode::AuthRevocableRequired,
        }
    }

    #[must_use]
    pub const fn variants() -> [SetOptionsResultCode; 11] {
        Self::VARIANTS
    }
}

impl Name for SetOptionsResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<SetOptionsResultCode> for SetOptionsResult {
    #[must_use]
    fn discriminant(&self) -> SetOptionsResultCode {
        Self::discriminant(self)
    }
}

impl Variants<SetOptionsResultCode> for SetOptionsResult {
    fn variants() -> slice::Iter<'static, SetOptionsResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<SetOptionsResultCode> for SetOptionsResult {}

impl ReadXdr for SetOptionsResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: SetOptionsResultCode = <SetOptionsResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            SetOptionsResultCode::Success => Self::Success,
            SetOptionsResultCode::LowReserve => Self::LowReserve,
            SetOptionsResultCode::TooManySigners => Self::TooManySigners,
            SetOptionsResultCode::BadFlags => Self::BadFlags,
            SetOptionsResultCode::InvalidInflation => Self::InvalidInflation,
            SetOptionsResultCode::CantChange => Self::CantChange,
            SetOptionsResultCode::UnknownFlag => Self::UnknownFlag,
            SetOptionsResultCode::ThresholdOutOfRange => Self::ThresholdOutOfRange,
            SetOptionsResultCode::BadSigner => Self::BadSigner,
            SetOptionsResultCode::InvalidHomeDomain => Self::InvalidHomeDomain,
            SetOptionsResultCode::AuthRevocableRequired => Self::AuthRevocableRequired,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for SetOptionsResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
            Self::TooManySigners => ().write_xdr(w)?,
            Self::BadFlags => ().write_xdr(w)?,
            Self::InvalidInflation => ().write_xdr(w)?,
            Self::CantChange => ().write_xdr(w)?,
            Self::UnknownFlag => ().write_xdr(w)?,
            Self::ThresholdOutOfRange => ().write_xdr(w)?,
            Self::BadSigner => ().write_xdr(w)?,
            Self::InvalidHomeDomain => ().write_xdr(w)?,
            Self::AuthRevocableRequired => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ChangeTrustResultCode is an XDR Enum defines as:
//
//   enum ChangeTrustResultCode
//    {
//        // codes considered as "success" for the operation
//        CHANGE_TRUST_SUCCESS = 0,
//        // codes considered as "failure" for the operation
//        CHANGE_TRUST_MALFORMED = -1,     // bad input
//        CHANGE_TRUST_NO_ISSUER = -2,     // could not find issuer
//        CHANGE_TRUST_INVALID_LIMIT = -3, // cannot drop limit below balance
//                                         // cannot create with a limit of 0
//        CHANGE_TRUST_LOW_RESERVE =
//            -4, // not enough funds to create a new trust line,
//        CHANGE_TRUST_SELF_NOT_ALLOWED = -5,   // trusting self is not allowed
//        CHANGE_TRUST_TRUST_LINE_MISSING = -6, // Asset trustline is missing for pool
//        CHANGE_TRUST_CANNOT_DELETE =
//            -7, // Asset trustline is still referenced in a pool
//        CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES =
//            -8 // Asset trustline is deauthorized
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ChangeTrustResultCode {
    Success = 0,
    Malformed = -1,
    NoIssuer = -2,
    InvalidLimit = -3,
    LowReserve = -4,
    SelfNotAllowed = -5,
    TrustLineMissing = -6,
    CannotDelete = -7,
    NotAuthMaintainLiabilities = -8,
}

impl ChangeTrustResultCode {
    pub const VARIANTS: [ChangeTrustResultCode; 9] = [
        ChangeTrustResultCode::Success,
        ChangeTrustResultCode::Malformed,
        ChangeTrustResultCode::NoIssuer,
        ChangeTrustResultCode::InvalidLimit,
        ChangeTrustResultCode::LowReserve,
        ChangeTrustResultCode::SelfNotAllowed,
        ChangeTrustResultCode::TrustLineMissing,
        ChangeTrustResultCode::CannotDelete,
        ChangeTrustResultCode::NotAuthMaintainLiabilities,
    ];
    pub const VARIANTS_STR: [&'static str; 9] = [
        "Success",
        "Malformed",
        "NoIssuer",
        "InvalidLimit",
        "LowReserve",
        "SelfNotAllowed",
        "TrustLineMissing",
        "CannotDelete",
        "NotAuthMaintainLiabilities",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoIssuer => "NoIssuer",
            Self::InvalidLimit => "InvalidLimit",
            Self::LowReserve => "LowReserve",
            Self::SelfNotAllowed => "SelfNotAllowed",
            Self::TrustLineMissing => "TrustLineMissing",
            Self::CannotDelete => "CannotDelete",
            Self::NotAuthMaintainLiabilities => "NotAuthMaintainLiabilities",
        }
    }

    #[must_use]
    pub const fn variants() -> [ChangeTrustResultCode; 9] {
        Self::VARIANTS
    }
}

impl Name for ChangeTrustResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ChangeTrustResultCode> for ChangeTrustResultCode {
    fn variants() -> slice::Iter<'static, ChangeTrustResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ChangeTrustResultCode {}

impl fmt::Display for ChangeTrustResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ChangeTrustResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ChangeTrustResultCode::Success,
            -1 => ChangeTrustResultCode::Malformed,
            -2 => ChangeTrustResultCode::NoIssuer,
            -3 => ChangeTrustResultCode::InvalidLimit,
            -4 => ChangeTrustResultCode::LowReserve,
            -5 => ChangeTrustResultCode::SelfNotAllowed,
            -6 => ChangeTrustResultCode::TrustLineMissing,
            -7 => ChangeTrustResultCode::CannotDelete,
            -8 => ChangeTrustResultCode::NotAuthMaintainLiabilities,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ChangeTrustResultCode> for i32 {
    #[must_use]
    fn from(e: ChangeTrustResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ChangeTrustResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ChangeTrustResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ChangeTrustResult is an XDR Union defines as:
//
//   union ChangeTrustResult switch (ChangeTrustResultCode code)
//    {
//    case CHANGE_TRUST_SUCCESS:
//        void;
//    case CHANGE_TRUST_MALFORMED:
//    case CHANGE_TRUST_NO_ISSUER:
//    case CHANGE_TRUST_INVALID_LIMIT:
//    case CHANGE_TRUST_LOW_RESERVE:
//    case CHANGE_TRUST_SELF_NOT_ALLOWED:
//    case CHANGE_TRUST_TRUST_LINE_MISSING:
//    case CHANGE_TRUST_CANNOT_DELETE:
//    case CHANGE_TRUST_NOT_AUTH_MAINTAIN_LIABILITIES:
//        void;
//    };
//
// union with discriminant ChangeTrustResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ChangeTrustResult {
    Success,
    Malformed,
    NoIssuer,
    InvalidLimit,
    LowReserve,
    SelfNotAllowed,
    TrustLineMissing,
    CannotDelete,
    NotAuthMaintainLiabilities,
}

impl ChangeTrustResult {
    pub const VARIANTS: [ChangeTrustResultCode; 9] = [
        ChangeTrustResultCode::Success,
        ChangeTrustResultCode::Malformed,
        ChangeTrustResultCode::NoIssuer,
        ChangeTrustResultCode::InvalidLimit,
        ChangeTrustResultCode::LowReserve,
        ChangeTrustResultCode::SelfNotAllowed,
        ChangeTrustResultCode::TrustLineMissing,
        ChangeTrustResultCode::CannotDelete,
        ChangeTrustResultCode::NotAuthMaintainLiabilities,
    ];
    pub const VARIANTS_STR: [&'static str; 9] = [
        "Success",
        "Malformed",
        "NoIssuer",
        "InvalidLimit",
        "LowReserve",
        "SelfNotAllowed",
        "TrustLineMissing",
        "CannotDelete",
        "NotAuthMaintainLiabilities",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoIssuer => "NoIssuer",
            Self::InvalidLimit => "InvalidLimit",
            Self::LowReserve => "LowReserve",
            Self::SelfNotAllowed => "SelfNotAllowed",
            Self::TrustLineMissing => "TrustLineMissing",
            Self::CannotDelete => "CannotDelete",
            Self::NotAuthMaintainLiabilities => "NotAuthMaintainLiabilities",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ChangeTrustResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ChangeTrustResultCode::Success,
            Self::Malformed => ChangeTrustResultCode::Malformed,
            Self::NoIssuer => ChangeTrustResultCode::NoIssuer,
            Self::InvalidLimit => ChangeTrustResultCode::InvalidLimit,
            Self::LowReserve => ChangeTrustResultCode::LowReserve,
            Self::SelfNotAllowed => ChangeTrustResultCode::SelfNotAllowed,
            Self::TrustLineMissing => ChangeTrustResultCode::TrustLineMissing,
            Self::CannotDelete => ChangeTrustResultCode::CannotDelete,
            Self::NotAuthMaintainLiabilities => ChangeTrustResultCode::NotAuthMaintainLiabilities,
        }
    }

    #[must_use]
    pub const fn variants() -> [ChangeTrustResultCode; 9] {
        Self::VARIANTS
    }
}

impl Name for ChangeTrustResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ChangeTrustResultCode> for ChangeTrustResult {
    #[must_use]
    fn discriminant(&self) -> ChangeTrustResultCode {
        Self::discriminant(self)
    }
}

impl Variants<ChangeTrustResultCode> for ChangeTrustResult {
    fn variants() -> slice::Iter<'static, ChangeTrustResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<ChangeTrustResultCode> for ChangeTrustResult {}

impl ReadXdr for ChangeTrustResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ChangeTrustResultCode = <ChangeTrustResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ChangeTrustResultCode::Success => Self::Success,
            ChangeTrustResultCode::Malformed => Self::Malformed,
            ChangeTrustResultCode::NoIssuer => Self::NoIssuer,
            ChangeTrustResultCode::InvalidLimit => Self::InvalidLimit,
            ChangeTrustResultCode::LowReserve => Self::LowReserve,
            ChangeTrustResultCode::SelfNotAllowed => Self::SelfNotAllowed,
            ChangeTrustResultCode::TrustLineMissing => Self::TrustLineMissing,
            ChangeTrustResultCode::CannotDelete => Self::CannotDelete,
            ChangeTrustResultCode::NotAuthMaintainLiabilities => Self::NotAuthMaintainLiabilities,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ChangeTrustResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::NoIssuer => ().write_xdr(w)?,
            Self::InvalidLimit => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
            Self::SelfNotAllowed => ().write_xdr(w)?,
            Self::TrustLineMissing => ().write_xdr(w)?,
            Self::CannotDelete => ().write_xdr(w)?,
            Self::NotAuthMaintainLiabilities => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// AllowTrustResultCode is an XDR Enum defines as:
//
//   enum AllowTrustResultCode
//    {
//        // codes considered as "success" for the operation
//        ALLOW_TRUST_SUCCESS = 0,
//        // codes considered as "failure" for the operation
//        ALLOW_TRUST_MALFORMED = -1,     // asset is not ASSET_TYPE_ALPHANUM
//        ALLOW_TRUST_NO_TRUST_LINE = -2, // trustor does not have a trustline
//                                        // source account does not require trust
//        ALLOW_TRUST_TRUST_NOT_REQUIRED = -3,
//        ALLOW_TRUST_CANT_REVOKE = -4,      // source account can't revoke trust,
//        ALLOW_TRUST_SELF_NOT_ALLOWED = -5, // trusting self is not allowed
//        ALLOW_TRUST_LOW_RESERVE = -6       // claimable balances can't be created
//                                           // on revoke due to low reserves
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum AllowTrustResultCode {
    Success = 0,
    Malformed = -1,
    NoTrustLine = -2,
    TrustNotRequired = -3,
    CantRevoke = -4,
    SelfNotAllowed = -5,
    LowReserve = -6,
}

impl AllowTrustResultCode {
    pub const VARIANTS: [AllowTrustResultCode; 7] = [
        AllowTrustResultCode::Success,
        AllowTrustResultCode::Malformed,
        AllowTrustResultCode::NoTrustLine,
        AllowTrustResultCode::TrustNotRequired,
        AllowTrustResultCode::CantRevoke,
        AllowTrustResultCode::SelfNotAllowed,
        AllowTrustResultCode::LowReserve,
    ];
    pub const VARIANTS_STR: [&'static str; 7] = [
        "Success",
        "Malformed",
        "NoTrustLine",
        "TrustNotRequired",
        "CantRevoke",
        "SelfNotAllowed",
        "LowReserve",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoTrustLine => "NoTrustLine",
            Self::TrustNotRequired => "TrustNotRequired",
            Self::CantRevoke => "CantRevoke",
            Self::SelfNotAllowed => "SelfNotAllowed",
            Self::LowReserve => "LowReserve",
        }
    }

    #[must_use]
    pub const fn variants() -> [AllowTrustResultCode; 7] {
        Self::VARIANTS
    }
}

impl Name for AllowTrustResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<AllowTrustResultCode> for AllowTrustResultCode {
    fn variants() -> slice::Iter<'static, AllowTrustResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for AllowTrustResultCode {}

impl fmt::Display for AllowTrustResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for AllowTrustResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => AllowTrustResultCode::Success,
            -1 => AllowTrustResultCode::Malformed,
            -2 => AllowTrustResultCode::NoTrustLine,
            -3 => AllowTrustResultCode::TrustNotRequired,
            -4 => AllowTrustResultCode::CantRevoke,
            -5 => AllowTrustResultCode::SelfNotAllowed,
            -6 => AllowTrustResultCode::LowReserve,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<AllowTrustResultCode> for i32 {
    #[must_use]
    fn from(e: AllowTrustResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for AllowTrustResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for AllowTrustResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// AllowTrustResult is an XDR Union defines as:
//
//   union AllowTrustResult switch (AllowTrustResultCode code)
//    {
//    case ALLOW_TRUST_SUCCESS:
//        void;
//    case ALLOW_TRUST_MALFORMED:
//    case ALLOW_TRUST_NO_TRUST_LINE:
//    case ALLOW_TRUST_TRUST_NOT_REQUIRED:
//    case ALLOW_TRUST_CANT_REVOKE:
//    case ALLOW_TRUST_SELF_NOT_ALLOWED:
//    case ALLOW_TRUST_LOW_RESERVE:
//        void;
//    };
//
// union with discriminant AllowTrustResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum AllowTrustResult {
    Success,
    Malformed,
    NoTrustLine,
    TrustNotRequired,
    CantRevoke,
    SelfNotAllowed,
    LowReserve,
}

impl AllowTrustResult {
    pub const VARIANTS: [AllowTrustResultCode; 7] = [
        AllowTrustResultCode::Success,
        AllowTrustResultCode::Malformed,
        AllowTrustResultCode::NoTrustLine,
        AllowTrustResultCode::TrustNotRequired,
        AllowTrustResultCode::CantRevoke,
        AllowTrustResultCode::SelfNotAllowed,
        AllowTrustResultCode::LowReserve,
    ];
    pub const VARIANTS_STR: [&'static str; 7] = [
        "Success",
        "Malformed",
        "NoTrustLine",
        "TrustNotRequired",
        "CantRevoke",
        "SelfNotAllowed",
        "LowReserve",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoTrustLine => "NoTrustLine",
            Self::TrustNotRequired => "TrustNotRequired",
            Self::CantRevoke => "CantRevoke",
            Self::SelfNotAllowed => "SelfNotAllowed",
            Self::LowReserve => "LowReserve",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> AllowTrustResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => AllowTrustResultCode::Success,
            Self::Malformed => AllowTrustResultCode::Malformed,
            Self::NoTrustLine => AllowTrustResultCode::NoTrustLine,
            Self::TrustNotRequired => AllowTrustResultCode::TrustNotRequired,
            Self::CantRevoke => AllowTrustResultCode::CantRevoke,
            Self::SelfNotAllowed => AllowTrustResultCode::SelfNotAllowed,
            Self::LowReserve => AllowTrustResultCode::LowReserve,
        }
    }

    #[must_use]
    pub const fn variants() -> [AllowTrustResultCode; 7] {
        Self::VARIANTS
    }
}

impl Name for AllowTrustResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<AllowTrustResultCode> for AllowTrustResult {
    #[must_use]
    fn discriminant(&self) -> AllowTrustResultCode {
        Self::discriminant(self)
    }
}

impl Variants<AllowTrustResultCode> for AllowTrustResult {
    fn variants() -> slice::Iter<'static, AllowTrustResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<AllowTrustResultCode> for AllowTrustResult {}

impl ReadXdr for AllowTrustResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: AllowTrustResultCode = <AllowTrustResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            AllowTrustResultCode::Success => Self::Success,
            AllowTrustResultCode::Malformed => Self::Malformed,
            AllowTrustResultCode::NoTrustLine => Self::NoTrustLine,
            AllowTrustResultCode::TrustNotRequired => Self::TrustNotRequired,
            AllowTrustResultCode::CantRevoke => Self::CantRevoke,
            AllowTrustResultCode::SelfNotAllowed => Self::SelfNotAllowed,
            AllowTrustResultCode::LowReserve => Self::LowReserve,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for AllowTrustResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::NoTrustLine => ().write_xdr(w)?,
            Self::TrustNotRequired => ().write_xdr(w)?,
            Self::CantRevoke => ().write_xdr(w)?,
            Self::SelfNotAllowed => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// AccountMergeResultCode is an XDR Enum defines as:
//
//   enum AccountMergeResultCode
//    {
//        // codes considered as "success" for the operation
//        ACCOUNT_MERGE_SUCCESS = 0,
//        // codes considered as "failure" for the operation
//        ACCOUNT_MERGE_MALFORMED = -1,       // can't merge onto itself
//        ACCOUNT_MERGE_NO_ACCOUNT = -2,      // destination does not exist
//        ACCOUNT_MERGE_IMMUTABLE_SET = -3,   // source account has AUTH_IMMUTABLE set
//        ACCOUNT_MERGE_HAS_SUB_ENTRIES = -4, // account has trust lines/offers
//        ACCOUNT_MERGE_SEQNUM_TOO_FAR = -5,  // sequence number is over max allowed
//        ACCOUNT_MERGE_DEST_FULL = -6,       // can't add source balance to
//                                            // destination balance
//        ACCOUNT_MERGE_IS_SPONSOR = -7       // can't merge account that is a sponsor
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum AccountMergeResultCode {
    Success = 0,
    Malformed = -1,
    NoAccount = -2,
    ImmutableSet = -3,
    HasSubEntries = -4,
    SeqnumTooFar = -5,
    DestFull = -6,
    IsSponsor = -7,
}

impl AccountMergeResultCode {
    pub const VARIANTS: [AccountMergeResultCode; 8] = [
        AccountMergeResultCode::Success,
        AccountMergeResultCode::Malformed,
        AccountMergeResultCode::NoAccount,
        AccountMergeResultCode::ImmutableSet,
        AccountMergeResultCode::HasSubEntries,
        AccountMergeResultCode::SeqnumTooFar,
        AccountMergeResultCode::DestFull,
        AccountMergeResultCode::IsSponsor,
    ];
    pub const VARIANTS_STR: [&'static str; 8] = [
        "Success",
        "Malformed",
        "NoAccount",
        "ImmutableSet",
        "HasSubEntries",
        "SeqnumTooFar",
        "DestFull",
        "IsSponsor",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoAccount => "NoAccount",
            Self::ImmutableSet => "ImmutableSet",
            Self::HasSubEntries => "HasSubEntries",
            Self::SeqnumTooFar => "SeqnumTooFar",
            Self::DestFull => "DestFull",
            Self::IsSponsor => "IsSponsor",
        }
    }

    #[must_use]
    pub const fn variants() -> [AccountMergeResultCode; 8] {
        Self::VARIANTS
    }
}

impl Name for AccountMergeResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<AccountMergeResultCode> for AccountMergeResultCode {
    fn variants() -> slice::Iter<'static, AccountMergeResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for AccountMergeResultCode {}

impl fmt::Display for AccountMergeResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for AccountMergeResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => AccountMergeResultCode::Success,
            -1 => AccountMergeResultCode::Malformed,
            -2 => AccountMergeResultCode::NoAccount,
            -3 => AccountMergeResultCode::ImmutableSet,
            -4 => AccountMergeResultCode::HasSubEntries,
            -5 => AccountMergeResultCode::SeqnumTooFar,
            -6 => AccountMergeResultCode::DestFull,
            -7 => AccountMergeResultCode::IsSponsor,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<AccountMergeResultCode> for i32 {
    #[must_use]
    fn from(e: AccountMergeResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for AccountMergeResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for AccountMergeResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// AccountMergeResult is an XDR Union defines as:
//
//   union AccountMergeResult switch (AccountMergeResultCode code)
//    {
//    case ACCOUNT_MERGE_SUCCESS:
//        int64 sourceAccountBalance; // how much got transferred from source account
//    case ACCOUNT_MERGE_MALFORMED:
//    case ACCOUNT_MERGE_NO_ACCOUNT:
//    case ACCOUNT_MERGE_IMMUTABLE_SET:
//    case ACCOUNT_MERGE_HAS_SUB_ENTRIES:
//    case ACCOUNT_MERGE_SEQNUM_TOO_FAR:
//    case ACCOUNT_MERGE_DEST_FULL:
//    case ACCOUNT_MERGE_IS_SPONSOR:
//        void;
//    };
//
// union with discriminant AccountMergeResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum AccountMergeResult {
    Success(i64),
    Malformed,
    NoAccount,
    ImmutableSet,
    HasSubEntries,
    SeqnumTooFar,
    DestFull,
    IsSponsor,
}

impl AccountMergeResult {
    pub const VARIANTS: [AccountMergeResultCode; 8] = [
        AccountMergeResultCode::Success,
        AccountMergeResultCode::Malformed,
        AccountMergeResultCode::NoAccount,
        AccountMergeResultCode::ImmutableSet,
        AccountMergeResultCode::HasSubEntries,
        AccountMergeResultCode::SeqnumTooFar,
        AccountMergeResultCode::DestFull,
        AccountMergeResultCode::IsSponsor,
    ];
    pub const VARIANTS_STR: [&'static str; 8] = [
        "Success",
        "Malformed",
        "NoAccount",
        "ImmutableSet",
        "HasSubEntries",
        "SeqnumTooFar",
        "DestFull",
        "IsSponsor",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success(_) => "Success",
            Self::Malformed => "Malformed",
            Self::NoAccount => "NoAccount",
            Self::ImmutableSet => "ImmutableSet",
            Self::HasSubEntries => "HasSubEntries",
            Self::SeqnumTooFar => "SeqnumTooFar",
            Self::DestFull => "DestFull",
            Self::IsSponsor => "IsSponsor",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> AccountMergeResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(_) => AccountMergeResultCode::Success,
            Self::Malformed => AccountMergeResultCode::Malformed,
            Self::NoAccount => AccountMergeResultCode::NoAccount,
            Self::ImmutableSet => AccountMergeResultCode::ImmutableSet,
            Self::HasSubEntries => AccountMergeResultCode::HasSubEntries,
            Self::SeqnumTooFar => AccountMergeResultCode::SeqnumTooFar,
            Self::DestFull => AccountMergeResultCode::DestFull,
            Self::IsSponsor => AccountMergeResultCode::IsSponsor,
        }
    }

    #[must_use]
    pub const fn variants() -> [AccountMergeResultCode; 8] {
        Self::VARIANTS
    }
}

impl Name for AccountMergeResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<AccountMergeResultCode> for AccountMergeResult {
    #[must_use]
    fn discriminant(&self) -> AccountMergeResultCode {
        Self::discriminant(self)
    }
}

impl Variants<AccountMergeResultCode> for AccountMergeResult {
    fn variants() -> slice::Iter<'static, AccountMergeResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<AccountMergeResultCode> for AccountMergeResult {}

impl ReadXdr for AccountMergeResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: AccountMergeResultCode = <AccountMergeResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            AccountMergeResultCode::Success => Self::Success(i64::read_xdr(r)?),
            AccountMergeResultCode::Malformed => Self::Malformed,
            AccountMergeResultCode::NoAccount => Self::NoAccount,
            AccountMergeResultCode::ImmutableSet => Self::ImmutableSet,
            AccountMergeResultCode::HasSubEntries => Self::HasSubEntries,
            AccountMergeResultCode::SeqnumTooFar => Self::SeqnumTooFar,
            AccountMergeResultCode::DestFull => Self::DestFull,
            AccountMergeResultCode::IsSponsor => Self::IsSponsor,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for AccountMergeResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(v) => v.write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::NoAccount => ().write_xdr(w)?,
            Self::ImmutableSet => ().write_xdr(w)?,
            Self::HasSubEntries => ().write_xdr(w)?,
            Self::SeqnumTooFar => ().write_xdr(w)?,
            Self::DestFull => ().write_xdr(w)?,
            Self::IsSponsor => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// InflationResultCode is an XDR Enum defines as:
//
//   enum InflationResultCode
//    {
//        // codes considered as "success" for the operation
//        INFLATION_SUCCESS = 0,
//        // codes considered as "failure" for the operation
//        INFLATION_NOT_TIME = -1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum InflationResultCode {
    Success = 0,
    NotTime = -1,
}

impl InflationResultCode {
    pub const VARIANTS: [InflationResultCode; 2] =
        [InflationResultCode::Success, InflationResultCode::NotTime];
    pub const VARIANTS_STR: [&'static str; 2] = ["Success", "NotTime"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::NotTime => "NotTime",
        }
    }

    #[must_use]
    pub const fn variants() -> [InflationResultCode; 2] {
        Self::VARIANTS
    }
}

impl Name for InflationResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<InflationResultCode> for InflationResultCode {
    fn variants() -> slice::Iter<'static, InflationResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for InflationResultCode {}

impl fmt::Display for InflationResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for InflationResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => InflationResultCode::Success,
            -1 => InflationResultCode::NotTime,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<InflationResultCode> for i32 {
    #[must_use]
    fn from(e: InflationResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for InflationResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for InflationResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// InflationPayout is an XDR Struct defines as:
//
//   struct InflationPayout // or use PaymentResultAtom to limit types?
//    {
//        AccountID destination;
//        int64 amount;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct InflationPayout {
    pub destination: AccountId,
    pub amount: i64,
}

impl ReadXdr for InflationPayout {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            destination: AccountId::read_xdr(r)?,
            amount: i64::read_xdr(r)?,
        })
    }
}

impl WriteXdr for InflationPayout {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.destination.write_xdr(w)?;
        self.amount.write_xdr(w)?;
        Ok(())
    }
}

// InflationResult is an XDR Union defines as:
//
//   union InflationResult switch (InflationResultCode code)
//    {
//    case INFLATION_SUCCESS:
//        InflationPayout payouts<>;
//    case INFLATION_NOT_TIME:
//        void;
//    };
//
// union with discriminant InflationResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum InflationResult {
    Success(VecM<InflationPayout>),
    NotTime,
}

impl InflationResult {
    pub const VARIANTS: [InflationResultCode; 2] =
        [InflationResultCode::Success, InflationResultCode::NotTime];
    pub const VARIANTS_STR: [&'static str; 2] = ["Success", "NotTime"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success(_) => "Success",
            Self::NotTime => "NotTime",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> InflationResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(_) => InflationResultCode::Success,
            Self::NotTime => InflationResultCode::NotTime,
        }
    }

    #[must_use]
    pub const fn variants() -> [InflationResultCode; 2] {
        Self::VARIANTS
    }
}

impl Name for InflationResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<InflationResultCode> for InflationResult {
    #[must_use]
    fn discriminant(&self) -> InflationResultCode {
        Self::discriminant(self)
    }
}

impl Variants<InflationResultCode> for InflationResult {
    fn variants() -> slice::Iter<'static, InflationResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<InflationResultCode> for InflationResult {}

impl ReadXdr for InflationResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: InflationResultCode = <InflationResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            InflationResultCode::Success => Self::Success(VecM::<InflationPayout>::read_xdr(r)?),
            InflationResultCode::NotTime => Self::NotTime,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for InflationResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(v) => v.write_xdr(w)?,
            Self::NotTime => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ManageDataResultCode is an XDR Enum defines as:
//
//   enum ManageDataResultCode
//    {
//        // codes considered as "success" for the operation
//        MANAGE_DATA_SUCCESS = 0,
//        // codes considered as "failure" for the operation
//        MANAGE_DATA_NOT_SUPPORTED_YET =
//            -1, // The network hasn't moved to this protocol change yet
//        MANAGE_DATA_NAME_NOT_FOUND =
//            -2, // Trying to remove a Data Entry that isn't there
//        MANAGE_DATA_LOW_RESERVE = -3, // not enough funds to create a new Data Entry
//        MANAGE_DATA_INVALID_NAME = -4 // Name not a valid string
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ManageDataResultCode {
    Success = 0,
    NotSupportedYet = -1,
    NameNotFound = -2,
    LowReserve = -3,
    InvalidName = -4,
}

impl ManageDataResultCode {
    pub const VARIANTS: [ManageDataResultCode; 5] = [
        ManageDataResultCode::Success,
        ManageDataResultCode::NotSupportedYet,
        ManageDataResultCode::NameNotFound,
        ManageDataResultCode::LowReserve,
        ManageDataResultCode::InvalidName,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "Success",
        "NotSupportedYet",
        "NameNotFound",
        "LowReserve",
        "InvalidName",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::NotSupportedYet => "NotSupportedYet",
            Self::NameNotFound => "NameNotFound",
            Self::LowReserve => "LowReserve",
            Self::InvalidName => "InvalidName",
        }
    }

    #[must_use]
    pub const fn variants() -> [ManageDataResultCode; 5] {
        Self::VARIANTS
    }
}

impl Name for ManageDataResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ManageDataResultCode> for ManageDataResultCode {
    fn variants() -> slice::Iter<'static, ManageDataResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ManageDataResultCode {}

impl fmt::Display for ManageDataResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ManageDataResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ManageDataResultCode::Success,
            -1 => ManageDataResultCode::NotSupportedYet,
            -2 => ManageDataResultCode::NameNotFound,
            -3 => ManageDataResultCode::LowReserve,
            -4 => ManageDataResultCode::InvalidName,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ManageDataResultCode> for i32 {
    #[must_use]
    fn from(e: ManageDataResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ManageDataResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ManageDataResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ManageDataResult is an XDR Union defines as:
//
//   union ManageDataResult switch (ManageDataResultCode code)
//    {
//    case MANAGE_DATA_SUCCESS:
//        void;
//    case MANAGE_DATA_NOT_SUPPORTED_YET:
//    case MANAGE_DATA_NAME_NOT_FOUND:
//    case MANAGE_DATA_LOW_RESERVE:
//    case MANAGE_DATA_INVALID_NAME:
//        void;
//    };
//
// union with discriminant ManageDataResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ManageDataResult {
    Success,
    NotSupportedYet,
    NameNotFound,
    LowReserve,
    InvalidName,
}

impl ManageDataResult {
    pub const VARIANTS: [ManageDataResultCode; 5] = [
        ManageDataResultCode::Success,
        ManageDataResultCode::NotSupportedYet,
        ManageDataResultCode::NameNotFound,
        ManageDataResultCode::LowReserve,
        ManageDataResultCode::InvalidName,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "Success",
        "NotSupportedYet",
        "NameNotFound",
        "LowReserve",
        "InvalidName",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::NotSupportedYet => "NotSupportedYet",
            Self::NameNotFound => "NameNotFound",
            Self::LowReserve => "LowReserve",
            Self::InvalidName => "InvalidName",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ManageDataResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ManageDataResultCode::Success,
            Self::NotSupportedYet => ManageDataResultCode::NotSupportedYet,
            Self::NameNotFound => ManageDataResultCode::NameNotFound,
            Self::LowReserve => ManageDataResultCode::LowReserve,
            Self::InvalidName => ManageDataResultCode::InvalidName,
        }
    }

    #[must_use]
    pub const fn variants() -> [ManageDataResultCode; 5] {
        Self::VARIANTS
    }
}

impl Name for ManageDataResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ManageDataResultCode> for ManageDataResult {
    #[must_use]
    fn discriminant(&self) -> ManageDataResultCode {
        Self::discriminant(self)
    }
}

impl Variants<ManageDataResultCode> for ManageDataResult {
    fn variants() -> slice::Iter<'static, ManageDataResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<ManageDataResultCode> for ManageDataResult {}

impl ReadXdr for ManageDataResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ManageDataResultCode = <ManageDataResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ManageDataResultCode::Success => Self::Success,
            ManageDataResultCode::NotSupportedYet => Self::NotSupportedYet,
            ManageDataResultCode::NameNotFound => Self::NameNotFound,
            ManageDataResultCode::LowReserve => Self::LowReserve,
            ManageDataResultCode::InvalidName => Self::InvalidName,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ManageDataResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::NotSupportedYet => ().write_xdr(w)?,
            Self::NameNotFound => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
            Self::InvalidName => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// BumpSequenceResultCode is an XDR Enum defines as:
//
//   enum BumpSequenceResultCode
//    {
//        // codes considered as "success" for the operation
//        BUMP_SEQUENCE_SUCCESS = 0,
//        // codes considered as "failure" for the operation
//        BUMP_SEQUENCE_BAD_SEQ = -1 // `bumpTo` is not within bounds
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum BumpSequenceResultCode {
    Success = 0,
    BadSeq = -1,
}

impl BumpSequenceResultCode {
    pub const VARIANTS: [BumpSequenceResultCode; 2] = [
        BumpSequenceResultCode::Success,
        BumpSequenceResultCode::BadSeq,
    ];
    pub const VARIANTS_STR: [&'static str; 2] = ["Success", "BadSeq"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::BadSeq => "BadSeq",
        }
    }

    #[must_use]
    pub const fn variants() -> [BumpSequenceResultCode; 2] {
        Self::VARIANTS
    }
}

impl Name for BumpSequenceResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<BumpSequenceResultCode> for BumpSequenceResultCode {
    fn variants() -> slice::Iter<'static, BumpSequenceResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for BumpSequenceResultCode {}

impl fmt::Display for BumpSequenceResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for BumpSequenceResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => BumpSequenceResultCode::Success,
            -1 => BumpSequenceResultCode::BadSeq,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<BumpSequenceResultCode> for i32 {
    #[must_use]
    fn from(e: BumpSequenceResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for BumpSequenceResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for BumpSequenceResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// BumpSequenceResult is an XDR Union defines as:
//
//   union BumpSequenceResult switch (BumpSequenceResultCode code)
//    {
//    case BUMP_SEQUENCE_SUCCESS:
//        void;
//    case BUMP_SEQUENCE_BAD_SEQ:
//        void;
//    };
//
// union with discriminant BumpSequenceResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum BumpSequenceResult {
    Success,
    BadSeq,
}

impl BumpSequenceResult {
    pub const VARIANTS: [BumpSequenceResultCode; 2] = [
        BumpSequenceResultCode::Success,
        BumpSequenceResultCode::BadSeq,
    ];
    pub const VARIANTS_STR: [&'static str; 2] = ["Success", "BadSeq"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::BadSeq => "BadSeq",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> BumpSequenceResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => BumpSequenceResultCode::Success,
            Self::BadSeq => BumpSequenceResultCode::BadSeq,
        }
    }

    #[must_use]
    pub const fn variants() -> [BumpSequenceResultCode; 2] {
        Self::VARIANTS
    }
}

impl Name for BumpSequenceResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<BumpSequenceResultCode> for BumpSequenceResult {
    #[must_use]
    fn discriminant(&self) -> BumpSequenceResultCode {
        Self::discriminant(self)
    }
}

impl Variants<BumpSequenceResultCode> for BumpSequenceResult {
    fn variants() -> slice::Iter<'static, BumpSequenceResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<BumpSequenceResultCode> for BumpSequenceResult {}

impl ReadXdr for BumpSequenceResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: BumpSequenceResultCode = <BumpSequenceResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            BumpSequenceResultCode::Success => Self::Success,
            BumpSequenceResultCode::BadSeq => Self::BadSeq,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for BumpSequenceResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::BadSeq => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// CreateClaimableBalanceResultCode is an XDR Enum defines as:
//
//   enum CreateClaimableBalanceResultCode
//    {
//        CREATE_CLAIMABLE_BALANCE_SUCCESS = 0,
//        CREATE_CLAIMABLE_BALANCE_MALFORMED = -1,
//        CREATE_CLAIMABLE_BALANCE_LOW_RESERVE = -2,
//        CREATE_CLAIMABLE_BALANCE_NO_TRUST = -3,
//        CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED = -4,
//        CREATE_CLAIMABLE_BALANCE_UNDERFUNDED = -5
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum CreateClaimableBalanceResultCode {
    Success = 0,
    Malformed = -1,
    LowReserve = -2,
    NoTrust = -3,
    NotAuthorized = -4,
    Underfunded = -5,
}

impl CreateClaimableBalanceResultCode {
    pub const VARIANTS: [CreateClaimableBalanceResultCode; 6] = [
        CreateClaimableBalanceResultCode::Success,
        CreateClaimableBalanceResultCode::Malformed,
        CreateClaimableBalanceResultCode::LowReserve,
        CreateClaimableBalanceResultCode::NoTrust,
        CreateClaimableBalanceResultCode::NotAuthorized,
        CreateClaimableBalanceResultCode::Underfunded,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "Malformed",
        "LowReserve",
        "NoTrust",
        "NotAuthorized",
        "Underfunded",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::LowReserve => "LowReserve",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::Underfunded => "Underfunded",
        }
    }

    #[must_use]
    pub const fn variants() -> [CreateClaimableBalanceResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for CreateClaimableBalanceResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<CreateClaimableBalanceResultCode> for CreateClaimableBalanceResultCode {
    fn variants() -> slice::Iter<'static, CreateClaimableBalanceResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for CreateClaimableBalanceResultCode {}

impl fmt::Display for CreateClaimableBalanceResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for CreateClaimableBalanceResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => CreateClaimableBalanceResultCode::Success,
            -1 => CreateClaimableBalanceResultCode::Malformed,
            -2 => CreateClaimableBalanceResultCode::LowReserve,
            -3 => CreateClaimableBalanceResultCode::NoTrust,
            -4 => CreateClaimableBalanceResultCode::NotAuthorized,
            -5 => CreateClaimableBalanceResultCode::Underfunded,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<CreateClaimableBalanceResultCode> for i32 {
    #[must_use]
    fn from(e: CreateClaimableBalanceResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for CreateClaimableBalanceResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for CreateClaimableBalanceResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// CreateClaimableBalanceResult is an XDR Union defines as:
//
//   union CreateClaimableBalanceResult switch (
//        CreateClaimableBalanceResultCode code)
//    {
//    case CREATE_CLAIMABLE_BALANCE_SUCCESS:
//        ClaimableBalanceID balanceID;
//    case CREATE_CLAIMABLE_BALANCE_MALFORMED:
//    case CREATE_CLAIMABLE_BALANCE_LOW_RESERVE:
//    case CREATE_CLAIMABLE_BALANCE_NO_TRUST:
//    case CREATE_CLAIMABLE_BALANCE_NOT_AUTHORIZED:
//    case CREATE_CLAIMABLE_BALANCE_UNDERFUNDED:
//        void;
//    };
//
// union with discriminant CreateClaimableBalanceResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum CreateClaimableBalanceResult {
    Success(ClaimableBalanceId),
    Malformed,
    LowReserve,
    NoTrust,
    NotAuthorized,
    Underfunded,
}

impl CreateClaimableBalanceResult {
    pub const VARIANTS: [CreateClaimableBalanceResultCode; 6] = [
        CreateClaimableBalanceResultCode::Success,
        CreateClaimableBalanceResultCode::Malformed,
        CreateClaimableBalanceResultCode::LowReserve,
        CreateClaimableBalanceResultCode::NoTrust,
        CreateClaimableBalanceResultCode::NotAuthorized,
        CreateClaimableBalanceResultCode::Underfunded,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "Malformed",
        "LowReserve",
        "NoTrust",
        "NotAuthorized",
        "Underfunded",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success(_) => "Success",
            Self::Malformed => "Malformed",
            Self::LowReserve => "LowReserve",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::Underfunded => "Underfunded",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> CreateClaimableBalanceResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(_) => CreateClaimableBalanceResultCode::Success,
            Self::Malformed => CreateClaimableBalanceResultCode::Malformed,
            Self::LowReserve => CreateClaimableBalanceResultCode::LowReserve,
            Self::NoTrust => CreateClaimableBalanceResultCode::NoTrust,
            Self::NotAuthorized => CreateClaimableBalanceResultCode::NotAuthorized,
            Self::Underfunded => CreateClaimableBalanceResultCode::Underfunded,
        }
    }

    #[must_use]
    pub const fn variants() -> [CreateClaimableBalanceResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for CreateClaimableBalanceResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<CreateClaimableBalanceResultCode> for CreateClaimableBalanceResult {
    #[must_use]
    fn discriminant(&self) -> CreateClaimableBalanceResultCode {
        Self::discriminant(self)
    }
}

impl Variants<CreateClaimableBalanceResultCode> for CreateClaimableBalanceResult {
    fn variants() -> slice::Iter<'static, CreateClaimableBalanceResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<CreateClaimableBalanceResultCode> for CreateClaimableBalanceResult {}

impl ReadXdr for CreateClaimableBalanceResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: CreateClaimableBalanceResultCode =
            <CreateClaimableBalanceResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            CreateClaimableBalanceResultCode::Success => {
                Self::Success(ClaimableBalanceId::read_xdr(r)?)
            }
            CreateClaimableBalanceResultCode::Malformed => Self::Malformed,
            CreateClaimableBalanceResultCode::LowReserve => Self::LowReserve,
            CreateClaimableBalanceResultCode::NoTrust => Self::NoTrust,
            CreateClaimableBalanceResultCode::NotAuthorized => Self::NotAuthorized,
            CreateClaimableBalanceResultCode::Underfunded => Self::Underfunded,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for CreateClaimableBalanceResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(v) => v.write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
            Self::NoTrust => ().write_xdr(w)?,
            Self::NotAuthorized => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ClaimClaimableBalanceResultCode is an XDR Enum defines as:
//
//   enum ClaimClaimableBalanceResultCode
//    {
//        CLAIM_CLAIMABLE_BALANCE_SUCCESS = 0,
//        CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST = -1,
//        CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM = -2,
//        CLAIM_CLAIMABLE_BALANCE_LINE_FULL = -3,
//        CLAIM_CLAIMABLE_BALANCE_NO_TRUST = -4,
//        CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED = -5
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ClaimClaimableBalanceResultCode {
    Success = 0,
    DoesNotExist = -1,
    CannotClaim = -2,
    LineFull = -3,
    NoTrust = -4,
    NotAuthorized = -5,
}

impl ClaimClaimableBalanceResultCode {
    pub const VARIANTS: [ClaimClaimableBalanceResultCode; 6] = [
        ClaimClaimableBalanceResultCode::Success,
        ClaimClaimableBalanceResultCode::DoesNotExist,
        ClaimClaimableBalanceResultCode::CannotClaim,
        ClaimClaimableBalanceResultCode::LineFull,
        ClaimClaimableBalanceResultCode::NoTrust,
        ClaimClaimableBalanceResultCode::NotAuthorized,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "DoesNotExist",
        "CannotClaim",
        "LineFull",
        "NoTrust",
        "NotAuthorized",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::DoesNotExist => "DoesNotExist",
            Self::CannotClaim => "CannotClaim",
            Self::LineFull => "LineFull",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimClaimableBalanceResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for ClaimClaimableBalanceResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ClaimClaimableBalanceResultCode> for ClaimClaimableBalanceResultCode {
    fn variants() -> slice::Iter<'static, ClaimClaimableBalanceResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ClaimClaimableBalanceResultCode {}

impl fmt::Display for ClaimClaimableBalanceResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ClaimClaimableBalanceResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ClaimClaimableBalanceResultCode::Success,
            -1 => ClaimClaimableBalanceResultCode::DoesNotExist,
            -2 => ClaimClaimableBalanceResultCode::CannotClaim,
            -3 => ClaimClaimableBalanceResultCode::LineFull,
            -4 => ClaimClaimableBalanceResultCode::NoTrust,
            -5 => ClaimClaimableBalanceResultCode::NotAuthorized,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ClaimClaimableBalanceResultCode> for i32 {
    #[must_use]
    fn from(e: ClaimClaimableBalanceResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ClaimClaimableBalanceResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ClaimClaimableBalanceResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ClaimClaimableBalanceResult is an XDR Union defines as:
//
//   union ClaimClaimableBalanceResult switch (ClaimClaimableBalanceResultCode code)
//    {
//    case CLAIM_CLAIMABLE_BALANCE_SUCCESS:
//        void;
//    case CLAIM_CLAIMABLE_BALANCE_DOES_NOT_EXIST:
//    case CLAIM_CLAIMABLE_BALANCE_CANNOT_CLAIM:
//    case CLAIM_CLAIMABLE_BALANCE_LINE_FULL:
//    case CLAIM_CLAIMABLE_BALANCE_NO_TRUST:
//    case CLAIM_CLAIMABLE_BALANCE_NOT_AUTHORIZED:
//        void;
//    };
//
// union with discriminant ClaimClaimableBalanceResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ClaimClaimableBalanceResult {
    Success,
    DoesNotExist,
    CannotClaim,
    LineFull,
    NoTrust,
    NotAuthorized,
}

impl ClaimClaimableBalanceResult {
    pub const VARIANTS: [ClaimClaimableBalanceResultCode; 6] = [
        ClaimClaimableBalanceResultCode::Success,
        ClaimClaimableBalanceResultCode::DoesNotExist,
        ClaimClaimableBalanceResultCode::CannotClaim,
        ClaimClaimableBalanceResultCode::LineFull,
        ClaimClaimableBalanceResultCode::NoTrust,
        ClaimClaimableBalanceResultCode::NotAuthorized,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "DoesNotExist",
        "CannotClaim",
        "LineFull",
        "NoTrust",
        "NotAuthorized",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::DoesNotExist => "DoesNotExist",
            Self::CannotClaim => "CannotClaim",
            Self::LineFull => "LineFull",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ClaimClaimableBalanceResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ClaimClaimableBalanceResultCode::Success,
            Self::DoesNotExist => ClaimClaimableBalanceResultCode::DoesNotExist,
            Self::CannotClaim => ClaimClaimableBalanceResultCode::CannotClaim,
            Self::LineFull => ClaimClaimableBalanceResultCode::LineFull,
            Self::NoTrust => ClaimClaimableBalanceResultCode::NoTrust,
            Self::NotAuthorized => ClaimClaimableBalanceResultCode::NotAuthorized,
        }
    }

    #[must_use]
    pub const fn variants() -> [ClaimClaimableBalanceResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for ClaimClaimableBalanceResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ClaimClaimableBalanceResultCode> for ClaimClaimableBalanceResult {
    #[must_use]
    fn discriminant(&self) -> ClaimClaimableBalanceResultCode {
        Self::discriminant(self)
    }
}

impl Variants<ClaimClaimableBalanceResultCode> for ClaimClaimableBalanceResult {
    fn variants() -> slice::Iter<'static, ClaimClaimableBalanceResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<ClaimClaimableBalanceResultCode> for ClaimClaimableBalanceResult {}

impl ReadXdr for ClaimClaimableBalanceResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ClaimClaimableBalanceResultCode =
            <ClaimClaimableBalanceResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ClaimClaimableBalanceResultCode::Success => Self::Success,
            ClaimClaimableBalanceResultCode::DoesNotExist => Self::DoesNotExist,
            ClaimClaimableBalanceResultCode::CannotClaim => Self::CannotClaim,
            ClaimClaimableBalanceResultCode::LineFull => Self::LineFull,
            ClaimClaimableBalanceResultCode::NoTrust => Self::NoTrust,
            ClaimClaimableBalanceResultCode::NotAuthorized => Self::NotAuthorized,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ClaimClaimableBalanceResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::DoesNotExist => ().write_xdr(w)?,
            Self::CannotClaim => ().write_xdr(w)?,
            Self::LineFull => ().write_xdr(w)?,
            Self::NoTrust => ().write_xdr(w)?,
            Self::NotAuthorized => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// BeginSponsoringFutureReservesResultCode is an XDR Enum defines as:
//
//   enum BeginSponsoringFutureReservesResultCode
//    {
//        // codes considered as "success" for the operation
//        BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED = -1,
//        BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED = -2,
//        BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE = -3
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum BeginSponsoringFutureReservesResultCode {
    Success = 0,
    Malformed = -1,
    AlreadySponsored = -2,
    Recursive = -3,
}

impl BeginSponsoringFutureReservesResultCode {
    pub const VARIANTS: [BeginSponsoringFutureReservesResultCode; 4] = [
        BeginSponsoringFutureReservesResultCode::Success,
        BeginSponsoringFutureReservesResultCode::Malformed,
        BeginSponsoringFutureReservesResultCode::AlreadySponsored,
        BeginSponsoringFutureReservesResultCode::Recursive,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Success", "Malformed", "AlreadySponsored", "Recursive"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::AlreadySponsored => "AlreadySponsored",
            Self::Recursive => "Recursive",
        }
    }

    #[must_use]
    pub const fn variants() -> [BeginSponsoringFutureReservesResultCode; 4] {
        Self::VARIANTS
    }
}

impl Name for BeginSponsoringFutureReservesResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<BeginSponsoringFutureReservesResultCode> for BeginSponsoringFutureReservesResultCode {
    fn variants() -> slice::Iter<'static, BeginSponsoringFutureReservesResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for BeginSponsoringFutureReservesResultCode {}

impl fmt::Display for BeginSponsoringFutureReservesResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for BeginSponsoringFutureReservesResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => BeginSponsoringFutureReservesResultCode::Success,
            -1 => BeginSponsoringFutureReservesResultCode::Malformed,
            -2 => BeginSponsoringFutureReservesResultCode::AlreadySponsored,
            -3 => BeginSponsoringFutureReservesResultCode::Recursive,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<BeginSponsoringFutureReservesResultCode> for i32 {
    #[must_use]
    fn from(e: BeginSponsoringFutureReservesResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for BeginSponsoringFutureReservesResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for BeginSponsoringFutureReservesResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// BeginSponsoringFutureReservesResult is an XDR Union defines as:
//
//   union BeginSponsoringFutureReservesResult switch (
//        BeginSponsoringFutureReservesResultCode code)
//    {
//    case BEGIN_SPONSORING_FUTURE_RESERVES_SUCCESS:
//        void;
//    case BEGIN_SPONSORING_FUTURE_RESERVES_MALFORMED:
//    case BEGIN_SPONSORING_FUTURE_RESERVES_ALREADY_SPONSORED:
//    case BEGIN_SPONSORING_FUTURE_RESERVES_RECURSIVE:
//        void;
//    };
//
// union with discriminant BeginSponsoringFutureReservesResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum BeginSponsoringFutureReservesResult {
    Success,
    Malformed,
    AlreadySponsored,
    Recursive,
}

impl BeginSponsoringFutureReservesResult {
    pub const VARIANTS: [BeginSponsoringFutureReservesResultCode; 4] = [
        BeginSponsoringFutureReservesResultCode::Success,
        BeginSponsoringFutureReservesResultCode::Malformed,
        BeginSponsoringFutureReservesResultCode::AlreadySponsored,
        BeginSponsoringFutureReservesResultCode::Recursive,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Success", "Malformed", "AlreadySponsored", "Recursive"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::AlreadySponsored => "AlreadySponsored",
            Self::Recursive => "Recursive",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> BeginSponsoringFutureReservesResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => BeginSponsoringFutureReservesResultCode::Success,
            Self::Malformed => BeginSponsoringFutureReservesResultCode::Malformed,
            Self::AlreadySponsored => BeginSponsoringFutureReservesResultCode::AlreadySponsored,
            Self::Recursive => BeginSponsoringFutureReservesResultCode::Recursive,
        }
    }

    #[must_use]
    pub const fn variants() -> [BeginSponsoringFutureReservesResultCode; 4] {
        Self::VARIANTS
    }
}

impl Name for BeginSponsoringFutureReservesResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<BeginSponsoringFutureReservesResultCode> for BeginSponsoringFutureReservesResult {
    #[must_use]
    fn discriminant(&self) -> BeginSponsoringFutureReservesResultCode {
        Self::discriminant(self)
    }
}

impl Variants<BeginSponsoringFutureReservesResultCode> for BeginSponsoringFutureReservesResult {
    fn variants() -> slice::Iter<'static, BeginSponsoringFutureReservesResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<BeginSponsoringFutureReservesResultCode> for BeginSponsoringFutureReservesResult {}

impl ReadXdr for BeginSponsoringFutureReservesResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: BeginSponsoringFutureReservesResultCode =
            <BeginSponsoringFutureReservesResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            BeginSponsoringFutureReservesResultCode::Success => Self::Success,
            BeginSponsoringFutureReservesResultCode::Malformed => Self::Malformed,
            BeginSponsoringFutureReservesResultCode::AlreadySponsored => Self::AlreadySponsored,
            BeginSponsoringFutureReservesResultCode::Recursive => Self::Recursive,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for BeginSponsoringFutureReservesResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::AlreadySponsored => ().write_xdr(w)?,
            Self::Recursive => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// EndSponsoringFutureReservesResultCode is an XDR Enum defines as:
//
//   enum EndSponsoringFutureReservesResultCode
//    {
//        // codes considered as "success" for the operation
//        END_SPONSORING_FUTURE_RESERVES_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED = -1
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum EndSponsoringFutureReservesResultCode {
    Success = 0,
    NotSponsored = -1,
}

impl EndSponsoringFutureReservesResultCode {
    pub const VARIANTS: [EndSponsoringFutureReservesResultCode; 2] = [
        EndSponsoringFutureReservesResultCode::Success,
        EndSponsoringFutureReservesResultCode::NotSponsored,
    ];
    pub const VARIANTS_STR: [&'static str; 2] = ["Success", "NotSponsored"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::NotSponsored => "NotSponsored",
        }
    }

    #[must_use]
    pub const fn variants() -> [EndSponsoringFutureReservesResultCode; 2] {
        Self::VARIANTS
    }
}

impl Name for EndSponsoringFutureReservesResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<EndSponsoringFutureReservesResultCode> for EndSponsoringFutureReservesResultCode {
    fn variants() -> slice::Iter<'static, EndSponsoringFutureReservesResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for EndSponsoringFutureReservesResultCode {}

impl fmt::Display for EndSponsoringFutureReservesResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for EndSponsoringFutureReservesResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => EndSponsoringFutureReservesResultCode::Success,
            -1 => EndSponsoringFutureReservesResultCode::NotSponsored,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<EndSponsoringFutureReservesResultCode> for i32 {
    #[must_use]
    fn from(e: EndSponsoringFutureReservesResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for EndSponsoringFutureReservesResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for EndSponsoringFutureReservesResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// EndSponsoringFutureReservesResult is an XDR Union defines as:
//
//   union EndSponsoringFutureReservesResult switch (
//        EndSponsoringFutureReservesResultCode code)
//    {
//    case END_SPONSORING_FUTURE_RESERVES_SUCCESS:
//        void;
//    case END_SPONSORING_FUTURE_RESERVES_NOT_SPONSORED:
//        void;
//    };
//
// union with discriminant EndSponsoringFutureReservesResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum EndSponsoringFutureReservesResult {
    Success,
    NotSponsored,
}

impl EndSponsoringFutureReservesResult {
    pub const VARIANTS: [EndSponsoringFutureReservesResultCode; 2] = [
        EndSponsoringFutureReservesResultCode::Success,
        EndSponsoringFutureReservesResultCode::NotSponsored,
    ];
    pub const VARIANTS_STR: [&'static str; 2] = ["Success", "NotSponsored"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::NotSponsored => "NotSponsored",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> EndSponsoringFutureReservesResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => EndSponsoringFutureReservesResultCode::Success,
            Self::NotSponsored => EndSponsoringFutureReservesResultCode::NotSponsored,
        }
    }

    #[must_use]
    pub const fn variants() -> [EndSponsoringFutureReservesResultCode; 2] {
        Self::VARIANTS
    }
}

impl Name for EndSponsoringFutureReservesResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<EndSponsoringFutureReservesResultCode> for EndSponsoringFutureReservesResult {
    #[must_use]
    fn discriminant(&self) -> EndSponsoringFutureReservesResultCode {
        Self::discriminant(self)
    }
}

impl Variants<EndSponsoringFutureReservesResultCode> for EndSponsoringFutureReservesResult {
    fn variants() -> slice::Iter<'static, EndSponsoringFutureReservesResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<EndSponsoringFutureReservesResultCode> for EndSponsoringFutureReservesResult {}

impl ReadXdr for EndSponsoringFutureReservesResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: EndSponsoringFutureReservesResultCode =
            <EndSponsoringFutureReservesResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            EndSponsoringFutureReservesResultCode::Success => Self::Success,
            EndSponsoringFutureReservesResultCode::NotSponsored => Self::NotSponsored,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for EndSponsoringFutureReservesResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::NotSponsored => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// RevokeSponsorshipResultCode is an XDR Enum defines as:
//
//   enum RevokeSponsorshipResultCode
//    {
//        // codes considered as "success" for the operation
//        REVOKE_SPONSORSHIP_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        REVOKE_SPONSORSHIP_DOES_NOT_EXIST = -1,
//        REVOKE_SPONSORSHIP_NOT_SPONSOR = -2,
//        REVOKE_SPONSORSHIP_LOW_RESERVE = -3,
//        REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE = -4,
//        REVOKE_SPONSORSHIP_MALFORMED = -5
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum RevokeSponsorshipResultCode {
    Success = 0,
    DoesNotExist = -1,
    NotSponsor = -2,
    LowReserve = -3,
    OnlyTransferable = -4,
    Malformed = -5,
}

impl RevokeSponsorshipResultCode {
    pub const VARIANTS: [RevokeSponsorshipResultCode; 6] = [
        RevokeSponsorshipResultCode::Success,
        RevokeSponsorshipResultCode::DoesNotExist,
        RevokeSponsorshipResultCode::NotSponsor,
        RevokeSponsorshipResultCode::LowReserve,
        RevokeSponsorshipResultCode::OnlyTransferable,
        RevokeSponsorshipResultCode::Malformed,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "DoesNotExist",
        "NotSponsor",
        "LowReserve",
        "OnlyTransferable",
        "Malformed",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::DoesNotExist => "DoesNotExist",
            Self::NotSponsor => "NotSponsor",
            Self::LowReserve => "LowReserve",
            Self::OnlyTransferable => "OnlyTransferable",
            Self::Malformed => "Malformed",
        }
    }

    #[must_use]
    pub const fn variants() -> [RevokeSponsorshipResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for RevokeSponsorshipResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<RevokeSponsorshipResultCode> for RevokeSponsorshipResultCode {
    fn variants() -> slice::Iter<'static, RevokeSponsorshipResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for RevokeSponsorshipResultCode {}

impl fmt::Display for RevokeSponsorshipResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for RevokeSponsorshipResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => RevokeSponsorshipResultCode::Success,
            -1 => RevokeSponsorshipResultCode::DoesNotExist,
            -2 => RevokeSponsorshipResultCode::NotSponsor,
            -3 => RevokeSponsorshipResultCode::LowReserve,
            -4 => RevokeSponsorshipResultCode::OnlyTransferable,
            -5 => RevokeSponsorshipResultCode::Malformed,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<RevokeSponsorshipResultCode> for i32 {
    #[must_use]
    fn from(e: RevokeSponsorshipResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for RevokeSponsorshipResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for RevokeSponsorshipResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// RevokeSponsorshipResult is an XDR Union defines as:
//
//   union RevokeSponsorshipResult switch (RevokeSponsorshipResultCode code)
//    {
//    case REVOKE_SPONSORSHIP_SUCCESS:
//        void;
//    case REVOKE_SPONSORSHIP_DOES_NOT_EXIST:
//    case REVOKE_SPONSORSHIP_NOT_SPONSOR:
//    case REVOKE_SPONSORSHIP_LOW_RESERVE:
//    case REVOKE_SPONSORSHIP_ONLY_TRANSFERABLE:
//    case REVOKE_SPONSORSHIP_MALFORMED:
//        void;
//    };
//
// union with discriminant RevokeSponsorshipResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum RevokeSponsorshipResult {
    Success,
    DoesNotExist,
    NotSponsor,
    LowReserve,
    OnlyTransferable,
    Malformed,
}

impl RevokeSponsorshipResult {
    pub const VARIANTS: [RevokeSponsorshipResultCode; 6] = [
        RevokeSponsorshipResultCode::Success,
        RevokeSponsorshipResultCode::DoesNotExist,
        RevokeSponsorshipResultCode::NotSponsor,
        RevokeSponsorshipResultCode::LowReserve,
        RevokeSponsorshipResultCode::OnlyTransferable,
        RevokeSponsorshipResultCode::Malformed,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "DoesNotExist",
        "NotSponsor",
        "LowReserve",
        "OnlyTransferable",
        "Malformed",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::DoesNotExist => "DoesNotExist",
            Self::NotSponsor => "NotSponsor",
            Self::LowReserve => "LowReserve",
            Self::OnlyTransferable => "OnlyTransferable",
            Self::Malformed => "Malformed",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> RevokeSponsorshipResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => RevokeSponsorshipResultCode::Success,
            Self::DoesNotExist => RevokeSponsorshipResultCode::DoesNotExist,
            Self::NotSponsor => RevokeSponsorshipResultCode::NotSponsor,
            Self::LowReserve => RevokeSponsorshipResultCode::LowReserve,
            Self::OnlyTransferable => RevokeSponsorshipResultCode::OnlyTransferable,
            Self::Malformed => RevokeSponsorshipResultCode::Malformed,
        }
    }

    #[must_use]
    pub const fn variants() -> [RevokeSponsorshipResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for RevokeSponsorshipResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<RevokeSponsorshipResultCode> for RevokeSponsorshipResult {
    #[must_use]
    fn discriminant(&self) -> RevokeSponsorshipResultCode {
        Self::discriminant(self)
    }
}

impl Variants<RevokeSponsorshipResultCode> for RevokeSponsorshipResult {
    fn variants() -> slice::Iter<'static, RevokeSponsorshipResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<RevokeSponsorshipResultCode> for RevokeSponsorshipResult {}

impl ReadXdr for RevokeSponsorshipResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: RevokeSponsorshipResultCode =
            <RevokeSponsorshipResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            RevokeSponsorshipResultCode::Success => Self::Success,
            RevokeSponsorshipResultCode::DoesNotExist => Self::DoesNotExist,
            RevokeSponsorshipResultCode::NotSponsor => Self::NotSponsor,
            RevokeSponsorshipResultCode::LowReserve => Self::LowReserve,
            RevokeSponsorshipResultCode::OnlyTransferable => Self::OnlyTransferable,
            RevokeSponsorshipResultCode::Malformed => Self::Malformed,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for RevokeSponsorshipResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::DoesNotExist => ().write_xdr(w)?,
            Self::NotSponsor => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
            Self::OnlyTransferable => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ClawbackResultCode is an XDR Enum defines as:
//
//   enum ClawbackResultCode
//    {
//        // codes considered as "success" for the operation
//        CLAWBACK_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        CLAWBACK_MALFORMED = -1,
//        CLAWBACK_NOT_CLAWBACK_ENABLED = -2,
//        CLAWBACK_NO_TRUST = -3,
//        CLAWBACK_UNDERFUNDED = -4
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ClawbackResultCode {
    Success = 0,
    Malformed = -1,
    NotClawbackEnabled = -2,
    NoTrust = -3,
    Underfunded = -4,
}

impl ClawbackResultCode {
    pub const VARIANTS: [ClawbackResultCode; 5] = [
        ClawbackResultCode::Success,
        ClawbackResultCode::Malformed,
        ClawbackResultCode::NotClawbackEnabled,
        ClawbackResultCode::NoTrust,
        ClawbackResultCode::Underfunded,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "Success",
        "Malformed",
        "NotClawbackEnabled",
        "NoTrust",
        "Underfunded",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NotClawbackEnabled => "NotClawbackEnabled",
            Self::NoTrust => "NoTrust",
            Self::Underfunded => "Underfunded",
        }
    }

    #[must_use]
    pub const fn variants() -> [ClawbackResultCode; 5] {
        Self::VARIANTS
    }
}

impl Name for ClawbackResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ClawbackResultCode> for ClawbackResultCode {
    fn variants() -> slice::Iter<'static, ClawbackResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ClawbackResultCode {}

impl fmt::Display for ClawbackResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ClawbackResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ClawbackResultCode::Success,
            -1 => ClawbackResultCode::Malformed,
            -2 => ClawbackResultCode::NotClawbackEnabled,
            -3 => ClawbackResultCode::NoTrust,
            -4 => ClawbackResultCode::Underfunded,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ClawbackResultCode> for i32 {
    #[must_use]
    fn from(e: ClawbackResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ClawbackResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ClawbackResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ClawbackResult is an XDR Union defines as:
//
//   union ClawbackResult switch (ClawbackResultCode code)
//    {
//    case CLAWBACK_SUCCESS:
//        void;
//    case CLAWBACK_MALFORMED:
//    case CLAWBACK_NOT_CLAWBACK_ENABLED:
//    case CLAWBACK_NO_TRUST:
//    case CLAWBACK_UNDERFUNDED:
//        void;
//    };
//
// union with discriminant ClawbackResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ClawbackResult {
    Success,
    Malformed,
    NotClawbackEnabled,
    NoTrust,
    Underfunded,
}

impl ClawbackResult {
    pub const VARIANTS: [ClawbackResultCode; 5] = [
        ClawbackResultCode::Success,
        ClawbackResultCode::Malformed,
        ClawbackResultCode::NotClawbackEnabled,
        ClawbackResultCode::NoTrust,
        ClawbackResultCode::Underfunded,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "Success",
        "Malformed",
        "NotClawbackEnabled",
        "NoTrust",
        "Underfunded",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NotClawbackEnabled => "NotClawbackEnabled",
            Self::NoTrust => "NoTrust",
            Self::Underfunded => "Underfunded",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ClawbackResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ClawbackResultCode::Success,
            Self::Malformed => ClawbackResultCode::Malformed,
            Self::NotClawbackEnabled => ClawbackResultCode::NotClawbackEnabled,
            Self::NoTrust => ClawbackResultCode::NoTrust,
            Self::Underfunded => ClawbackResultCode::Underfunded,
        }
    }

    #[must_use]
    pub const fn variants() -> [ClawbackResultCode; 5] {
        Self::VARIANTS
    }
}

impl Name for ClawbackResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ClawbackResultCode> for ClawbackResult {
    #[must_use]
    fn discriminant(&self) -> ClawbackResultCode {
        Self::discriminant(self)
    }
}

impl Variants<ClawbackResultCode> for ClawbackResult {
    fn variants() -> slice::Iter<'static, ClawbackResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<ClawbackResultCode> for ClawbackResult {}

impl ReadXdr for ClawbackResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ClawbackResultCode = <ClawbackResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ClawbackResultCode::Success => Self::Success,
            ClawbackResultCode::Malformed => Self::Malformed,
            ClawbackResultCode::NotClawbackEnabled => Self::NotClawbackEnabled,
            ClawbackResultCode::NoTrust => Self::NoTrust,
            ClawbackResultCode::Underfunded => Self::Underfunded,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ClawbackResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::NotClawbackEnabled => ().write_xdr(w)?,
            Self::NoTrust => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// ClawbackClaimableBalanceResultCode is an XDR Enum defines as:
//
//   enum ClawbackClaimableBalanceResultCode
//    {
//        // codes considered as "success" for the operation
//        CLAWBACK_CLAIMABLE_BALANCE_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST = -1,
//        CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER = -2,
//        CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED = -3
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum ClawbackClaimableBalanceResultCode {
    Success = 0,
    DoesNotExist = -1,
    NotIssuer = -2,
    NotClawbackEnabled = -3,
}

impl ClawbackClaimableBalanceResultCode {
    pub const VARIANTS: [ClawbackClaimableBalanceResultCode; 4] = [
        ClawbackClaimableBalanceResultCode::Success,
        ClawbackClaimableBalanceResultCode::DoesNotExist,
        ClawbackClaimableBalanceResultCode::NotIssuer,
        ClawbackClaimableBalanceResultCode::NotClawbackEnabled,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Success", "DoesNotExist", "NotIssuer", "NotClawbackEnabled"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::DoesNotExist => "DoesNotExist",
            Self::NotIssuer => "NotIssuer",
            Self::NotClawbackEnabled => "NotClawbackEnabled",
        }
    }

    #[must_use]
    pub const fn variants() -> [ClawbackClaimableBalanceResultCode; 4] {
        Self::VARIANTS
    }
}

impl Name for ClawbackClaimableBalanceResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<ClawbackClaimableBalanceResultCode> for ClawbackClaimableBalanceResultCode {
    fn variants() -> slice::Iter<'static, ClawbackClaimableBalanceResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for ClawbackClaimableBalanceResultCode {}

impl fmt::Display for ClawbackClaimableBalanceResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for ClawbackClaimableBalanceResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => ClawbackClaimableBalanceResultCode::Success,
            -1 => ClawbackClaimableBalanceResultCode::DoesNotExist,
            -2 => ClawbackClaimableBalanceResultCode::NotIssuer,
            -3 => ClawbackClaimableBalanceResultCode::NotClawbackEnabled,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<ClawbackClaimableBalanceResultCode> for i32 {
    #[must_use]
    fn from(e: ClawbackClaimableBalanceResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for ClawbackClaimableBalanceResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for ClawbackClaimableBalanceResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// ClawbackClaimableBalanceResult is an XDR Union defines as:
//
//   union ClawbackClaimableBalanceResult switch (
//        ClawbackClaimableBalanceResultCode code)
//    {
//    case CLAWBACK_CLAIMABLE_BALANCE_SUCCESS:
//        void;
//    case CLAWBACK_CLAIMABLE_BALANCE_DOES_NOT_EXIST:
//    case CLAWBACK_CLAIMABLE_BALANCE_NOT_ISSUER:
//    case CLAWBACK_CLAIMABLE_BALANCE_NOT_CLAWBACK_ENABLED:
//        void;
//    };
//
// union with discriminant ClawbackClaimableBalanceResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ClawbackClaimableBalanceResult {
    Success,
    DoesNotExist,
    NotIssuer,
    NotClawbackEnabled,
}

impl ClawbackClaimableBalanceResult {
    pub const VARIANTS: [ClawbackClaimableBalanceResultCode; 4] = [
        ClawbackClaimableBalanceResultCode::Success,
        ClawbackClaimableBalanceResultCode::DoesNotExist,
        ClawbackClaimableBalanceResultCode::NotIssuer,
        ClawbackClaimableBalanceResultCode::NotClawbackEnabled,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Success", "DoesNotExist", "NotIssuer", "NotClawbackEnabled"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::DoesNotExist => "DoesNotExist",
            Self::NotIssuer => "NotIssuer",
            Self::NotClawbackEnabled => "NotClawbackEnabled",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> ClawbackClaimableBalanceResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ClawbackClaimableBalanceResultCode::Success,
            Self::DoesNotExist => ClawbackClaimableBalanceResultCode::DoesNotExist,
            Self::NotIssuer => ClawbackClaimableBalanceResultCode::NotIssuer,
            Self::NotClawbackEnabled => ClawbackClaimableBalanceResultCode::NotClawbackEnabled,
        }
    }

    #[must_use]
    pub const fn variants() -> [ClawbackClaimableBalanceResultCode; 4] {
        Self::VARIANTS
    }
}

impl Name for ClawbackClaimableBalanceResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<ClawbackClaimableBalanceResultCode> for ClawbackClaimableBalanceResult {
    #[must_use]
    fn discriminant(&self) -> ClawbackClaimableBalanceResultCode {
        Self::discriminant(self)
    }
}

impl Variants<ClawbackClaimableBalanceResultCode> for ClawbackClaimableBalanceResult {
    fn variants() -> slice::Iter<'static, ClawbackClaimableBalanceResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<ClawbackClaimableBalanceResultCode> for ClawbackClaimableBalanceResult {}

impl ReadXdr for ClawbackClaimableBalanceResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: ClawbackClaimableBalanceResultCode =
            <ClawbackClaimableBalanceResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            ClawbackClaimableBalanceResultCode::Success => Self::Success,
            ClawbackClaimableBalanceResultCode::DoesNotExist => Self::DoesNotExist,
            ClawbackClaimableBalanceResultCode::NotIssuer => Self::NotIssuer,
            ClawbackClaimableBalanceResultCode::NotClawbackEnabled => Self::NotClawbackEnabled,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ClawbackClaimableBalanceResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::DoesNotExist => ().write_xdr(w)?,
            Self::NotIssuer => ().write_xdr(w)?,
            Self::NotClawbackEnabled => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// SetTrustLineFlagsResultCode is an XDR Enum defines as:
//
//   enum SetTrustLineFlagsResultCode
//    {
//        // codes considered as "success" for the operation
//        SET_TRUST_LINE_FLAGS_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        SET_TRUST_LINE_FLAGS_MALFORMED = -1,
//        SET_TRUST_LINE_FLAGS_NO_TRUST_LINE = -2,
//        SET_TRUST_LINE_FLAGS_CANT_REVOKE = -3,
//        SET_TRUST_LINE_FLAGS_INVALID_STATE = -4,
//        SET_TRUST_LINE_FLAGS_LOW_RESERVE = -5 // claimable balances can't be created
//                                              // on revoke due to low reserves
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum SetTrustLineFlagsResultCode {
    Success = 0,
    Malformed = -1,
    NoTrustLine = -2,
    CantRevoke = -3,
    InvalidState = -4,
    LowReserve = -5,
}

impl SetTrustLineFlagsResultCode {
    pub const VARIANTS: [SetTrustLineFlagsResultCode; 6] = [
        SetTrustLineFlagsResultCode::Success,
        SetTrustLineFlagsResultCode::Malformed,
        SetTrustLineFlagsResultCode::NoTrustLine,
        SetTrustLineFlagsResultCode::CantRevoke,
        SetTrustLineFlagsResultCode::InvalidState,
        SetTrustLineFlagsResultCode::LowReserve,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "Malformed",
        "NoTrustLine",
        "CantRevoke",
        "InvalidState",
        "LowReserve",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoTrustLine => "NoTrustLine",
            Self::CantRevoke => "CantRevoke",
            Self::InvalidState => "InvalidState",
            Self::LowReserve => "LowReserve",
        }
    }

    #[must_use]
    pub const fn variants() -> [SetTrustLineFlagsResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for SetTrustLineFlagsResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<SetTrustLineFlagsResultCode> for SetTrustLineFlagsResultCode {
    fn variants() -> slice::Iter<'static, SetTrustLineFlagsResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for SetTrustLineFlagsResultCode {}

impl fmt::Display for SetTrustLineFlagsResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for SetTrustLineFlagsResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => SetTrustLineFlagsResultCode::Success,
            -1 => SetTrustLineFlagsResultCode::Malformed,
            -2 => SetTrustLineFlagsResultCode::NoTrustLine,
            -3 => SetTrustLineFlagsResultCode::CantRevoke,
            -4 => SetTrustLineFlagsResultCode::InvalidState,
            -5 => SetTrustLineFlagsResultCode::LowReserve,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<SetTrustLineFlagsResultCode> for i32 {
    #[must_use]
    fn from(e: SetTrustLineFlagsResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for SetTrustLineFlagsResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for SetTrustLineFlagsResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// SetTrustLineFlagsResult is an XDR Union defines as:
//
//   union SetTrustLineFlagsResult switch (SetTrustLineFlagsResultCode code)
//    {
//    case SET_TRUST_LINE_FLAGS_SUCCESS:
//        void;
//    case SET_TRUST_LINE_FLAGS_MALFORMED:
//    case SET_TRUST_LINE_FLAGS_NO_TRUST_LINE:
//    case SET_TRUST_LINE_FLAGS_CANT_REVOKE:
//    case SET_TRUST_LINE_FLAGS_INVALID_STATE:
//    case SET_TRUST_LINE_FLAGS_LOW_RESERVE:
//        void;
//    };
//
// union with discriminant SetTrustLineFlagsResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum SetTrustLineFlagsResult {
    Success,
    Malformed,
    NoTrustLine,
    CantRevoke,
    InvalidState,
    LowReserve,
}

impl SetTrustLineFlagsResult {
    pub const VARIANTS: [SetTrustLineFlagsResultCode; 6] = [
        SetTrustLineFlagsResultCode::Success,
        SetTrustLineFlagsResultCode::Malformed,
        SetTrustLineFlagsResultCode::NoTrustLine,
        SetTrustLineFlagsResultCode::CantRevoke,
        SetTrustLineFlagsResultCode::InvalidState,
        SetTrustLineFlagsResultCode::LowReserve,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "Malformed",
        "NoTrustLine",
        "CantRevoke",
        "InvalidState",
        "LowReserve",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoTrustLine => "NoTrustLine",
            Self::CantRevoke => "CantRevoke",
            Self::InvalidState => "InvalidState",
            Self::LowReserve => "LowReserve",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> SetTrustLineFlagsResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => SetTrustLineFlagsResultCode::Success,
            Self::Malformed => SetTrustLineFlagsResultCode::Malformed,
            Self::NoTrustLine => SetTrustLineFlagsResultCode::NoTrustLine,
            Self::CantRevoke => SetTrustLineFlagsResultCode::CantRevoke,
            Self::InvalidState => SetTrustLineFlagsResultCode::InvalidState,
            Self::LowReserve => SetTrustLineFlagsResultCode::LowReserve,
        }
    }

    #[must_use]
    pub const fn variants() -> [SetTrustLineFlagsResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for SetTrustLineFlagsResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<SetTrustLineFlagsResultCode> for SetTrustLineFlagsResult {
    #[must_use]
    fn discriminant(&self) -> SetTrustLineFlagsResultCode {
        Self::discriminant(self)
    }
}

impl Variants<SetTrustLineFlagsResultCode> for SetTrustLineFlagsResult {
    fn variants() -> slice::Iter<'static, SetTrustLineFlagsResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<SetTrustLineFlagsResultCode> for SetTrustLineFlagsResult {}

impl ReadXdr for SetTrustLineFlagsResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: SetTrustLineFlagsResultCode =
            <SetTrustLineFlagsResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            SetTrustLineFlagsResultCode::Success => Self::Success,
            SetTrustLineFlagsResultCode::Malformed => Self::Malformed,
            SetTrustLineFlagsResultCode::NoTrustLine => Self::NoTrustLine,
            SetTrustLineFlagsResultCode::CantRevoke => Self::CantRevoke,
            SetTrustLineFlagsResultCode::InvalidState => Self::InvalidState,
            SetTrustLineFlagsResultCode::LowReserve => Self::LowReserve,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for SetTrustLineFlagsResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::NoTrustLine => ().write_xdr(w)?,
            Self::CantRevoke => ().write_xdr(w)?,
            Self::InvalidState => ().write_xdr(w)?,
            Self::LowReserve => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// LiquidityPoolDepositResultCode is an XDR Enum defines as:
//
//   enum LiquidityPoolDepositResultCode
//    {
//        // codes considered as "success" for the operation
//        LIQUIDITY_POOL_DEPOSIT_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        LIQUIDITY_POOL_DEPOSIT_MALFORMED = -1,      // bad input
//        LIQUIDITY_POOL_DEPOSIT_NO_TRUST = -2,       // no trust line for one of the
//                                                    // assets
//        LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED = -3, // not authorized for one of the
//                                                    // assets
//        LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED = -4,    // not enough balance for one of
//                                                    // the assets
//        LIQUIDITY_POOL_DEPOSIT_LINE_FULL = -5,      // pool share trust line doesn't
//                                                    // have sufficient limit
//        LIQUIDITY_POOL_DEPOSIT_BAD_PRICE = -6,      // deposit price outside bounds
//        LIQUIDITY_POOL_DEPOSIT_POOL_FULL = -7       // pool reserves are full
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum LiquidityPoolDepositResultCode {
    Success = 0,
    Malformed = -1,
    NoTrust = -2,
    NotAuthorized = -3,
    Underfunded = -4,
    LineFull = -5,
    BadPrice = -6,
    PoolFull = -7,
}

impl LiquidityPoolDepositResultCode {
    pub const VARIANTS: [LiquidityPoolDepositResultCode; 8] = [
        LiquidityPoolDepositResultCode::Success,
        LiquidityPoolDepositResultCode::Malformed,
        LiquidityPoolDepositResultCode::NoTrust,
        LiquidityPoolDepositResultCode::NotAuthorized,
        LiquidityPoolDepositResultCode::Underfunded,
        LiquidityPoolDepositResultCode::LineFull,
        LiquidityPoolDepositResultCode::BadPrice,
        LiquidityPoolDepositResultCode::PoolFull,
    ];
    pub const VARIANTS_STR: [&'static str; 8] = [
        "Success",
        "Malformed",
        "NoTrust",
        "NotAuthorized",
        "Underfunded",
        "LineFull",
        "BadPrice",
        "PoolFull",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::Underfunded => "Underfunded",
            Self::LineFull => "LineFull",
            Self::BadPrice => "BadPrice",
            Self::PoolFull => "PoolFull",
        }
    }

    #[must_use]
    pub const fn variants() -> [LiquidityPoolDepositResultCode; 8] {
        Self::VARIANTS
    }
}

impl Name for LiquidityPoolDepositResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<LiquidityPoolDepositResultCode> for LiquidityPoolDepositResultCode {
    fn variants() -> slice::Iter<'static, LiquidityPoolDepositResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for LiquidityPoolDepositResultCode {}

impl fmt::Display for LiquidityPoolDepositResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for LiquidityPoolDepositResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => LiquidityPoolDepositResultCode::Success,
            -1 => LiquidityPoolDepositResultCode::Malformed,
            -2 => LiquidityPoolDepositResultCode::NoTrust,
            -3 => LiquidityPoolDepositResultCode::NotAuthorized,
            -4 => LiquidityPoolDepositResultCode::Underfunded,
            -5 => LiquidityPoolDepositResultCode::LineFull,
            -6 => LiquidityPoolDepositResultCode::BadPrice,
            -7 => LiquidityPoolDepositResultCode::PoolFull,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<LiquidityPoolDepositResultCode> for i32 {
    #[must_use]
    fn from(e: LiquidityPoolDepositResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for LiquidityPoolDepositResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for LiquidityPoolDepositResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// LiquidityPoolDepositResult is an XDR Union defines as:
//
//   union LiquidityPoolDepositResult switch (LiquidityPoolDepositResultCode code)
//    {
//    case LIQUIDITY_POOL_DEPOSIT_SUCCESS:
//        void;
//    case LIQUIDITY_POOL_DEPOSIT_MALFORMED:
//    case LIQUIDITY_POOL_DEPOSIT_NO_TRUST:
//    case LIQUIDITY_POOL_DEPOSIT_NOT_AUTHORIZED:
//    case LIQUIDITY_POOL_DEPOSIT_UNDERFUNDED:
//    case LIQUIDITY_POOL_DEPOSIT_LINE_FULL:
//    case LIQUIDITY_POOL_DEPOSIT_BAD_PRICE:
//    case LIQUIDITY_POOL_DEPOSIT_POOL_FULL:
//        void;
//    };
//
// union with discriminant LiquidityPoolDepositResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LiquidityPoolDepositResult {
    Success,
    Malformed,
    NoTrust,
    NotAuthorized,
    Underfunded,
    LineFull,
    BadPrice,
    PoolFull,
}

impl LiquidityPoolDepositResult {
    pub const VARIANTS: [LiquidityPoolDepositResultCode; 8] = [
        LiquidityPoolDepositResultCode::Success,
        LiquidityPoolDepositResultCode::Malformed,
        LiquidityPoolDepositResultCode::NoTrust,
        LiquidityPoolDepositResultCode::NotAuthorized,
        LiquidityPoolDepositResultCode::Underfunded,
        LiquidityPoolDepositResultCode::LineFull,
        LiquidityPoolDepositResultCode::BadPrice,
        LiquidityPoolDepositResultCode::PoolFull,
    ];
    pub const VARIANTS_STR: [&'static str; 8] = [
        "Success",
        "Malformed",
        "NoTrust",
        "NotAuthorized",
        "Underfunded",
        "LineFull",
        "BadPrice",
        "PoolFull",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoTrust => "NoTrust",
            Self::NotAuthorized => "NotAuthorized",
            Self::Underfunded => "Underfunded",
            Self::LineFull => "LineFull",
            Self::BadPrice => "BadPrice",
            Self::PoolFull => "PoolFull",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> LiquidityPoolDepositResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => LiquidityPoolDepositResultCode::Success,
            Self::Malformed => LiquidityPoolDepositResultCode::Malformed,
            Self::NoTrust => LiquidityPoolDepositResultCode::NoTrust,
            Self::NotAuthorized => LiquidityPoolDepositResultCode::NotAuthorized,
            Self::Underfunded => LiquidityPoolDepositResultCode::Underfunded,
            Self::LineFull => LiquidityPoolDepositResultCode::LineFull,
            Self::BadPrice => LiquidityPoolDepositResultCode::BadPrice,
            Self::PoolFull => LiquidityPoolDepositResultCode::PoolFull,
        }
    }

    #[must_use]
    pub const fn variants() -> [LiquidityPoolDepositResultCode; 8] {
        Self::VARIANTS
    }
}

impl Name for LiquidityPoolDepositResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<LiquidityPoolDepositResultCode> for LiquidityPoolDepositResult {
    #[must_use]
    fn discriminant(&self) -> LiquidityPoolDepositResultCode {
        Self::discriminant(self)
    }
}

impl Variants<LiquidityPoolDepositResultCode> for LiquidityPoolDepositResult {
    fn variants() -> slice::Iter<'static, LiquidityPoolDepositResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<LiquidityPoolDepositResultCode> for LiquidityPoolDepositResult {}

impl ReadXdr for LiquidityPoolDepositResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: LiquidityPoolDepositResultCode =
            <LiquidityPoolDepositResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            LiquidityPoolDepositResultCode::Success => Self::Success,
            LiquidityPoolDepositResultCode::Malformed => Self::Malformed,
            LiquidityPoolDepositResultCode::NoTrust => Self::NoTrust,
            LiquidityPoolDepositResultCode::NotAuthorized => Self::NotAuthorized,
            LiquidityPoolDepositResultCode::Underfunded => Self::Underfunded,
            LiquidityPoolDepositResultCode::LineFull => Self::LineFull,
            LiquidityPoolDepositResultCode::BadPrice => Self::BadPrice,
            LiquidityPoolDepositResultCode::PoolFull => Self::PoolFull,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LiquidityPoolDepositResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::NoTrust => ().write_xdr(w)?,
            Self::NotAuthorized => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
            Self::LineFull => ().write_xdr(w)?,
            Self::BadPrice => ().write_xdr(w)?,
            Self::PoolFull => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// LiquidityPoolWithdrawResultCode is an XDR Enum defines as:
//
//   enum LiquidityPoolWithdrawResultCode
//    {
//        // codes considered as "success" for the operation
//        LIQUIDITY_POOL_WITHDRAW_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        LIQUIDITY_POOL_WITHDRAW_MALFORMED = -1,    // bad input
//        LIQUIDITY_POOL_WITHDRAW_NO_TRUST = -2,     // no trust line for one of the
//                                                   // assets
//        LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED = -3,  // not enough balance of the
//                                                   // pool share
//        LIQUIDITY_POOL_WITHDRAW_LINE_FULL = -4,    // would go above limit for one
//                                                   // of the assets
//        LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM = -5 // didn't withdraw enough
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum LiquidityPoolWithdrawResultCode {
    Success = 0,
    Malformed = -1,
    NoTrust = -2,
    Underfunded = -3,
    LineFull = -4,
    UnderMinimum = -5,
}

impl LiquidityPoolWithdrawResultCode {
    pub const VARIANTS: [LiquidityPoolWithdrawResultCode; 6] = [
        LiquidityPoolWithdrawResultCode::Success,
        LiquidityPoolWithdrawResultCode::Malformed,
        LiquidityPoolWithdrawResultCode::NoTrust,
        LiquidityPoolWithdrawResultCode::Underfunded,
        LiquidityPoolWithdrawResultCode::LineFull,
        LiquidityPoolWithdrawResultCode::UnderMinimum,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "Malformed",
        "NoTrust",
        "Underfunded",
        "LineFull",
        "UnderMinimum",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoTrust => "NoTrust",
            Self::Underfunded => "Underfunded",
            Self::LineFull => "LineFull",
            Self::UnderMinimum => "UnderMinimum",
        }
    }

    #[must_use]
    pub const fn variants() -> [LiquidityPoolWithdrawResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for LiquidityPoolWithdrawResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<LiquidityPoolWithdrawResultCode> for LiquidityPoolWithdrawResultCode {
    fn variants() -> slice::Iter<'static, LiquidityPoolWithdrawResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for LiquidityPoolWithdrawResultCode {}

impl fmt::Display for LiquidityPoolWithdrawResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for LiquidityPoolWithdrawResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => LiquidityPoolWithdrawResultCode::Success,
            -1 => LiquidityPoolWithdrawResultCode::Malformed,
            -2 => LiquidityPoolWithdrawResultCode::NoTrust,
            -3 => LiquidityPoolWithdrawResultCode::Underfunded,
            -4 => LiquidityPoolWithdrawResultCode::LineFull,
            -5 => LiquidityPoolWithdrawResultCode::UnderMinimum,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<LiquidityPoolWithdrawResultCode> for i32 {
    #[must_use]
    fn from(e: LiquidityPoolWithdrawResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for LiquidityPoolWithdrawResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for LiquidityPoolWithdrawResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// LiquidityPoolWithdrawResult is an XDR Union defines as:
//
//   union LiquidityPoolWithdrawResult switch (LiquidityPoolWithdrawResultCode code)
//    {
//    case LIQUIDITY_POOL_WITHDRAW_SUCCESS:
//        void;
//    case LIQUIDITY_POOL_WITHDRAW_MALFORMED:
//    case LIQUIDITY_POOL_WITHDRAW_NO_TRUST:
//    case LIQUIDITY_POOL_WITHDRAW_UNDERFUNDED:
//    case LIQUIDITY_POOL_WITHDRAW_LINE_FULL:
//    case LIQUIDITY_POOL_WITHDRAW_UNDER_MINIMUM:
//        void;
//    };
//
// union with discriminant LiquidityPoolWithdrawResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum LiquidityPoolWithdrawResult {
    Success,
    Malformed,
    NoTrust,
    Underfunded,
    LineFull,
    UnderMinimum,
}

impl LiquidityPoolWithdrawResult {
    pub const VARIANTS: [LiquidityPoolWithdrawResultCode; 6] = [
        LiquidityPoolWithdrawResultCode::Success,
        LiquidityPoolWithdrawResultCode::Malformed,
        LiquidityPoolWithdrawResultCode::NoTrust,
        LiquidityPoolWithdrawResultCode::Underfunded,
        LiquidityPoolWithdrawResultCode::LineFull,
        LiquidityPoolWithdrawResultCode::UnderMinimum,
    ];
    pub const VARIANTS_STR: [&'static str; 6] = [
        "Success",
        "Malformed",
        "NoTrust",
        "Underfunded",
        "LineFull",
        "UnderMinimum",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::NoTrust => "NoTrust",
            Self::Underfunded => "Underfunded",
            Self::LineFull => "LineFull",
            Self::UnderMinimum => "UnderMinimum",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> LiquidityPoolWithdrawResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => LiquidityPoolWithdrawResultCode::Success,
            Self::Malformed => LiquidityPoolWithdrawResultCode::Malformed,
            Self::NoTrust => LiquidityPoolWithdrawResultCode::NoTrust,
            Self::Underfunded => LiquidityPoolWithdrawResultCode::Underfunded,
            Self::LineFull => LiquidityPoolWithdrawResultCode::LineFull,
            Self::UnderMinimum => LiquidityPoolWithdrawResultCode::UnderMinimum,
        }
    }

    #[must_use]
    pub const fn variants() -> [LiquidityPoolWithdrawResultCode; 6] {
        Self::VARIANTS
    }
}

impl Name for LiquidityPoolWithdrawResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<LiquidityPoolWithdrawResultCode> for LiquidityPoolWithdrawResult {
    #[must_use]
    fn discriminant(&self) -> LiquidityPoolWithdrawResultCode {
        Self::discriminant(self)
    }
}

impl Variants<LiquidityPoolWithdrawResultCode> for LiquidityPoolWithdrawResult {
    fn variants() -> slice::Iter<'static, LiquidityPoolWithdrawResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<LiquidityPoolWithdrawResultCode> for LiquidityPoolWithdrawResult {}

impl ReadXdr for LiquidityPoolWithdrawResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: LiquidityPoolWithdrawResultCode =
            <LiquidityPoolWithdrawResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            LiquidityPoolWithdrawResultCode::Success => Self::Success,
            LiquidityPoolWithdrawResultCode::Malformed => Self::Malformed,
            LiquidityPoolWithdrawResultCode::NoTrust => Self::NoTrust,
            LiquidityPoolWithdrawResultCode::Underfunded => Self::Underfunded,
            LiquidityPoolWithdrawResultCode::LineFull => Self::LineFull,
            LiquidityPoolWithdrawResultCode::UnderMinimum => Self::UnderMinimum,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for LiquidityPoolWithdrawResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success => ().write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::NoTrust => ().write_xdr(w)?,
            Self::Underfunded => ().write_xdr(w)?,
            Self::LineFull => ().write_xdr(w)?,
            Self::UnderMinimum => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// InvokeHostFunctionResultCode is an XDR Enum defines as:
//
//   enum InvokeHostFunctionResultCode
//    {
//        // codes considered as "success" for the operation
//        INVOKE_HOST_FUNCTION_SUCCESS = 0,
//
//        // codes considered as "failure" for the operation
//        INVOKE_HOST_FUNCTION_MALFORMED = -1,
//        INVOKE_HOST_FUNCTION_TRAPPED = -2
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum InvokeHostFunctionResultCode {
    Success = 0,
    Malformed = -1,
    Trapped = -2,
}

impl InvokeHostFunctionResultCode {
    pub const VARIANTS: [InvokeHostFunctionResultCode; 3] = [
        InvokeHostFunctionResultCode::Success,
        InvokeHostFunctionResultCode::Malformed,
        InvokeHostFunctionResultCode::Trapped,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["Success", "Malformed", "Trapped"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success => "Success",
            Self::Malformed => "Malformed",
            Self::Trapped => "Trapped",
        }
    }

    #[must_use]
    pub const fn variants() -> [InvokeHostFunctionResultCode; 3] {
        Self::VARIANTS
    }
}

impl Name for InvokeHostFunctionResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<InvokeHostFunctionResultCode> for InvokeHostFunctionResultCode {
    fn variants() -> slice::Iter<'static, InvokeHostFunctionResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for InvokeHostFunctionResultCode {}

impl fmt::Display for InvokeHostFunctionResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for InvokeHostFunctionResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => InvokeHostFunctionResultCode::Success,
            -1 => InvokeHostFunctionResultCode::Malformed,
            -2 => InvokeHostFunctionResultCode::Trapped,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<InvokeHostFunctionResultCode> for i32 {
    #[must_use]
    fn from(e: InvokeHostFunctionResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for InvokeHostFunctionResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for InvokeHostFunctionResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// InvokeHostFunctionResult is an XDR Union defines as:
//
//   union InvokeHostFunctionResult switch (InvokeHostFunctionResultCode code)
//    {
//    case INVOKE_HOST_FUNCTION_SUCCESS:
//        SCVal success;
//    case INVOKE_HOST_FUNCTION_MALFORMED:
//    case INVOKE_HOST_FUNCTION_TRAPPED:
//        void;
//    };
//
// union with discriminant InvokeHostFunctionResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum InvokeHostFunctionResult {
    Success(ScVal),
    Malformed,
    Trapped,
}

impl InvokeHostFunctionResult {
    pub const VARIANTS: [InvokeHostFunctionResultCode; 3] = [
        InvokeHostFunctionResultCode::Success,
        InvokeHostFunctionResultCode::Malformed,
        InvokeHostFunctionResultCode::Trapped,
    ];
    pub const VARIANTS_STR: [&'static str; 3] = ["Success", "Malformed", "Trapped"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Success(_) => "Success",
            Self::Malformed => "Malformed",
            Self::Trapped => "Trapped",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> InvokeHostFunctionResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(_) => InvokeHostFunctionResultCode::Success,
            Self::Malformed => InvokeHostFunctionResultCode::Malformed,
            Self::Trapped => InvokeHostFunctionResultCode::Trapped,
        }
    }

    #[must_use]
    pub const fn variants() -> [InvokeHostFunctionResultCode; 3] {
        Self::VARIANTS
    }
}

impl Name for InvokeHostFunctionResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<InvokeHostFunctionResultCode> for InvokeHostFunctionResult {
    #[must_use]
    fn discriminant(&self) -> InvokeHostFunctionResultCode {
        Self::discriminant(self)
    }
}

impl Variants<InvokeHostFunctionResultCode> for InvokeHostFunctionResult {
    fn variants() -> slice::Iter<'static, InvokeHostFunctionResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<InvokeHostFunctionResultCode> for InvokeHostFunctionResult {}

impl ReadXdr for InvokeHostFunctionResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: InvokeHostFunctionResultCode =
            <InvokeHostFunctionResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            InvokeHostFunctionResultCode::Success => Self::Success(ScVal::read_xdr(r)?),
            InvokeHostFunctionResultCode::Malformed => Self::Malformed,
            InvokeHostFunctionResultCode::Trapped => Self::Trapped,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for InvokeHostFunctionResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Success(v) => v.write_xdr(w)?,
            Self::Malformed => ().write_xdr(w)?,
            Self::Trapped => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// OperationResultCode is an XDR Enum defines as:
//
//   enum OperationResultCode
//    {
//        opINNER = 0, // inner object result is valid
//
//        opBAD_AUTH = -1,            // too few valid signatures / wrong network
//        opNO_ACCOUNT = -2,          // source account was not found
//        opNOT_SUPPORTED = -3,       // operation not supported at this time
//        opTOO_MANY_SUBENTRIES = -4, // max number of subentries already reached
//        opEXCEEDED_WORK_LIMIT = -5, // operation did too much work
//        opTOO_MANY_SPONSORING = -6  // account is sponsoring too many entries
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum OperationResultCode {
    OpInner = 0,
    OpBadAuth = -1,
    OpNoAccount = -2,
    OpNotSupported = -3,
    OpTooManySubentries = -4,
    OpExceededWorkLimit = -5,
    OpTooManySponsoring = -6,
}

impl OperationResultCode {
    pub const VARIANTS: [OperationResultCode; 7] = [
        OperationResultCode::OpInner,
        OperationResultCode::OpBadAuth,
        OperationResultCode::OpNoAccount,
        OperationResultCode::OpNotSupported,
        OperationResultCode::OpTooManySubentries,
        OperationResultCode::OpExceededWorkLimit,
        OperationResultCode::OpTooManySponsoring,
    ];
    pub const VARIANTS_STR: [&'static str; 7] = [
        "OpInner",
        "OpBadAuth",
        "OpNoAccount",
        "OpNotSupported",
        "OpTooManySubentries",
        "OpExceededWorkLimit",
        "OpTooManySponsoring",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::OpInner => "OpInner",
            Self::OpBadAuth => "OpBadAuth",
            Self::OpNoAccount => "OpNoAccount",
            Self::OpNotSupported => "OpNotSupported",
            Self::OpTooManySubentries => "OpTooManySubentries",
            Self::OpExceededWorkLimit => "OpExceededWorkLimit",
            Self::OpTooManySponsoring => "OpTooManySponsoring",
        }
    }

    #[must_use]
    pub const fn variants() -> [OperationResultCode; 7] {
        Self::VARIANTS
    }
}

impl Name for OperationResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<OperationResultCode> for OperationResultCode {
    fn variants() -> slice::Iter<'static, OperationResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for OperationResultCode {}

impl fmt::Display for OperationResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for OperationResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => OperationResultCode::OpInner,
            -1 => OperationResultCode::OpBadAuth,
            -2 => OperationResultCode::OpNoAccount,
            -3 => OperationResultCode::OpNotSupported,
            -4 => OperationResultCode::OpTooManySubentries,
            -5 => OperationResultCode::OpExceededWorkLimit,
            -6 => OperationResultCode::OpTooManySponsoring,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<OperationResultCode> for i32 {
    #[must_use]
    fn from(e: OperationResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for OperationResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for OperationResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// OperationResultTr is an XDR NestedUnion defines as:
//
//   union switch (OperationType type)
//        {
//        case CREATE_ACCOUNT:
//            CreateAccountResult createAccountResult;
//        case PAYMENT:
//            PaymentResult paymentResult;
//        case PATH_PAYMENT_STRICT_RECEIVE:
//            PathPaymentStrictReceiveResult pathPaymentStrictReceiveResult;
//        case MANAGE_SELL_OFFER:
//            ManageSellOfferResult manageSellOfferResult;
//        case CREATE_PASSIVE_SELL_OFFER:
//            ManageSellOfferResult createPassiveSellOfferResult;
//        case SET_OPTIONS:
//            SetOptionsResult setOptionsResult;
//        case CHANGE_TRUST:
//            ChangeTrustResult changeTrustResult;
//        case ALLOW_TRUST:
//            AllowTrustResult allowTrustResult;
//        case ACCOUNT_MERGE:
//            AccountMergeResult accountMergeResult;
//        case INFLATION:
//            InflationResult inflationResult;
//        case MANAGE_DATA:
//            ManageDataResult manageDataResult;
//        case BUMP_SEQUENCE:
//            BumpSequenceResult bumpSeqResult;
//        case MANAGE_BUY_OFFER:
//            ManageBuyOfferResult manageBuyOfferResult;
//        case PATH_PAYMENT_STRICT_SEND:
//            PathPaymentStrictSendResult pathPaymentStrictSendResult;
//        case CREATE_CLAIMABLE_BALANCE:
//            CreateClaimableBalanceResult createClaimableBalanceResult;
//        case CLAIM_CLAIMABLE_BALANCE:
//            ClaimClaimableBalanceResult claimClaimableBalanceResult;
//        case BEGIN_SPONSORING_FUTURE_RESERVES:
//            BeginSponsoringFutureReservesResult beginSponsoringFutureReservesResult;
//        case END_SPONSORING_FUTURE_RESERVES:
//            EndSponsoringFutureReservesResult endSponsoringFutureReservesResult;
//        case REVOKE_SPONSORSHIP:
//            RevokeSponsorshipResult revokeSponsorshipResult;
//        case CLAWBACK:
//            ClawbackResult clawbackResult;
//        case CLAWBACK_CLAIMABLE_BALANCE:
//            ClawbackClaimableBalanceResult clawbackClaimableBalanceResult;
//        case SET_TRUST_LINE_FLAGS:
//            SetTrustLineFlagsResult setTrustLineFlagsResult;
//        case LIQUIDITY_POOL_DEPOSIT:
//            LiquidityPoolDepositResult liquidityPoolDepositResult;
//        case LIQUIDITY_POOL_WITHDRAW:
//            LiquidityPoolWithdrawResult liquidityPoolWithdrawResult;
//        case INVOKE_HOST_FUNCTION:
//            InvokeHostFunctionResult invokeHostFunctionResult;
//        }
//
// union with discriminant OperationType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum OperationResultTr {
    CreateAccount(CreateAccountResult),
    Payment(PaymentResult),
    PathPaymentStrictReceive(PathPaymentStrictReceiveResult),
    ManageSellOffer(ManageSellOfferResult),
    CreatePassiveSellOffer(ManageSellOfferResult),
    SetOptions(SetOptionsResult),
    ChangeTrust(ChangeTrustResult),
    AllowTrust(AllowTrustResult),
    AccountMerge(AccountMergeResult),
    Inflation(InflationResult),
    ManageData(ManageDataResult),
    BumpSequence(BumpSequenceResult),
    ManageBuyOffer(ManageBuyOfferResult),
    PathPaymentStrictSend(PathPaymentStrictSendResult),
    CreateClaimableBalance(CreateClaimableBalanceResult),
    ClaimClaimableBalance(ClaimClaimableBalanceResult),
    BeginSponsoringFutureReserves(BeginSponsoringFutureReservesResult),
    EndSponsoringFutureReserves(EndSponsoringFutureReservesResult),
    RevokeSponsorship(RevokeSponsorshipResult),
    Clawback(ClawbackResult),
    ClawbackClaimableBalance(ClawbackClaimableBalanceResult),
    SetTrustLineFlags(SetTrustLineFlagsResult),
    LiquidityPoolDeposit(LiquidityPoolDepositResult),
    LiquidityPoolWithdraw(LiquidityPoolWithdrawResult),
    InvokeHostFunction(InvokeHostFunctionResult),
}

impl OperationResultTr {
    pub const VARIANTS: [OperationType; 25] = [
        OperationType::CreateAccount,
        OperationType::Payment,
        OperationType::PathPaymentStrictReceive,
        OperationType::ManageSellOffer,
        OperationType::CreatePassiveSellOffer,
        OperationType::SetOptions,
        OperationType::ChangeTrust,
        OperationType::AllowTrust,
        OperationType::AccountMerge,
        OperationType::Inflation,
        OperationType::ManageData,
        OperationType::BumpSequence,
        OperationType::ManageBuyOffer,
        OperationType::PathPaymentStrictSend,
        OperationType::CreateClaimableBalance,
        OperationType::ClaimClaimableBalance,
        OperationType::BeginSponsoringFutureReserves,
        OperationType::EndSponsoringFutureReserves,
        OperationType::RevokeSponsorship,
        OperationType::Clawback,
        OperationType::ClawbackClaimableBalance,
        OperationType::SetTrustLineFlags,
        OperationType::LiquidityPoolDeposit,
        OperationType::LiquidityPoolWithdraw,
        OperationType::InvokeHostFunction,
    ];
    pub const VARIANTS_STR: [&'static str; 25] = [
        "CreateAccount",
        "Payment",
        "PathPaymentStrictReceive",
        "ManageSellOffer",
        "CreatePassiveSellOffer",
        "SetOptions",
        "ChangeTrust",
        "AllowTrust",
        "AccountMerge",
        "Inflation",
        "ManageData",
        "BumpSequence",
        "ManageBuyOffer",
        "PathPaymentStrictSend",
        "CreateClaimableBalance",
        "ClaimClaimableBalance",
        "BeginSponsoringFutureReserves",
        "EndSponsoringFutureReserves",
        "RevokeSponsorship",
        "Clawback",
        "ClawbackClaimableBalance",
        "SetTrustLineFlags",
        "LiquidityPoolDeposit",
        "LiquidityPoolWithdraw",
        "InvokeHostFunction",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::CreateAccount(_) => "CreateAccount",
            Self::Payment(_) => "Payment",
            Self::PathPaymentStrictReceive(_) => "PathPaymentStrictReceive",
            Self::ManageSellOffer(_) => "ManageSellOffer",
            Self::CreatePassiveSellOffer(_) => "CreatePassiveSellOffer",
            Self::SetOptions(_) => "SetOptions",
            Self::ChangeTrust(_) => "ChangeTrust",
            Self::AllowTrust(_) => "AllowTrust",
            Self::AccountMerge(_) => "AccountMerge",
            Self::Inflation(_) => "Inflation",
            Self::ManageData(_) => "ManageData",
            Self::BumpSequence(_) => "BumpSequence",
            Self::ManageBuyOffer(_) => "ManageBuyOffer",
            Self::PathPaymentStrictSend(_) => "PathPaymentStrictSend",
            Self::CreateClaimableBalance(_) => "CreateClaimableBalance",
            Self::ClaimClaimableBalance(_) => "ClaimClaimableBalance",
            Self::BeginSponsoringFutureReserves(_) => "BeginSponsoringFutureReserves",
            Self::EndSponsoringFutureReserves(_) => "EndSponsoringFutureReserves",
            Self::RevokeSponsorship(_) => "RevokeSponsorship",
            Self::Clawback(_) => "Clawback",
            Self::ClawbackClaimableBalance(_) => "ClawbackClaimableBalance",
            Self::SetTrustLineFlags(_) => "SetTrustLineFlags",
            Self::LiquidityPoolDeposit(_) => "LiquidityPoolDeposit",
            Self::LiquidityPoolWithdraw(_) => "LiquidityPoolWithdraw",
            Self::InvokeHostFunction(_) => "InvokeHostFunction",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> OperationType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::CreateAccount(_) => OperationType::CreateAccount,
            Self::Payment(_) => OperationType::Payment,
            Self::PathPaymentStrictReceive(_) => OperationType::PathPaymentStrictReceive,
            Self::ManageSellOffer(_) => OperationType::ManageSellOffer,
            Self::CreatePassiveSellOffer(_) => OperationType::CreatePassiveSellOffer,
            Self::SetOptions(_) => OperationType::SetOptions,
            Self::ChangeTrust(_) => OperationType::ChangeTrust,
            Self::AllowTrust(_) => OperationType::AllowTrust,
            Self::AccountMerge(_) => OperationType::AccountMerge,
            Self::Inflation(_) => OperationType::Inflation,
            Self::ManageData(_) => OperationType::ManageData,
            Self::BumpSequence(_) => OperationType::BumpSequence,
            Self::ManageBuyOffer(_) => OperationType::ManageBuyOffer,
            Self::PathPaymentStrictSend(_) => OperationType::PathPaymentStrictSend,
            Self::CreateClaimableBalance(_) => OperationType::CreateClaimableBalance,
            Self::ClaimClaimableBalance(_) => OperationType::ClaimClaimableBalance,
            Self::BeginSponsoringFutureReserves(_) => OperationType::BeginSponsoringFutureReserves,
            Self::EndSponsoringFutureReserves(_) => OperationType::EndSponsoringFutureReserves,
            Self::RevokeSponsorship(_) => OperationType::RevokeSponsorship,
            Self::Clawback(_) => OperationType::Clawback,
            Self::ClawbackClaimableBalance(_) => OperationType::ClawbackClaimableBalance,
            Self::SetTrustLineFlags(_) => OperationType::SetTrustLineFlags,
            Self::LiquidityPoolDeposit(_) => OperationType::LiquidityPoolDeposit,
            Self::LiquidityPoolWithdraw(_) => OperationType::LiquidityPoolWithdraw,
            Self::InvokeHostFunction(_) => OperationType::InvokeHostFunction,
        }
    }

    #[must_use]
    pub const fn variants() -> [OperationType; 25] {
        Self::VARIANTS
    }
}

impl Name for OperationResultTr {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<OperationType> for OperationResultTr {
    #[must_use]
    fn discriminant(&self) -> OperationType {
        Self::discriminant(self)
    }
}

impl Variants<OperationType> for OperationResultTr {
    fn variants() -> slice::Iter<'static, OperationType> {
        Self::VARIANTS.iter()
    }
}

impl Union<OperationType> for OperationResultTr {}

impl ReadXdr for OperationResultTr {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: OperationType = <OperationType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            OperationType::CreateAccount => Self::CreateAccount(CreateAccountResult::read_xdr(r)?),
            OperationType::Payment => Self::Payment(PaymentResult::read_xdr(r)?),
            OperationType::PathPaymentStrictReceive => {
                Self::PathPaymentStrictReceive(PathPaymentStrictReceiveResult::read_xdr(r)?)
            }
            OperationType::ManageSellOffer => {
                Self::ManageSellOffer(ManageSellOfferResult::read_xdr(r)?)
            }
            OperationType::CreatePassiveSellOffer => {
                Self::CreatePassiveSellOffer(ManageSellOfferResult::read_xdr(r)?)
            }
            OperationType::SetOptions => Self::SetOptions(SetOptionsResult::read_xdr(r)?),
            OperationType::ChangeTrust => Self::ChangeTrust(ChangeTrustResult::read_xdr(r)?),
            OperationType::AllowTrust => Self::AllowTrust(AllowTrustResult::read_xdr(r)?),
            OperationType::AccountMerge => Self::AccountMerge(AccountMergeResult::read_xdr(r)?),
            OperationType::Inflation => Self::Inflation(InflationResult::read_xdr(r)?),
            OperationType::ManageData => Self::ManageData(ManageDataResult::read_xdr(r)?),
            OperationType::BumpSequence => Self::BumpSequence(BumpSequenceResult::read_xdr(r)?),
            OperationType::ManageBuyOffer => {
                Self::ManageBuyOffer(ManageBuyOfferResult::read_xdr(r)?)
            }
            OperationType::PathPaymentStrictSend => {
                Self::PathPaymentStrictSend(PathPaymentStrictSendResult::read_xdr(r)?)
            }
            OperationType::CreateClaimableBalance => {
                Self::CreateClaimableBalance(CreateClaimableBalanceResult::read_xdr(r)?)
            }
            OperationType::ClaimClaimableBalance => {
                Self::ClaimClaimableBalance(ClaimClaimableBalanceResult::read_xdr(r)?)
            }
            OperationType::BeginSponsoringFutureReserves => Self::BeginSponsoringFutureReserves(
                BeginSponsoringFutureReservesResult::read_xdr(r)?,
            ),
            OperationType::EndSponsoringFutureReserves => {
                Self::EndSponsoringFutureReserves(EndSponsoringFutureReservesResult::read_xdr(r)?)
            }
            OperationType::RevokeSponsorship => {
                Self::RevokeSponsorship(RevokeSponsorshipResult::read_xdr(r)?)
            }
            OperationType::Clawback => Self::Clawback(ClawbackResult::read_xdr(r)?),
            OperationType::ClawbackClaimableBalance => {
                Self::ClawbackClaimableBalance(ClawbackClaimableBalanceResult::read_xdr(r)?)
            }
            OperationType::SetTrustLineFlags => {
                Self::SetTrustLineFlags(SetTrustLineFlagsResult::read_xdr(r)?)
            }
            OperationType::LiquidityPoolDeposit => {
                Self::LiquidityPoolDeposit(LiquidityPoolDepositResult::read_xdr(r)?)
            }
            OperationType::LiquidityPoolWithdraw => {
                Self::LiquidityPoolWithdraw(LiquidityPoolWithdrawResult::read_xdr(r)?)
            }
            OperationType::InvokeHostFunction => {
                Self::InvokeHostFunction(InvokeHostFunctionResult::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for OperationResultTr {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::CreateAccount(v) => v.write_xdr(w)?,
            Self::Payment(v) => v.write_xdr(w)?,
            Self::PathPaymentStrictReceive(v) => v.write_xdr(w)?,
            Self::ManageSellOffer(v) => v.write_xdr(w)?,
            Self::CreatePassiveSellOffer(v) => v.write_xdr(w)?,
            Self::SetOptions(v) => v.write_xdr(w)?,
            Self::ChangeTrust(v) => v.write_xdr(w)?,
            Self::AllowTrust(v) => v.write_xdr(w)?,
            Self::AccountMerge(v) => v.write_xdr(w)?,
            Self::Inflation(v) => v.write_xdr(w)?,
            Self::ManageData(v) => v.write_xdr(w)?,
            Self::BumpSequence(v) => v.write_xdr(w)?,
            Self::ManageBuyOffer(v) => v.write_xdr(w)?,
            Self::PathPaymentStrictSend(v) => v.write_xdr(w)?,
            Self::CreateClaimableBalance(v) => v.write_xdr(w)?,
            Self::ClaimClaimableBalance(v) => v.write_xdr(w)?,
            Self::BeginSponsoringFutureReserves(v) => v.write_xdr(w)?,
            Self::EndSponsoringFutureReserves(v) => v.write_xdr(w)?,
            Self::RevokeSponsorship(v) => v.write_xdr(w)?,
            Self::Clawback(v) => v.write_xdr(w)?,
            Self::ClawbackClaimableBalance(v) => v.write_xdr(w)?,
            Self::SetTrustLineFlags(v) => v.write_xdr(w)?,
            Self::LiquidityPoolDeposit(v) => v.write_xdr(w)?,
            Self::LiquidityPoolWithdraw(v) => v.write_xdr(w)?,
            Self::InvokeHostFunction(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// OperationResult is an XDR Union defines as:
//
//   union OperationResult switch (OperationResultCode code)
//    {
//    case opINNER:
//        union switch (OperationType type)
//        {
//        case CREATE_ACCOUNT:
//            CreateAccountResult createAccountResult;
//        case PAYMENT:
//            PaymentResult paymentResult;
//        case PATH_PAYMENT_STRICT_RECEIVE:
//            PathPaymentStrictReceiveResult pathPaymentStrictReceiveResult;
//        case MANAGE_SELL_OFFER:
//            ManageSellOfferResult manageSellOfferResult;
//        case CREATE_PASSIVE_SELL_OFFER:
//            ManageSellOfferResult createPassiveSellOfferResult;
//        case SET_OPTIONS:
//            SetOptionsResult setOptionsResult;
//        case CHANGE_TRUST:
//            ChangeTrustResult changeTrustResult;
//        case ALLOW_TRUST:
//            AllowTrustResult allowTrustResult;
//        case ACCOUNT_MERGE:
//            AccountMergeResult accountMergeResult;
//        case INFLATION:
//            InflationResult inflationResult;
//        case MANAGE_DATA:
//            ManageDataResult manageDataResult;
//        case BUMP_SEQUENCE:
//            BumpSequenceResult bumpSeqResult;
//        case MANAGE_BUY_OFFER:
//            ManageBuyOfferResult manageBuyOfferResult;
//        case PATH_PAYMENT_STRICT_SEND:
//            PathPaymentStrictSendResult pathPaymentStrictSendResult;
//        case CREATE_CLAIMABLE_BALANCE:
//            CreateClaimableBalanceResult createClaimableBalanceResult;
//        case CLAIM_CLAIMABLE_BALANCE:
//            ClaimClaimableBalanceResult claimClaimableBalanceResult;
//        case BEGIN_SPONSORING_FUTURE_RESERVES:
//            BeginSponsoringFutureReservesResult beginSponsoringFutureReservesResult;
//        case END_SPONSORING_FUTURE_RESERVES:
//            EndSponsoringFutureReservesResult endSponsoringFutureReservesResult;
//        case REVOKE_SPONSORSHIP:
//            RevokeSponsorshipResult revokeSponsorshipResult;
//        case CLAWBACK:
//            ClawbackResult clawbackResult;
//        case CLAWBACK_CLAIMABLE_BALANCE:
//            ClawbackClaimableBalanceResult clawbackClaimableBalanceResult;
//        case SET_TRUST_LINE_FLAGS:
//            SetTrustLineFlagsResult setTrustLineFlagsResult;
//        case LIQUIDITY_POOL_DEPOSIT:
//            LiquidityPoolDepositResult liquidityPoolDepositResult;
//        case LIQUIDITY_POOL_WITHDRAW:
//            LiquidityPoolWithdrawResult liquidityPoolWithdrawResult;
//        case INVOKE_HOST_FUNCTION:
//            InvokeHostFunctionResult invokeHostFunctionResult;
//        }
//        tr;
//    case opBAD_AUTH:
//    case opNO_ACCOUNT:
//    case opNOT_SUPPORTED:
//    case opTOO_MANY_SUBENTRIES:
//    case opEXCEEDED_WORK_LIMIT:
//    case opTOO_MANY_SPONSORING:
//        void;
//    };
//
// union with discriminant OperationResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum OperationResult {
    OpInner(OperationResultTr),
    OpBadAuth,
    OpNoAccount,
    OpNotSupported,
    OpTooManySubentries,
    OpExceededWorkLimit,
    OpTooManySponsoring,
}

impl OperationResult {
    pub const VARIANTS: [OperationResultCode; 7] = [
        OperationResultCode::OpInner,
        OperationResultCode::OpBadAuth,
        OperationResultCode::OpNoAccount,
        OperationResultCode::OpNotSupported,
        OperationResultCode::OpTooManySubentries,
        OperationResultCode::OpExceededWorkLimit,
        OperationResultCode::OpTooManySponsoring,
    ];
    pub const VARIANTS_STR: [&'static str; 7] = [
        "OpInner",
        "OpBadAuth",
        "OpNoAccount",
        "OpNotSupported",
        "OpTooManySubentries",
        "OpExceededWorkLimit",
        "OpTooManySponsoring",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::OpInner(_) => "OpInner",
            Self::OpBadAuth => "OpBadAuth",
            Self::OpNoAccount => "OpNoAccount",
            Self::OpNotSupported => "OpNotSupported",
            Self::OpTooManySubentries => "OpTooManySubentries",
            Self::OpExceededWorkLimit => "OpExceededWorkLimit",
            Self::OpTooManySponsoring => "OpTooManySponsoring",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> OperationResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::OpInner(_) => OperationResultCode::OpInner,
            Self::OpBadAuth => OperationResultCode::OpBadAuth,
            Self::OpNoAccount => OperationResultCode::OpNoAccount,
            Self::OpNotSupported => OperationResultCode::OpNotSupported,
            Self::OpTooManySubentries => OperationResultCode::OpTooManySubentries,
            Self::OpExceededWorkLimit => OperationResultCode::OpExceededWorkLimit,
            Self::OpTooManySponsoring => OperationResultCode::OpTooManySponsoring,
        }
    }

    #[must_use]
    pub const fn variants() -> [OperationResultCode; 7] {
        Self::VARIANTS
    }
}

impl Name for OperationResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<OperationResultCode> for OperationResult {
    #[must_use]
    fn discriminant(&self) -> OperationResultCode {
        Self::discriminant(self)
    }
}

impl Variants<OperationResultCode> for OperationResult {
    fn variants() -> slice::Iter<'static, OperationResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<OperationResultCode> for OperationResult {}

impl ReadXdr for OperationResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: OperationResultCode = <OperationResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            OperationResultCode::OpInner => Self::OpInner(OperationResultTr::read_xdr(r)?),
            OperationResultCode::OpBadAuth => Self::OpBadAuth,
            OperationResultCode::OpNoAccount => Self::OpNoAccount,
            OperationResultCode::OpNotSupported => Self::OpNotSupported,
            OperationResultCode::OpTooManySubentries => Self::OpTooManySubentries,
            OperationResultCode::OpExceededWorkLimit => Self::OpExceededWorkLimit,
            OperationResultCode::OpTooManySponsoring => Self::OpTooManySponsoring,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for OperationResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::OpInner(v) => v.write_xdr(w)?,
            Self::OpBadAuth => ().write_xdr(w)?,
            Self::OpNoAccount => ().write_xdr(w)?,
            Self::OpNotSupported => ().write_xdr(w)?,
            Self::OpTooManySubentries => ().write_xdr(w)?,
            Self::OpExceededWorkLimit => ().write_xdr(w)?,
            Self::OpTooManySponsoring => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionResultCode is an XDR Enum defines as:
//
//   enum TransactionResultCode
//    {
//        txFEE_BUMP_INNER_SUCCESS = 1, // fee bump inner transaction succeeded
//        txSUCCESS = 0,                // all operations succeeded
//
//        txFAILED = -1, // one of the operations failed (none were applied)
//
//        txTOO_EARLY = -2,         // ledger closeTime before minTime
//        txTOO_LATE = -3,          // ledger closeTime after maxTime
//        txMISSING_OPERATION = -4, // no operation was specified
//        txBAD_SEQ = -5,           // sequence number does not match source account
//
//        txBAD_AUTH = -6,             // too few valid signatures / wrong network
//        txINSUFFICIENT_BALANCE = -7, // fee would bring account below reserve
//        txNO_ACCOUNT = -8,           // source account not found
//        txINSUFFICIENT_FEE = -9,     // fee is too small
//        txBAD_AUTH_EXTRA = -10,      // unused signatures attached to transaction
//        txINTERNAL_ERROR = -11,      // an unknown error occurred
//
//        txNOT_SUPPORTED = -12,         // transaction type not supported
//        txFEE_BUMP_INNER_FAILED = -13, // fee bump inner transaction failed
//        txBAD_SPONSORSHIP = -14,       // sponsorship not confirmed
//        txBAD_MIN_SEQ_AGE_OR_GAP =
//            -15, // minSeqAge or minSeqLedgerGap conditions not met
//        txMALFORMED = -16 // precondition is invalid
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum TransactionResultCode {
    TxFeeBumpInnerSuccess = 1,
    TxSuccess = 0,
    TxFailed = -1,
    TxTooEarly = -2,
    TxTooLate = -3,
    TxMissingOperation = -4,
    TxBadSeq = -5,
    TxBadAuth = -6,
    TxInsufficientBalance = -7,
    TxNoAccount = -8,
    TxInsufficientFee = -9,
    TxBadAuthExtra = -10,
    TxInternalError = -11,
    TxNotSupported = -12,
    TxFeeBumpInnerFailed = -13,
    TxBadSponsorship = -14,
    TxBadMinSeqAgeOrGap = -15,
    TxMalformed = -16,
}

impl TransactionResultCode {
    pub const VARIANTS: [TransactionResultCode; 18] = [
        TransactionResultCode::TxFeeBumpInnerSuccess,
        TransactionResultCode::TxSuccess,
        TransactionResultCode::TxFailed,
        TransactionResultCode::TxTooEarly,
        TransactionResultCode::TxTooLate,
        TransactionResultCode::TxMissingOperation,
        TransactionResultCode::TxBadSeq,
        TransactionResultCode::TxBadAuth,
        TransactionResultCode::TxInsufficientBalance,
        TransactionResultCode::TxNoAccount,
        TransactionResultCode::TxInsufficientFee,
        TransactionResultCode::TxBadAuthExtra,
        TransactionResultCode::TxInternalError,
        TransactionResultCode::TxNotSupported,
        TransactionResultCode::TxFeeBumpInnerFailed,
        TransactionResultCode::TxBadSponsorship,
        TransactionResultCode::TxBadMinSeqAgeOrGap,
        TransactionResultCode::TxMalformed,
    ];
    pub const VARIANTS_STR: [&'static str; 18] = [
        "TxFeeBumpInnerSuccess",
        "TxSuccess",
        "TxFailed",
        "TxTooEarly",
        "TxTooLate",
        "TxMissingOperation",
        "TxBadSeq",
        "TxBadAuth",
        "TxInsufficientBalance",
        "TxNoAccount",
        "TxInsufficientFee",
        "TxBadAuthExtra",
        "TxInternalError",
        "TxNotSupported",
        "TxFeeBumpInnerFailed",
        "TxBadSponsorship",
        "TxBadMinSeqAgeOrGap",
        "TxMalformed",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::TxFeeBumpInnerSuccess => "TxFeeBumpInnerSuccess",
            Self::TxSuccess => "TxSuccess",
            Self::TxFailed => "TxFailed",
            Self::TxTooEarly => "TxTooEarly",
            Self::TxTooLate => "TxTooLate",
            Self::TxMissingOperation => "TxMissingOperation",
            Self::TxBadSeq => "TxBadSeq",
            Self::TxBadAuth => "TxBadAuth",
            Self::TxInsufficientBalance => "TxInsufficientBalance",
            Self::TxNoAccount => "TxNoAccount",
            Self::TxInsufficientFee => "TxInsufficientFee",
            Self::TxBadAuthExtra => "TxBadAuthExtra",
            Self::TxInternalError => "TxInternalError",
            Self::TxNotSupported => "TxNotSupported",
            Self::TxFeeBumpInnerFailed => "TxFeeBumpInnerFailed",
            Self::TxBadSponsorship => "TxBadSponsorship",
            Self::TxBadMinSeqAgeOrGap => "TxBadMinSeqAgeOrGap",
            Self::TxMalformed => "TxMalformed",
        }
    }

    #[must_use]
    pub const fn variants() -> [TransactionResultCode; 18] {
        Self::VARIANTS
    }
}

impl Name for TransactionResultCode {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<TransactionResultCode> for TransactionResultCode {
    fn variants() -> slice::Iter<'static, TransactionResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Enum for TransactionResultCode {}

impl fmt::Display for TransactionResultCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for TransactionResultCode {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            1 => TransactionResultCode::TxFeeBumpInnerSuccess,
            0 => TransactionResultCode::TxSuccess,
            -1 => TransactionResultCode::TxFailed,
            -2 => TransactionResultCode::TxTooEarly,
            -3 => TransactionResultCode::TxTooLate,
            -4 => TransactionResultCode::TxMissingOperation,
            -5 => TransactionResultCode::TxBadSeq,
            -6 => TransactionResultCode::TxBadAuth,
            -7 => TransactionResultCode::TxInsufficientBalance,
            -8 => TransactionResultCode::TxNoAccount,
            -9 => TransactionResultCode::TxInsufficientFee,
            -10 => TransactionResultCode::TxBadAuthExtra,
            -11 => TransactionResultCode::TxInternalError,
            -12 => TransactionResultCode::TxNotSupported,
            -13 => TransactionResultCode::TxFeeBumpInnerFailed,
            -14 => TransactionResultCode::TxBadSponsorship,
            -15 => TransactionResultCode::TxBadMinSeqAgeOrGap,
            -16 => TransactionResultCode::TxMalformed,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<TransactionResultCode> for i32 {
    #[must_use]
    fn from(e: TransactionResultCode) -> Self {
        e as Self
    }
}

impl ReadXdr for TransactionResultCode {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for TransactionResultCode {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// InnerTransactionResultResult is an XDR NestedUnion defines as:
//
//   union switch (TransactionResultCode code)
//        {
//        // txFEE_BUMP_INNER_SUCCESS is not included
//        case txSUCCESS:
//        case txFAILED:
//            OperationResult results<>;
//        case txTOO_EARLY:
//        case txTOO_LATE:
//        case txMISSING_OPERATION:
//        case txBAD_SEQ:
//        case txBAD_AUTH:
//        case txINSUFFICIENT_BALANCE:
//        case txNO_ACCOUNT:
//        case txINSUFFICIENT_FEE:
//        case txBAD_AUTH_EXTRA:
//        case txINTERNAL_ERROR:
//        case txNOT_SUPPORTED:
//        // txFEE_BUMP_INNER_FAILED is not included
//        case txBAD_SPONSORSHIP:
//        case txBAD_MIN_SEQ_AGE_OR_GAP:
//        case txMALFORMED:
//            void;
//        }
//
// union with discriminant TransactionResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum InnerTransactionResultResult {
    TxSuccess(VecM<OperationResult>),
    TxFailed(VecM<OperationResult>),
    TxTooEarly,
    TxTooLate,
    TxMissingOperation,
    TxBadSeq,
    TxBadAuth,
    TxInsufficientBalance,
    TxNoAccount,
    TxInsufficientFee,
    TxBadAuthExtra,
    TxInternalError,
    TxNotSupported,
    TxBadSponsorship,
    TxBadMinSeqAgeOrGap,
    TxMalformed,
}

impl InnerTransactionResultResult {
    pub const VARIANTS: [TransactionResultCode; 16] = [
        TransactionResultCode::TxSuccess,
        TransactionResultCode::TxFailed,
        TransactionResultCode::TxTooEarly,
        TransactionResultCode::TxTooLate,
        TransactionResultCode::TxMissingOperation,
        TransactionResultCode::TxBadSeq,
        TransactionResultCode::TxBadAuth,
        TransactionResultCode::TxInsufficientBalance,
        TransactionResultCode::TxNoAccount,
        TransactionResultCode::TxInsufficientFee,
        TransactionResultCode::TxBadAuthExtra,
        TransactionResultCode::TxInternalError,
        TransactionResultCode::TxNotSupported,
        TransactionResultCode::TxBadSponsorship,
        TransactionResultCode::TxBadMinSeqAgeOrGap,
        TransactionResultCode::TxMalformed,
    ];
    pub const VARIANTS_STR: [&'static str; 16] = [
        "TxSuccess",
        "TxFailed",
        "TxTooEarly",
        "TxTooLate",
        "TxMissingOperation",
        "TxBadSeq",
        "TxBadAuth",
        "TxInsufficientBalance",
        "TxNoAccount",
        "TxInsufficientFee",
        "TxBadAuthExtra",
        "TxInternalError",
        "TxNotSupported",
        "TxBadSponsorship",
        "TxBadMinSeqAgeOrGap",
        "TxMalformed",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::TxSuccess(_) => "TxSuccess",
            Self::TxFailed(_) => "TxFailed",
            Self::TxTooEarly => "TxTooEarly",
            Self::TxTooLate => "TxTooLate",
            Self::TxMissingOperation => "TxMissingOperation",
            Self::TxBadSeq => "TxBadSeq",
            Self::TxBadAuth => "TxBadAuth",
            Self::TxInsufficientBalance => "TxInsufficientBalance",
            Self::TxNoAccount => "TxNoAccount",
            Self::TxInsufficientFee => "TxInsufficientFee",
            Self::TxBadAuthExtra => "TxBadAuthExtra",
            Self::TxInternalError => "TxInternalError",
            Self::TxNotSupported => "TxNotSupported",
            Self::TxBadSponsorship => "TxBadSponsorship",
            Self::TxBadMinSeqAgeOrGap => "TxBadMinSeqAgeOrGap",
            Self::TxMalformed => "TxMalformed",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> TransactionResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::TxSuccess(_) => TransactionResultCode::TxSuccess,
            Self::TxFailed(_) => TransactionResultCode::TxFailed,
            Self::TxTooEarly => TransactionResultCode::TxTooEarly,
            Self::TxTooLate => TransactionResultCode::TxTooLate,
            Self::TxMissingOperation => TransactionResultCode::TxMissingOperation,
            Self::TxBadSeq => TransactionResultCode::TxBadSeq,
            Self::TxBadAuth => TransactionResultCode::TxBadAuth,
            Self::TxInsufficientBalance => TransactionResultCode::TxInsufficientBalance,
            Self::TxNoAccount => TransactionResultCode::TxNoAccount,
            Self::TxInsufficientFee => TransactionResultCode::TxInsufficientFee,
            Self::TxBadAuthExtra => TransactionResultCode::TxBadAuthExtra,
            Self::TxInternalError => TransactionResultCode::TxInternalError,
            Self::TxNotSupported => TransactionResultCode::TxNotSupported,
            Self::TxBadSponsorship => TransactionResultCode::TxBadSponsorship,
            Self::TxBadMinSeqAgeOrGap => TransactionResultCode::TxBadMinSeqAgeOrGap,
            Self::TxMalformed => TransactionResultCode::TxMalformed,
        }
    }

    #[must_use]
    pub const fn variants() -> [TransactionResultCode; 16] {
        Self::VARIANTS
    }
}

impl Name for InnerTransactionResultResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<TransactionResultCode> for InnerTransactionResultResult {
    #[must_use]
    fn discriminant(&self) -> TransactionResultCode {
        Self::discriminant(self)
    }
}

impl Variants<TransactionResultCode> for InnerTransactionResultResult {
    fn variants() -> slice::Iter<'static, TransactionResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<TransactionResultCode> for InnerTransactionResultResult {}

impl ReadXdr for InnerTransactionResultResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: TransactionResultCode = <TransactionResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            TransactionResultCode::TxSuccess => {
                Self::TxSuccess(VecM::<OperationResult>::read_xdr(r)?)
            }
            TransactionResultCode::TxFailed => {
                Self::TxFailed(VecM::<OperationResult>::read_xdr(r)?)
            }
            TransactionResultCode::TxTooEarly => Self::TxTooEarly,
            TransactionResultCode::TxTooLate => Self::TxTooLate,
            TransactionResultCode::TxMissingOperation => Self::TxMissingOperation,
            TransactionResultCode::TxBadSeq => Self::TxBadSeq,
            TransactionResultCode::TxBadAuth => Self::TxBadAuth,
            TransactionResultCode::TxInsufficientBalance => Self::TxInsufficientBalance,
            TransactionResultCode::TxNoAccount => Self::TxNoAccount,
            TransactionResultCode::TxInsufficientFee => Self::TxInsufficientFee,
            TransactionResultCode::TxBadAuthExtra => Self::TxBadAuthExtra,
            TransactionResultCode::TxInternalError => Self::TxInternalError,
            TransactionResultCode::TxNotSupported => Self::TxNotSupported,
            TransactionResultCode::TxBadSponsorship => Self::TxBadSponsorship,
            TransactionResultCode::TxBadMinSeqAgeOrGap => Self::TxBadMinSeqAgeOrGap,
            TransactionResultCode::TxMalformed => Self::TxMalformed,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for InnerTransactionResultResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::TxSuccess(v) => v.write_xdr(w)?,
            Self::TxFailed(v) => v.write_xdr(w)?,
            Self::TxTooEarly => ().write_xdr(w)?,
            Self::TxTooLate => ().write_xdr(w)?,
            Self::TxMissingOperation => ().write_xdr(w)?,
            Self::TxBadSeq => ().write_xdr(w)?,
            Self::TxBadAuth => ().write_xdr(w)?,
            Self::TxInsufficientBalance => ().write_xdr(w)?,
            Self::TxNoAccount => ().write_xdr(w)?,
            Self::TxInsufficientFee => ().write_xdr(w)?,
            Self::TxBadAuthExtra => ().write_xdr(w)?,
            Self::TxInternalError => ().write_xdr(w)?,
            Self::TxNotSupported => ().write_xdr(w)?,
            Self::TxBadSponsorship => ().write_xdr(w)?,
            Self::TxBadMinSeqAgeOrGap => ().write_xdr(w)?,
            Self::TxMalformed => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// InnerTransactionResultExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum InnerTransactionResultExt {
    V0,
}

impl InnerTransactionResultExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for InnerTransactionResultExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for InnerTransactionResultExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for InnerTransactionResultExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for InnerTransactionResultExt {}

impl ReadXdr for InnerTransactionResultExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for InnerTransactionResultExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// InnerTransactionResult is an XDR Struct defines as:
//
//   struct InnerTransactionResult
//    {
//        // Always 0. Here for binary compatibility.
//        int64 feeCharged;
//
//        union switch (TransactionResultCode code)
//        {
//        // txFEE_BUMP_INNER_SUCCESS is not included
//        case txSUCCESS:
//        case txFAILED:
//            OperationResult results<>;
//        case txTOO_EARLY:
//        case txTOO_LATE:
//        case txMISSING_OPERATION:
//        case txBAD_SEQ:
//        case txBAD_AUTH:
//        case txINSUFFICIENT_BALANCE:
//        case txNO_ACCOUNT:
//        case txINSUFFICIENT_FEE:
//        case txBAD_AUTH_EXTRA:
//        case txINTERNAL_ERROR:
//        case txNOT_SUPPORTED:
//        // txFEE_BUMP_INNER_FAILED is not included
//        case txBAD_SPONSORSHIP:
//        case txBAD_MIN_SEQ_AGE_OR_GAP:
//        case txMALFORMED:
//            void;
//        }
//        result;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct InnerTransactionResult {
    pub fee_charged: i64,
    pub result: InnerTransactionResultResult,
    pub ext: InnerTransactionResultExt,
}

impl ReadXdr for InnerTransactionResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            fee_charged: i64::read_xdr(r)?,
            result: InnerTransactionResultResult::read_xdr(r)?,
            ext: InnerTransactionResultExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for InnerTransactionResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.fee_charged.write_xdr(w)?;
        self.result.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// InnerTransactionResultPair is an XDR Struct defines as:
//
//   struct InnerTransactionResultPair
//    {
//        Hash transactionHash;          // hash of the inner transaction
//        InnerTransactionResult result; // result for the inner transaction
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct InnerTransactionResultPair {
    pub transaction_hash: Hash,
    pub result: InnerTransactionResult,
}

impl ReadXdr for InnerTransactionResultPair {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            transaction_hash: Hash::read_xdr(r)?,
            result: InnerTransactionResult::read_xdr(r)?,
        })
    }
}

impl WriteXdr for InnerTransactionResultPair {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.transaction_hash.write_xdr(w)?;
        self.result.write_xdr(w)?;
        Ok(())
    }
}

// TransactionResultResult is an XDR NestedUnion defines as:
//
//   union switch (TransactionResultCode code)
//        {
//        case txFEE_BUMP_INNER_SUCCESS:
//        case txFEE_BUMP_INNER_FAILED:
//            InnerTransactionResultPair innerResultPair;
//        case txSUCCESS:
//        case txFAILED:
//            OperationResult results<>;
//        case txTOO_EARLY:
//        case txTOO_LATE:
//        case txMISSING_OPERATION:
//        case txBAD_SEQ:
//        case txBAD_AUTH:
//        case txINSUFFICIENT_BALANCE:
//        case txNO_ACCOUNT:
//        case txINSUFFICIENT_FEE:
//        case txBAD_AUTH_EXTRA:
//        case txINTERNAL_ERROR:
//        case txNOT_SUPPORTED:
//        // case txFEE_BUMP_INNER_FAILED: handled above
//        case txBAD_SPONSORSHIP:
//        case txBAD_MIN_SEQ_AGE_OR_GAP:
//        case txMALFORMED:
//            void;
//        }
//
// union with discriminant TransactionResultCode
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionResultResult {
    TxFeeBumpInnerSuccess(InnerTransactionResultPair),
    TxFeeBumpInnerFailed(InnerTransactionResultPair),
    TxSuccess(VecM<OperationResult>),
    TxFailed(VecM<OperationResult>),
    TxTooEarly,
    TxTooLate,
    TxMissingOperation,
    TxBadSeq,
    TxBadAuth,
    TxInsufficientBalance,
    TxNoAccount,
    TxInsufficientFee,
    TxBadAuthExtra,
    TxInternalError,
    TxNotSupported,
    TxBadSponsorship,
    TxBadMinSeqAgeOrGap,
    TxMalformed,
}

impl TransactionResultResult {
    pub const VARIANTS: [TransactionResultCode; 18] = [
        TransactionResultCode::TxFeeBumpInnerSuccess,
        TransactionResultCode::TxFeeBumpInnerFailed,
        TransactionResultCode::TxSuccess,
        TransactionResultCode::TxFailed,
        TransactionResultCode::TxTooEarly,
        TransactionResultCode::TxTooLate,
        TransactionResultCode::TxMissingOperation,
        TransactionResultCode::TxBadSeq,
        TransactionResultCode::TxBadAuth,
        TransactionResultCode::TxInsufficientBalance,
        TransactionResultCode::TxNoAccount,
        TransactionResultCode::TxInsufficientFee,
        TransactionResultCode::TxBadAuthExtra,
        TransactionResultCode::TxInternalError,
        TransactionResultCode::TxNotSupported,
        TransactionResultCode::TxBadSponsorship,
        TransactionResultCode::TxBadMinSeqAgeOrGap,
        TransactionResultCode::TxMalformed,
    ];
    pub const VARIANTS_STR: [&'static str; 18] = [
        "TxFeeBumpInnerSuccess",
        "TxFeeBumpInnerFailed",
        "TxSuccess",
        "TxFailed",
        "TxTooEarly",
        "TxTooLate",
        "TxMissingOperation",
        "TxBadSeq",
        "TxBadAuth",
        "TxInsufficientBalance",
        "TxNoAccount",
        "TxInsufficientFee",
        "TxBadAuthExtra",
        "TxInternalError",
        "TxNotSupported",
        "TxBadSponsorship",
        "TxBadMinSeqAgeOrGap",
        "TxMalformed",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::TxFeeBumpInnerSuccess(_) => "TxFeeBumpInnerSuccess",
            Self::TxFeeBumpInnerFailed(_) => "TxFeeBumpInnerFailed",
            Self::TxSuccess(_) => "TxSuccess",
            Self::TxFailed(_) => "TxFailed",
            Self::TxTooEarly => "TxTooEarly",
            Self::TxTooLate => "TxTooLate",
            Self::TxMissingOperation => "TxMissingOperation",
            Self::TxBadSeq => "TxBadSeq",
            Self::TxBadAuth => "TxBadAuth",
            Self::TxInsufficientBalance => "TxInsufficientBalance",
            Self::TxNoAccount => "TxNoAccount",
            Self::TxInsufficientFee => "TxInsufficientFee",
            Self::TxBadAuthExtra => "TxBadAuthExtra",
            Self::TxInternalError => "TxInternalError",
            Self::TxNotSupported => "TxNotSupported",
            Self::TxBadSponsorship => "TxBadSponsorship",
            Self::TxBadMinSeqAgeOrGap => "TxBadMinSeqAgeOrGap",
            Self::TxMalformed => "TxMalformed",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> TransactionResultCode {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::TxFeeBumpInnerSuccess(_) => TransactionResultCode::TxFeeBumpInnerSuccess,
            Self::TxFeeBumpInnerFailed(_) => TransactionResultCode::TxFeeBumpInnerFailed,
            Self::TxSuccess(_) => TransactionResultCode::TxSuccess,
            Self::TxFailed(_) => TransactionResultCode::TxFailed,
            Self::TxTooEarly => TransactionResultCode::TxTooEarly,
            Self::TxTooLate => TransactionResultCode::TxTooLate,
            Self::TxMissingOperation => TransactionResultCode::TxMissingOperation,
            Self::TxBadSeq => TransactionResultCode::TxBadSeq,
            Self::TxBadAuth => TransactionResultCode::TxBadAuth,
            Self::TxInsufficientBalance => TransactionResultCode::TxInsufficientBalance,
            Self::TxNoAccount => TransactionResultCode::TxNoAccount,
            Self::TxInsufficientFee => TransactionResultCode::TxInsufficientFee,
            Self::TxBadAuthExtra => TransactionResultCode::TxBadAuthExtra,
            Self::TxInternalError => TransactionResultCode::TxInternalError,
            Self::TxNotSupported => TransactionResultCode::TxNotSupported,
            Self::TxBadSponsorship => TransactionResultCode::TxBadSponsorship,
            Self::TxBadMinSeqAgeOrGap => TransactionResultCode::TxBadMinSeqAgeOrGap,
            Self::TxMalformed => TransactionResultCode::TxMalformed,
        }
    }

    #[must_use]
    pub const fn variants() -> [TransactionResultCode; 18] {
        Self::VARIANTS
    }
}

impl Name for TransactionResultResult {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<TransactionResultCode> for TransactionResultResult {
    #[must_use]
    fn discriminant(&self) -> TransactionResultCode {
        Self::discriminant(self)
    }
}

impl Variants<TransactionResultCode> for TransactionResultResult {
    fn variants() -> slice::Iter<'static, TransactionResultCode> {
        Self::VARIANTS.iter()
    }
}

impl Union<TransactionResultCode> for TransactionResultResult {}

impl ReadXdr for TransactionResultResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: TransactionResultCode = <TransactionResultCode as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            TransactionResultCode::TxFeeBumpInnerSuccess => {
                Self::TxFeeBumpInnerSuccess(InnerTransactionResultPair::read_xdr(r)?)
            }
            TransactionResultCode::TxFeeBumpInnerFailed => {
                Self::TxFeeBumpInnerFailed(InnerTransactionResultPair::read_xdr(r)?)
            }
            TransactionResultCode::TxSuccess => {
                Self::TxSuccess(VecM::<OperationResult>::read_xdr(r)?)
            }
            TransactionResultCode::TxFailed => {
                Self::TxFailed(VecM::<OperationResult>::read_xdr(r)?)
            }
            TransactionResultCode::TxTooEarly => Self::TxTooEarly,
            TransactionResultCode::TxTooLate => Self::TxTooLate,
            TransactionResultCode::TxMissingOperation => Self::TxMissingOperation,
            TransactionResultCode::TxBadSeq => Self::TxBadSeq,
            TransactionResultCode::TxBadAuth => Self::TxBadAuth,
            TransactionResultCode::TxInsufficientBalance => Self::TxInsufficientBalance,
            TransactionResultCode::TxNoAccount => Self::TxNoAccount,
            TransactionResultCode::TxInsufficientFee => Self::TxInsufficientFee,
            TransactionResultCode::TxBadAuthExtra => Self::TxBadAuthExtra,
            TransactionResultCode::TxInternalError => Self::TxInternalError,
            TransactionResultCode::TxNotSupported => Self::TxNotSupported,
            TransactionResultCode::TxBadSponsorship => Self::TxBadSponsorship,
            TransactionResultCode::TxBadMinSeqAgeOrGap => Self::TxBadMinSeqAgeOrGap,
            TransactionResultCode::TxMalformed => Self::TxMalformed,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionResultResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::TxFeeBumpInnerSuccess(v) => v.write_xdr(w)?,
            Self::TxFeeBumpInnerFailed(v) => v.write_xdr(w)?,
            Self::TxSuccess(v) => v.write_xdr(w)?,
            Self::TxFailed(v) => v.write_xdr(w)?,
            Self::TxTooEarly => ().write_xdr(w)?,
            Self::TxTooLate => ().write_xdr(w)?,
            Self::TxMissingOperation => ().write_xdr(w)?,
            Self::TxBadSeq => ().write_xdr(w)?,
            Self::TxBadAuth => ().write_xdr(w)?,
            Self::TxInsufficientBalance => ().write_xdr(w)?,
            Self::TxNoAccount => ().write_xdr(w)?,
            Self::TxInsufficientFee => ().write_xdr(w)?,
            Self::TxBadAuthExtra => ().write_xdr(w)?,
            Self::TxInternalError => ().write_xdr(w)?,
            Self::TxNotSupported => ().write_xdr(w)?,
            Self::TxBadSponsorship => ().write_xdr(w)?,
            Self::TxBadMinSeqAgeOrGap => ().write_xdr(w)?,
            Self::TxMalformed => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionResultExt is an XDR NestedUnion defines as:
//
//   union switch (int v)
//        {
//        case 0:
//            void;
//        }
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionResultExt {
    V0,
}

impl TransactionResultExt {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for TransactionResultExt {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for TransactionResultExt {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for TransactionResultExt {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for TransactionResultExt {}

impl ReadXdr for TransactionResultExt {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for TransactionResultExt {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// TransactionResult is an XDR Struct defines as:
//
//   struct TransactionResult
//    {
//        int64 feeCharged; // actual fee charged for the transaction
//
//        union switch (TransactionResultCode code)
//        {
//        case txFEE_BUMP_INNER_SUCCESS:
//        case txFEE_BUMP_INNER_FAILED:
//            InnerTransactionResultPair innerResultPair;
//        case txSUCCESS:
//        case txFAILED:
//            OperationResult results<>;
//        case txTOO_EARLY:
//        case txTOO_LATE:
//        case txMISSING_OPERATION:
//        case txBAD_SEQ:
//        case txBAD_AUTH:
//        case txINSUFFICIENT_BALANCE:
//        case txNO_ACCOUNT:
//        case txINSUFFICIENT_FEE:
//        case txBAD_AUTH_EXTRA:
//        case txINTERNAL_ERROR:
//        case txNOT_SUPPORTED:
//        // case txFEE_BUMP_INNER_FAILED: handled above
//        case txBAD_SPONSORSHIP:
//        case txBAD_MIN_SEQ_AGE_OR_GAP:
//        case txMALFORMED:
//            void;
//        }
//        result;
//
//        // reserved for future use
//        union switch (int v)
//        {
//        case 0:
//            void;
//        }
//        ext;
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct TransactionResult {
    pub fee_charged: i64,
    pub result: TransactionResultResult,
    pub ext: TransactionResultExt,
}

impl ReadXdr for TransactionResult {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            fee_charged: i64::read_xdr(r)?,
            result: TransactionResultResult::read_xdr(r)?,
            ext: TransactionResultExt::read_xdr(r)?,
        })
    }
}

impl WriteXdr for TransactionResult {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.fee_charged.write_xdr(w)?;
        self.result.write_xdr(w)?;
        self.ext.write_xdr(w)?;
        Ok(())
    }
}

// Hash is an XDR Typedef defines as:
//
//   typedef opaque Hash[32];
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
)]
pub struct Hash(pub [u8; 32]);

impl core::fmt::Display for Hash {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        Ok(())
    }
}

impl core::fmt::Debug for Hash {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        write!(f, "Hash(")?;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        write!(f, ")")?;
        Ok(())
    }
}

#[cfg(feature = "alloc")]
impl core::str::FromStr for Hash {
    type Err = Error;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        hex::decode(s).map_err(|_| Error::InvalidHex)?.try_into()
    }
}
impl From<Hash> for [u8; 32] {
    #[must_use]
    fn from(x: Hash) -> Self {
        x.0
    }
}

impl From<[u8; 32]> for Hash {
    #[must_use]
    fn from(x: [u8; 32]) -> Self {
        Hash(x)
    }
}

impl AsRef<[u8; 32]> for Hash {
    #[must_use]
    fn as_ref(&self) -> &[u8; 32] {
        &self.0
    }
}

impl ReadXdr for Hash {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = <[u8; 32]>::read_xdr(r)?;
        let v = Hash(i);
        Ok(v)
    }
}

impl WriteXdr for Hash {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Hash {
    #[must_use]
    pub fn as_slice(&self) -> &[u8] {
        &self.0
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<Vec<u8>> for Hash {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for Hash {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

impl TryFrom<&[u8]> for Hash {
    type Error = Error;
    fn try_from(x: &[u8]) -> Result<Self> {
        Ok(Hash(x.try_into()?))
    }
}

impl AsRef<[u8]> for Hash {
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

// Uint256 is an XDR Typedef defines as:
//
//   typedef opaque uint256[32];
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
)]
pub struct Uint256(pub [u8; 32]);

impl core::fmt::Display for Uint256 {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        Ok(())
    }
}

impl core::fmt::Debug for Uint256 {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        write!(f, "Uint256(")?;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        write!(f, ")")?;
        Ok(())
    }
}

#[cfg(feature = "alloc")]
impl core::str::FromStr for Uint256 {
    type Err = Error;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        hex::decode(s).map_err(|_| Error::InvalidHex)?.try_into()
    }
}
impl From<Uint256> for [u8; 32] {
    #[must_use]
    fn from(x: Uint256) -> Self {
        x.0
    }
}

impl From<[u8; 32]> for Uint256 {
    #[must_use]
    fn from(x: [u8; 32]) -> Self {
        Uint256(x)
    }
}

impl AsRef<[u8; 32]> for Uint256 {
    #[must_use]
    fn as_ref(&self) -> &[u8; 32] {
        &self.0
    }
}

impl ReadXdr for Uint256 {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = <[u8; 32]>::read_xdr(r)?;
        let v = Uint256(i);
        Ok(v)
    }
}

impl WriteXdr for Uint256 {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Uint256 {
    #[must_use]
    pub fn as_slice(&self) -> &[u8] {
        &self.0
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<Vec<u8>> for Uint256 {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for Uint256 {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

impl TryFrom<&[u8]> for Uint256 {
    type Error = Error;
    fn try_from(x: &[u8]) -> Result<Self> {
        Ok(Uint256(x.try_into()?))
    }
}

impl AsRef<[u8]> for Uint256 {
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

// Uint32 is an XDR Typedef defines as:
//
//   typedef unsigned int uint32;
//
pub type Uint32 = u32;

// Int32 is an XDR Typedef defines as:
//
//   typedef int int32;
//
pub type Int32 = i32;

// Uint64 is an XDR Typedef defines as:
//
//   typedef unsigned hyper uint64;
//
pub type Uint64 = u64;

// Int64 is an XDR Typedef defines as:
//
//   typedef hyper int64;
//
pub type Int64 = i64;

// ExtensionPoint is an XDR Union defines as:
//
//   union ExtensionPoint switch (int v)
//    {
//    case 0:
//        void;
//    };
//
// union with discriminant i32
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum ExtensionPoint {
    V0,
}

impl ExtensionPoint {
    pub const VARIANTS: [i32; 1] = [0];
    pub const VARIANTS_STR: [&'static str; 1] = ["V0"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::V0 => "V0",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> i32 {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => 0,
        }
    }

    #[must_use]
    pub const fn variants() -> [i32; 1] {
        Self::VARIANTS
    }
}

impl Name for ExtensionPoint {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<i32> for ExtensionPoint {
    #[must_use]
    fn discriminant(&self) -> i32 {
        Self::discriminant(self)
    }
}

impl Variants<i32> for ExtensionPoint {
    fn variants() -> slice::Iter<'static, i32> {
        Self::VARIANTS.iter()
    }
}

impl Union<i32> for ExtensionPoint {}

impl ReadXdr for ExtensionPoint {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: i32 = <i32 as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            0 => Self::V0,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for ExtensionPoint {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::V0 => ().write_xdr(w)?,
        };
        Ok(())
    }
}

// CryptoKeyType is an XDR Enum defines as:
//
//   enum CryptoKeyType
//    {
//        KEY_TYPE_ED25519 = 0,
//        KEY_TYPE_PRE_AUTH_TX = 1,
//        KEY_TYPE_HASH_X = 2,
//        KEY_TYPE_ED25519_SIGNED_PAYLOAD = 3,
//        // MUXED enum values for supported type are derived from the enum values
//        // above by ORing them with 0x100
//        KEY_TYPE_MUXED_ED25519 = 0x100
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum CryptoKeyType {
    Ed25519 = 0,
    PreAuthTx = 1,
    HashX = 2,
    Ed25519SignedPayload = 3,
    MuxedEd25519 = 256,
}

impl CryptoKeyType {
    pub const VARIANTS: [CryptoKeyType; 5] = [
        CryptoKeyType::Ed25519,
        CryptoKeyType::PreAuthTx,
        CryptoKeyType::HashX,
        CryptoKeyType::Ed25519SignedPayload,
        CryptoKeyType::MuxedEd25519,
    ];
    pub const VARIANTS_STR: [&'static str; 5] = [
        "Ed25519",
        "PreAuthTx",
        "HashX",
        "Ed25519SignedPayload",
        "MuxedEd25519",
    ];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Ed25519 => "Ed25519",
            Self::PreAuthTx => "PreAuthTx",
            Self::HashX => "HashX",
            Self::Ed25519SignedPayload => "Ed25519SignedPayload",
            Self::MuxedEd25519 => "MuxedEd25519",
        }
    }

    #[must_use]
    pub const fn variants() -> [CryptoKeyType; 5] {
        Self::VARIANTS
    }
}

impl Name for CryptoKeyType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<CryptoKeyType> for CryptoKeyType {
    fn variants() -> slice::Iter<'static, CryptoKeyType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for CryptoKeyType {}

impl fmt::Display for CryptoKeyType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for CryptoKeyType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => CryptoKeyType::Ed25519,
            1 => CryptoKeyType::PreAuthTx,
            2 => CryptoKeyType::HashX,
            3 => CryptoKeyType::Ed25519SignedPayload,
            256 => CryptoKeyType::MuxedEd25519,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<CryptoKeyType> for i32 {
    #[must_use]
    fn from(e: CryptoKeyType) -> Self {
        e as Self
    }
}

impl ReadXdr for CryptoKeyType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for CryptoKeyType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// PublicKeyType is an XDR Enum defines as:
//
//   enum PublicKeyType
//    {
//        PUBLIC_KEY_TYPE_ED25519 = KEY_TYPE_ED25519
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum PublicKeyType {
    PublicKeyTypeEd25519 = 0,
}

impl PublicKeyType {
    pub const VARIANTS: [PublicKeyType; 1] = [PublicKeyType::PublicKeyTypeEd25519];
    pub const VARIANTS_STR: [&'static str; 1] = ["PublicKeyTypeEd25519"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::PublicKeyTypeEd25519 => "PublicKeyTypeEd25519",
        }
    }

    #[must_use]
    pub const fn variants() -> [PublicKeyType; 1] {
        Self::VARIANTS
    }
}

impl Name for PublicKeyType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<PublicKeyType> for PublicKeyType {
    fn variants() -> slice::Iter<'static, PublicKeyType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for PublicKeyType {}

impl fmt::Display for PublicKeyType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for PublicKeyType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => PublicKeyType::PublicKeyTypeEd25519,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<PublicKeyType> for i32 {
    #[must_use]
    fn from(e: PublicKeyType) -> Self {
        e as Self
    }
}

impl ReadXdr for PublicKeyType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for PublicKeyType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// SignerKeyType is an XDR Enum defines as:
//
//   enum SignerKeyType
//    {
//        SIGNER_KEY_TYPE_ED25519 = KEY_TYPE_ED25519,
//        SIGNER_KEY_TYPE_PRE_AUTH_TX = KEY_TYPE_PRE_AUTH_TX,
//        SIGNER_KEY_TYPE_HASH_X = KEY_TYPE_HASH_X,
//        SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD = KEY_TYPE_ED25519_SIGNED_PAYLOAD
//    };
//
// enum
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[repr(i32)]
pub enum SignerKeyType {
    Ed25519 = 0,
    PreAuthTx = 1,
    HashX = 2,
    Ed25519SignedPayload = 3,
}

impl SignerKeyType {
    pub const VARIANTS: [SignerKeyType; 4] = [
        SignerKeyType::Ed25519,
        SignerKeyType::PreAuthTx,
        SignerKeyType::HashX,
        SignerKeyType::Ed25519SignedPayload,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Ed25519", "PreAuthTx", "HashX", "Ed25519SignedPayload"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Ed25519 => "Ed25519",
            Self::PreAuthTx => "PreAuthTx",
            Self::HashX => "HashX",
            Self::Ed25519SignedPayload => "Ed25519SignedPayload",
        }
    }

    #[must_use]
    pub const fn variants() -> [SignerKeyType; 4] {
        Self::VARIANTS
    }
}

impl Name for SignerKeyType {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<SignerKeyType> for SignerKeyType {
    fn variants() -> slice::Iter<'static, SignerKeyType> {
        Self::VARIANTS.iter()
    }
}

impl Enum for SignerKeyType {}

impl fmt::Display for SignerKeyType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name())
    }
}

impl TryFrom<i32> for SignerKeyType {
    type Error = Error;

    fn try_from(i: i32) -> Result<Self> {
        let e = match i {
            0 => SignerKeyType::Ed25519,
            1 => SignerKeyType::PreAuthTx,
            2 => SignerKeyType::HashX,
            3 => SignerKeyType::Ed25519SignedPayload,
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(e)
    }
}

impl From<SignerKeyType> for i32 {
    #[must_use]
    fn from(e: SignerKeyType) -> Self {
        e as Self
    }
}

impl ReadXdr for SignerKeyType {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let e = i32::read_xdr(r)?;
        let v: Self = e.try_into()?;
        Ok(v)
    }
}

impl WriteXdr for SignerKeyType {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        let i: i32 = (*self).into();
        i.write_xdr(w)
    }
}

// PublicKey is an XDR Union defines as:
//
//   union PublicKey switch (PublicKeyType type)
//    {
//    case PUBLIC_KEY_TYPE_ED25519:
//        uint256 ed25519;
//    };
//
// union with discriminant PublicKeyType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum PublicKey {
    PublicKeyTypeEd25519(Uint256),
}

impl PublicKey {
    pub const VARIANTS: [PublicKeyType; 1] = [PublicKeyType::PublicKeyTypeEd25519];
    pub const VARIANTS_STR: [&'static str; 1] = ["PublicKeyTypeEd25519"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::PublicKeyTypeEd25519(_) => "PublicKeyTypeEd25519",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> PublicKeyType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::PublicKeyTypeEd25519(_) => PublicKeyType::PublicKeyTypeEd25519,
        }
    }

    #[must_use]
    pub const fn variants() -> [PublicKeyType; 1] {
        Self::VARIANTS
    }
}

impl Name for PublicKey {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<PublicKeyType> for PublicKey {
    #[must_use]
    fn discriminant(&self) -> PublicKeyType {
        Self::discriminant(self)
    }
}

impl Variants<PublicKeyType> for PublicKey {
    fn variants() -> slice::Iter<'static, PublicKeyType> {
        Self::VARIANTS.iter()
    }
}

impl Union<PublicKeyType> for PublicKey {}

impl ReadXdr for PublicKey {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: PublicKeyType = <PublicKeyType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            PublicKeyType::PublicKeyTypeEd25519 => {
                Self::PublicKeyTypeEd25519(Uint256::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for PublicKey {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::PublicKeyTypeEd25519(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// SignerKeyEd25519SignedPayload is an XDR NestedStruct defines as:
//
//   struct
//        {
//            /* Public key that must sign the payload. */
//            uint256 ed25519;
//            /* Payload to be raw signed by ed25519. */
//            opaque payload<64>;
//        }
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct SignerKeyEd25519SignedPayload {
    pub ed25519: Uint256,
    pub payload: BytesM<64>,
}

impl ReadXdr for SignerKeyEd25519SignedPayload {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            ed25519: Uint256::read_xdr(r)?,
            payload: BytesM::<64>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for SignerKeyEd25519SignedPayload {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.ed25519.write_xdr(w)?;
        self.payload.write_xdr(w)?;
        Ok(())
    }
}

// SignerKey is an XDR Union defines as:
//
//   union SignerKey switch (SignerKeyType type)
//    {
//    case SIGNER_KEY_TYPE_ED25519:
//        uint256 ed25519;
//    case SIGNER_KEY_TYPE_PRE_AUTH_TX:
//        /* SHA-256 Hash of TransactionSignaturePayload structure */
//        uint256 preAuthTx;
//    case SIGNER_KEY_TYPE_HASH_X:
//        /* Hash of random 256 bit preimage X */
//        uint256 hashX;
//    case SIGNER_KEY_TYPE_ED25519_SIGNED_PAYLOAD:
//        struct
//        {
//            /* Public key that must sign the payload. */
//            uint256 ed25519;
//            /* Payload to be raw signed by ed25519. */
//            opaque payload<64>;
//        } ed25519SignedPayload;
//    };
//
// union with discriminant SignerKeyType
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
#[allow(clippy::large_enum_variant)]
pub enum SignerKey {
    Ed25519(Uint256),
    PreAuthTx(Uint256),
    HashX(Uint256),
    Ed25519SignedPayload(SignerKeyEd25519SignedPayload),
}

impl SignerKey {
    pub const VARIANTS: [SignerKeyType; 4] = [
        SignerKeyType::Ed25519,
        SignerKeyType::PreAuthTx,
        SignerKeyType::HashX,
        SignerKeyType::Ed25519SignedPayload,
    ];
    pub const VARIANTS_STR: [&'static str; 4] =
        ["Ed25519", "PreAuthTx", "HashX", "Ed25519SignedPayload"];

    #[must_use]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Ed25519(_) => "Ed25519",
            Self::PreAuthTx(_) => "PreAuthTx",
            Self::HashX(_) => "HashX",
            Self::Ed25519SignedPayload(_) => "Ed25519SignedPayload",
        }
    }

    #[must_use]
    pub const fn discriminant(&self) -> SignerKeyType {
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Ed25519(_) => SignerKeyType::Ed25519,
            Self::PreAuthTx(_) => SignerKeyType::PreAuthTx,
            Self::HashX(_) => SignerKeyType::HashX,
            Self::Ed25519SignedPayload(_) => SignerKeyType::Ed25519SignedPayload,
        }
    }

    #[must_use]
    pub const fn variants() -> [SignerKeyType; 4] {
        Self::VARIANTS
    }
}

impl Name for SignerKey {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Discriminant<SignerKeyType> for SignerKey {
    #[must_use]
    fn discriminant(&self) -> SignerKeyType {
        Self::discriminant(self)
    }
}

impl Variants<SignerKeyType> for SignerKey {
    fn variants() -> slice::Iter<'static, SignerKeyType> {
        Self::VARIANTS.iter()
    }
}

impl Union<SignerKeyType> for SignerKey {}

impl ReadXdr for SignerKey {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let dv: SignerKeyType = <SignerKeyType as ReadXdr>::read_xdr(r)?;
        #[allow(clippy::match_same_arms, clippy::match_wildcard_for_single_variants)]
        let v = match dv {
            SignerKeyType::Ed25519 => Self::Ed25519(Uint256::read_xdr(r)?),
            SignerKeyType::PreAuthTx => Self::PreAuthTx(Uint256::read_xdr(r)?),
            SignerKeyType::HashX => Self::HashX(Uint256::read_xdr(r)?),
            SignerKeyType::Ed25519SignedPayload => {
                Self::Ed25519SignedPayload(SignerKeyEd25519SignedPayload::read_xdr(r)?)
            }
            #[allow(unreachable_patterns)]
            _ => return Err(Error::Invalid),
        };
        Ok(v)
    }
}

impl WriteXdr for SignerKey {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.discriminant().write_xdr(w)?;
        #[allow(clippy::match_same_arms)]
        match self {
            Self::Ed25519(v) => v.write_xdr(w)?,
            Self::PreAuthTx(v) => v.write_xdr(w)?,
            Self::HashX(v) => v.write_xdr(w)?,
            Self::Ed25519SignedPayload(v) => v.write_xdr(w)?,
        };
        Ok(())
    }
}

// Signature is an XDR Typedef defines as:
//
//   typedef opaque Signature<64>;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Default, Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Signature(pub BytesM<64>);

impl From<Signature> for BytesM<64> {
    #[must_use]
    fn from(x: Signature) -> Self {
        x.0
    }
}

impl From<BytesM<64>> for Signature {
    #[must_use]
    fn from(x: BytesM<64>) -> Self {
        Signature(x)
    }
}

impl AsRef<BytesM<64>> for Signature {
    #[must_use]
    fn as_ref(&self) -> &BytesM<64> {
        &self.0
    }
}

impl ReadXdr for Signature {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = BytesM::<64>::read_xdr(r)?;
        let v = Signature(i);
        Ok(v)
    }
}

impl WriteXdr for Signature {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl Deref for Signature {
    type Target = BytesM<64>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<Signature> for Vec<u8> {
    #[must_use]
    fn from(x: Signature) -> Self {
        x.0 .0
    }
}

impl TryFrom<Vec<u8>> for Signature {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        Ok(Signature(x.try_into()?))
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for Signature {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        Ok(Signature(x.try_into()?))
    }
}

impl AsRef<Vec<u8>> for Signature {
    #[must_use]
    fn as_ref(&self) -> &Vec<u8> {
        &self.0 .0
    }
}

impl AsRef<[u8]> for Signature {
    #[cfg(feature = "alloc")]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0 .0
    }
    #[cfg(not(feature = "alloc"))]
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        self.0 .0
    }
}

// SignatureHint is an XDR Typedef defines as:
//
//   typedef opaque SignatureHint[4];
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde_with::SerializeDisplay, serde_with::DeserializeFromStr)
)]
pub struct SignatureHint(pub [u8; 4]);

impl core::fmt::Display for SignatureHint {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        Ok(())
    }
}

impl core::fmt::Debug for SignatureHint {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let v = &self.0;
        write!(f, "SignatureHint(")?;
        for b in v {
            write!(f, "{b:02x}")?;
        }
        write!(f, ")")?;
        Ok(())
    }
}

#[cfg(feature = "alloc")]
impl core::str::FromStr for SignatureHint {
    type Err = Error;
    fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
        hex::decode(s).map_err(|_| Error::InvalidHex)?.try_into()
    }
}
impl From<SignatureHint> for [u8; 4] {
    #[must_use]
    fn from(x: SignatureHint) -> Self {
        x.0
    }
}

impl From<[u8; 4]> for SignatureHint {
    #[must_use]
    fn from(x: [u8; 4]) -> Self {
        SignatureHint(x)
    }
}

impl AsRef<[u8; 4]> for SignatureHint {
    #[must_use]
    fn as_ref(&self) -> &[u8; 4] {
        &self.0
    }
}

impl ReadXdr for SignatureHint {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = <[u8; 4]>::read_xdr(r)?;
        let v = SignatureHint(i);
        Ok(v)
    }
}

impl WriteXdr for SignatureHint {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

impl SignatureHint {
    #[must_use]
    pub fn as_slice(&self) -> &[u8] {
        &self.0
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<Vec<u8>> for SignatureHint {
    type Error = Error;
    fn try_from(x: Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

#[cfg(feature = "alloc")]
impl TryFrom<&Vec<u8>> for SignatureHint {
    type Error = Error;
    fn try_from(x: &Vec<u8>) -> Result<Self> {
        x.as_slice().try_into()
    }
}

impl TryFrom<&[u8]> for SignatureHint {
    type Error = Error;
    fn try_from(x: &[u8]) -> Result<Self> {
        Ok(SignatureHint(x.try_into()?))
    }
}

impl AsRef<[u8]> for SignatureHint {
    #[must_use]
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

// NodeId is an XDR Typedef defines as:
//
//   typedef PublicKey NodeID;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct NodeId(pub PublicKey);

impl From<NodeId> for PublicKey {
    #[must_use]
    fn from(x: NodeId) -> Self {
        x.0
    }
}

impl From<PublicKey> for NodeId {
    #[must_use]
    fn from(x: PublicKey) -> Self {
        NodeId(x)
    }
}

impl AsRef<PublicKey> for NodeId {
    #[must_use]
    fn as_ref(&self) -> &PublicKey {
        &self.0
    }
}

impl ReadXdr for NodeId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = PublicKey::read_xdr(r)?;
        let v = NodeId(i);
        Ok(v)
    }
}

impl WriteXdr for NodeId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

// AccountId is an XDR Typedef defines as:
//
//   typedef PublicKey AccountID;
//
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[derive(Debug)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct AccountId(pub PublicKey);

impl From<AccountId> for PublicKey {
    #[must_use]
    fn from(x: AccountId) -> Self {
        x.0
    }
}

impl From<PublicKey> for AccountId {
    #[must_use]
    fn from(x: PublicKey) -> Self {
        AccountId(x)
    }
}

impl AsRef<PublicKey> for AccountId {
    #[must_use]
    fn as_ref(&self) -> &PublicKey {
        &self.0
    }
}

impl ReadXdr for AccountId {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        let i = PublicKey::read_xdr(r)?;
        let v = AccountId(i);
        Ok(v)
    }
}

impl WriteXdr for AccountId {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.0.write_xdr(w)
    }
}

// Curve25519Secret is an XDR Struct defines as:
//
//   struct Curve25519Secret
//    {
//        opaque key[32];
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Curve25519Secret {
    pub key: [u8; 32],
}

impl ReadXdr for Curve25519Secret {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            key: <[u8; 32]>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Curve25519Secret {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.key.write_xdr(w)?;
        Ok(())
    }
}

// Curve25519Public is an XDR Struct defines as:
//
//   struct Curve25519Public
//    {
//        opaque key[32];
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct Curve25519Public {
    pub key: [u8; 32],
}

impl ReadXdr for Curve25519Public {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            key: <[u8; 32]>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for Curve25519Public {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.key.write_xdr(w)?;
        Ok(())
    }
}

// HmacSha256Key is an XDR Struct defines as:
//
//   struct HmacSha256Key
//    {
//        opaque key[32];
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct HmacSha256Key {
    pub key: [u8; 32],
}

impl ReadXdr for HmacSha256Key {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            key: <[u8; 32]>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for HmacSha256Key {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.key.write_xdr(w)?;
        Ok(())
    }
}

// HmacSha256Mac is an XDR Struct defines as:
//
//   struct HmacSha256Mac
//    {
//        opaque mac[32];
//    };
//
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub struct HmacSha256Mac {
    pub mac: [u8; 32],
}

impl ReadXdr for HmacSha256Mac {
    #[cfg(feature = "std")]
    fn read_xdr(r: &mut impl Read) -> Result<Self> {
        Ok(Self {
            mac: <[u8; 32]>::read_xdr(r)?,
        })
    }
}

impl WriteXdr for HmacSha256Mac {
    #[cfg(feature = "std")]
    fn write_xdr(&self, w: &mut impl Write) -> Result<()> {
        self.mac.write_xdr(w)?;
        Ok(())
    }
}

#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case")
)]
pub enum TypeVariant {
    Value,
    ScpBallot,
    ScpStatementType,
    ScpNomination,
    ScpStatement,
    ScpStatementPledges,
    ScpStatementPrepare,
    ScpStatementConfirm,
    ScpStatementExternalize,
    ScpEnvelope,
    ScpQuorumSet,
    ScEnvMetaKind,
    ScEnvMetaEntry,
    ScSpecType,
    ScSpecTypeOption,
    ScSpecTypeResult,
    ScSpecTypeVec,
    ScSpecTypeMap,
    ScSpecTypeSet,
    ScSpecTypeTuple,
    ScSpecTypeBytesN,
    ScSpecTypeUdt,
    ScSpecTypeDef,
    ScSpecUdtStructFieldV0,
    ScSpecUdtStructV0,
    ScSpecUdtUnionCaseV0,
    ScSpecUdtUnionV0,
    ScSpecUdtEnumCaseV0,
    ScSpecUdtEnumV0,
    ScSpecUdtErrorEnumCaseV0,
    ScSpecUdtErrorEnumV0,
    ScSpecFunctionInputV0,
    ScSpecFunctionV0,
    ScSpecEntryKind,
    ScSpecEntry,
    ScSymbol,
    ScValType,
    ScStatic,
    ScStatusType,
    ScHostValErrorCode,
    ScHostObjErrorCode,
    ScHostFnErrorCode,
    ScHostStorageErrorCode,
    ScHostContextErrorCode,
    ScVmErrorCode,
    ScUnknownErrorCode,
    ScStatus,
    ScVal,
    ScObjectType,
    ScMapEntry,
    ScVec,
    ScMap,
    ScContractCodeType,
    ScContractCode,
    Int128Parts,
    ScObject,
    StoredTransactionSet,
    PersistedScpStateV0,
    PersistedScpStateV1,
    PersistedScpState,
    Thresholds,
    String32,
    String64,
    SequenceNumber,
    TimePoint,
    Duration,
    DataValue,
    PoolId,
    AssetCode4,
    AssetCode12,
    AssetType,
    AssetCode,
    AlphaNum4,
    AlphaNum12,
    Asset,
    Price,
    Liabilities,
    ThresholdIndexes,
    LedgerEntryType,
    Signer,
    AccountFlags,
    SponsorshipDescriptor,
    AccountEntryExtensionV3,
    AccountEntryExtensionV2,
    AccountEntryExtensionV2Ext,
    AccountEntryExtensionV1,
    AccountEntryExtensionV1Ext,
    AccountEntry,
    AccountEntryExt,
    TrustLineFlags,
    LiquidityPoolType,
    TrustLineAsset,
    TrustLineEntryExtensionV2,
    TrustLineEntryExtensionV2Ext,
    TrustLineEntry,
    TrustLineEntryExt,
    TrustLineEntryV1,
    TrustLineEntryV1Ext,
    OfferEntryFlags,
    OfferEntry,
    OfferEntryExt,
    DataEntry,
    DataEntryExt,
    ClaimPredicateType,
    ClaimPredicate,
    ClaimantType,
    Claimant,
    ClaimantV0,
    ClaimableBalanceIdType,
    ClaimableBalanceId,
    ClaimableBalanceFlags,
    ClaimableBalanceEntryExtensionV1,
    ClaimableBalanceEntryExtensionV1Ext,
    ClaimableBalanceEntry,
    ClaimableBalanceEntryExt,
    LiquidityPoolConstantProductParameters,
    LiquidityPoolEntry,
    LiquidityPoolEntryBody,
    LiquidityPoolEntryConstantProduct,
    ContractDataEntry,
    ContractCodeEntry,
    ConfigSettingType,
    ConfigSetting,
    ConfigSettingId,
    ConfigSettingEntry,
    ConfigSettingEntryExt,
    LedgerEntryExtensionV1,
    LedgerEntryExtensionV1Ext,
    LedgerEntry,
    LedgerEntryData,
    LedgerEntryExt,
    LedgerKey,
    LedgerKeyAccount,
    LedgerKeyTrustLine,
    LedgerKeyOffer,
    LedgerKeyData,
    LedgerKeyClaimableBalance,
    LedgerKeyLiquidityPool,
    LedgerKeyContractData,
    LedgerKeyContractCode,
    LedgerKeyConfigSetting,
    EnvelopeType,
    UpgradeType,
    StellarValueType,
    LedgerCloseValueSignature,
    StellarValue,
    StellarValueExt,
    LedgerHeaderFlags,
    LedgerHeaderExtensionV1,
    LedgerHeaderExtensionV1Ext,
    LedgerHeader,
    LedgerHeaderExt,
    LedgerUpgradeType,
    LedgerUpgrade,
    LedgerUpgradeConfigSetting,
    BucketEntryType,
    BucketMetadata,
    BucketMetadataExt,
    BucketEntry,
    TxSetComponentType,
    TxSetComponent,
    TxSetComponentTxsMaybeDiscountedFee,
    TransactionPhase,
    TransactionSet,
    TransactionSetV1,
    GeneralizedTransactionSet,
    TransactionResultPair,
    TransactionResultSet,
    TransactionHistoryEntry,
    TransactionHistoryEntryExt,
    TransactionHistoryResultEntry,
    TransactionHistoryResultEntryExt,
    TransactionResultPairV2,
    TransactionResultSetV2,
    TransactionHistoryResultEntryV2,
    TransactionHistoryResultEntryV2Ext,
    LedgerHeaderHistoryEntry,
    LedgerHeaderHistoryEntryExt,
    LedgerScpMessages,
    ScpHistoryEntryV0,
    ScpHistoryEntry,
    LedgerEntryChangeType,
    LedgerEntryChange,
    LedgerEntryChanges,
    OperationMeta,
    TransactionMetaV1,
    TransactionMetaV2,
    ContractEventType,
    ContractEvent,
    ContractEventBody,
    ContractEventV0,
    OperationEvents,
    TransactionMetaV3,
    TransactionMeta,
    TransactionResultMeta,
    TransactionResultMetaV2,
    UpgradeEntryMeta,
    LedgerCloseMetaV0,
    LedgerCloseMetaV1,
    LedgerCloseMetaV2,
    LedgerCloseMeta,
    ErrorCode,
    SError,
    SendMore,
    AuthCert,
    Hello,
    Auth,
    IpAddrType,
    PeerAddress,
    PeerAddressIp,
    MessageType,
    DontHave,
    SurveyMessageCommandType,
    SurveyRequestMessage,
    SignedSurveyRequestMessage,
    EncryptedBody,
    SurveyResponseMessage,
    SignedSurveyResponseMessage,
    PeerStats,
    PeerStatList,
    TopologyResponseBody,
    SurveyResponseBody,
    TxAdvertVector,
    FloodAdvert,
    TxDemandVector,
    FloodDemand,
    StellarMessage,
    AuthenticatedMessage,
    AuthenticatedMessageV0,
    LiquidityPoolParameters,
    MuxedAccount,
    MuxedAccountMed25519,
    DecoratedSignature,
    LedgerFootprint,
    OperationType,
    CreateAccountOp,
    PaymentOp,
    PathPaymentStrictReceiveOp,
    PathPaymentStrictSendOp,
    ManageSellOfferOp,
    ManageBuyOfferOp,
    CreatePassiveSellOfferOp,
    SetOptionsOp,
    ChangeTrustAsset,
    ChangeTrustOp,
    AllowTrustOp,
    ManageDataOp,
    BumpSequenceOp,
    CreateClaimableBalanceOp,
    ClaimClaimableBalanceOp,
    BeginSponsoringFutureReservesOp,
    RevokeSponsorshipType,
    RevokeSponsorshipOp,
    RevokeSponsorshipOpSigner,
    ClawbackOp,
    ClawbackClaimableBalanceOp,
    SetTrustLineFlagsOp,
    LiquidityPoolDepositOp,
    LiquidityPoolWithdrawOp,
    HostFunctionType,
    ContractIdType,
    ContractIdPublicKeyType,
    InstallContractCodeArgs,
    ContractId,
    ContractIdFromEd25519PublicKey,
    CreateContractArgs,
    HostFunction,
    InvokeHostFunctionOp,
    Operation,
    OperationBody,
    HashIdPreimage,
    HashIdPreimageOperationId,
    HashIdPreimageRevokeId,
    HashIdPreimageEd25519ContractId,
    HashIdPreimageContractId,
    HashIdPreimageFromAsset,
    HashIdPreimageSourceAccountContractId,
    HashIdPreimageCreateContractArgs,
    MemoType,
    Memo,
    TimeBounds,
    LedgerBounds,
    PreconditionsV2,
    PreconditionType,
    Preconditions,
    TransactionV0,
    TransactionV0Ext,
    TransactionV0Envelope,
    Transaction,
    TransactionExt,
    TransactionV1Envelope,
    FeeBumpTransaction,
    FeeBumpTransactionInnerTx,
    FeeBumpTransactionExt,
    FeeBumpTransactionEnvelope,
    TransactionEnvelope,
    TransactionSignaturePayload,
    TransactionSignaturePayloadTaggedTransaction,
    ClaimAtomType,
    ClaimOfferAtomV0,
    ClaimOfferAtom,
    ClaimLiquidityAtom,
    ClaimAtom,
    CreateAccountResultCode,
    CreateAccountResult,
    PaymentResultCode,
    PaymentResult,
    PathPaymentStrictReceiveResultCode,
    SimplePaymentResult,
    PathPaymentStrictReceiveResult,
    PathPaymentStrictReceiveResultSuccess,
    PathPaymentStrictSendResultCode,
    PathPaymentStrictSendResult,
    PathPaymentStrictSendResultSuccess,
    ManageSellOfferResultCode,
    ManageOfferEffect,
    ManageOfferSuccessResult,
    ManageOfferSuccessResultOffer,
    ManageSellOfferResult,
    ManageBuyOfferResultCode,
    ManageBuyOfferResult,
    SetOptionsResultCode,
    SetOptionsResult,
    ChangeTrustResultCode,
    ChangeTrustResult,
    AllowTrustResultCode,
    AllowTrustResult,
    AccountMergeResultCode,
    AccountMergeResult,
    InflationResultCode,
    InflationPayout,
    InflationResult,
    ManageDataResultCode,
    ManageDataResult,
    BumpSequenceResultCode,
    BumpSequenceResult,
    CreateClaimableBalanceResultCode,
    CreateClaimableBalanceResult,
    ClaimClaimableBalanceResultCode,
    ClaimClaimableBalanceResult,
    BeginSponsoringFutureReservesResultCode,
    BeginSponsoringFutureReservesResult,
    EndSponsoringFutureReservesResultCode,
    EndSponsoringFutureReservesResult,
    RevokeSponsorshipResultCode,
    RevokeSponsorshipResult,
    ClawbackResultCode,
    ClawbackResult,
    ClawbackClaimableBalanceResultCode,
    ClawbackClaimableBalanceResult,
    SetTrustLineFlagsResultCode,
    SetTrustLineFlagsResult,
    LiquidityPoolDepositResultCode,
    LiquidityPoolDepositResult,
    LiquidityPoolWithdrawResultCode,
    LiquidityPoolWithdrawResult,
    InvokeHostFunctionResultCode,
    InvokeHostFunctionResult,
    OperationResultCode,
    OperationResult,
    OperationResultTr,
    TransactionResultCode,
    InnerTransactionResult,
    InnerTransactionResultResult,
    InnerTransactionResultExt,
    InnerTransactionResultPair,
    TransactionResult,
    TransactionResultResult,
    TransactionResultExt,
    Hash,
    Uint256,
    Uint32,
    Int32,
    Uint64,
    Int64,
    ExtensionPoint,
    CryptoKeyType,
    PublicKeyType,
    SignerKeyType,
    PublicKey,
    SignerKey,
    SignerKeyEd25519SignedPayload,
    Signature,
    SignatureHint,
    NodeId,
    AccountId,
    Curve25519Secret,
    Curve25519Public,
    HmacSha256Key,
    HmacSha256Mac,
}

impl TypeVariant {
    pub const VARIANTS: [TypeVariant; 390] = [
        TypeVariant::Value,
        TypeVariant::ScpBallot,
        TypeVariant::ScpStatementType,
        TypeVariant::ScpNomination,
        TypeVariant::ScpStatement,
        TypeVariant::ScpStatementPledges,
        TypeVariant::ScpStatementPrepare,
        TypeVariant::ScpStatementConfirm,
        TypeVariant::ScpStatementExternalize,
        TypeVariant::ScpEnvelope,
        TypeVariant::ScpQuorumSet,
        TypeVariant::ScEnvMetaKind,
        TypeVariant::ScEnvMetaEntry,
        TypeVariant::ScSpecType,
        TypeVariant::ScSpecTypeOption,
        TypeVariant::ScSpecTypeResult,
        TypeVariant::ScSpecTypeVec,
        TypeVariant::ScSpecTypeMap,
        TypeVariant::ScSpecTypeSet,
        TypeVariant::ScSpecTypeTuple,
        TypeVariant::ScSpecTypeBytesN,
        TypeVariant::ScSpecTypeUdt,
        TypeVariant::ScSpecTypeDef,
        TypeVariant::ScSpecUdtStructFieldV0,
        TypeVariant::ScSpecUdtStructV0,
        TypeVariant::ScSpecUdtUnionCaseV0,
        TypeVariant::ScSpecUdtUnionV0,
        TypeVariant::ScSpecUdtEnumCaseV0,
        TypeVariant::ScSpecUdtEnumV0,
        TypeVariant::ScSpecUdtErrorEnumCaseV0,
        TypeVariant::ScSpecUdtErrorEnumV0,
        TypeVariant::ScSpecFunctionInputV0,
        TypeVariant::ScSpecFunctionV0,
        TypeVariant::ScSpecEntryKind,
        TypeVariant::ScSpecEntry,
        TypeVariant::ScSymbol,
        TypeVariant::ScValType,
        TypeVariant::ScStatic,
        TypeVariant::ScStatusType,
        TypeVariant::ScHostValErrorCode,
        TypeVariant::ScHostObjErrorCode,
        TypeVariant::ScHostFnErrorCode,
        TypeVariant::ScHostStorageErrorCode,
        TypeVariant::ScHostContextErrorCode,
        TypeVariant::ScVmErrorCode,
        TypeVariant::ScUnknownErrorCode,
        TypeVariant::ScStatus,
        TypeVariant::ScVal,
        TypeVariant::ScObjectType,
        TypeVariant::ScMapEntry,
        TypeVariant::ScVec,
        TypeVariant::ScMap,
        TypeVariant::ScContractCodeType,
        TypeVariant::ScContractCode,
        TypeVariant::Int128Parts,
        TypeVariant::ScObject,
        TypeVariant::StoredTransactionSet,
        TypeVariant::PersistedScpStateV0,
        TypeVariant::PersistedScpStateV1,
        TypeVariant::PersistedScpState,
        TypeVariant::Thresholds,
        TypeVariant::String32,
        TypeVariant::String64,
        TypeVariant::SequenceNumber,
        TypeVariant::TimePoint,
        TypeVariant::Duration,
        TypeVariant::DataValue,
        TypeVariant::PoolId,
        TypeVariant::AssetCode4,
        TypeVariant::AssetCode12,
        TypeVariant::AssetType,
        TypeVariant::AssetCode,
        TypeVariant::AlphaNum4,
        TypeVariant::AlphaNum12,
        TypeVariant::Asset,
        TypeVariant::Price,
        TypeVariant::Liabilities,
        TypeVariant::ThresholdIndexes,
        TypeVariant::LedgerEntryType,
        TypeVariant::Signer,
        TypeVariant::AccountFlags,
        TypeVariant::SponsorshipDescriptor,
        TypeVariant::AccountEntryExtensionV3,
        TypeVariant::AccountEntryExtensionV2,
        TypeVariant::AccountEntryExtensionV2Ext,
        TypeVariant::AccountEntryExtensionV1,
        TypeVariant::AccountEntryExtensionV1Ext,
        TypeVariant::AccountEntry,
        TypeVariant::AccountEntryExt,
        TypeVariant::TrustLineFlags,
        TypeVariant::LiquidityPoolType,
        TypeVariant::TrustLineAsset,
        TypeVariant::TrustLineEntryExtensionV2,
        TypeVariant::TrustLineEntryExtensionV2Ext,
        TypeVariant::TrustLineEntry,
        TypeVariant::TrustLineEntryExt,
        TypeVariant::TrustLineEntryV1,
        TypeVariant::TrustLineEntryV1Ext,
        TypeVariant::OfferEntryFlags,
        TypeVariant::OfferEntry,
        TypeVariant::OfferEntryExt,
        TypeVariant::DataEntry,
        TypeVariant::DataEntryExt,
        TypeVariant::ClaimPredicateType,
        TypeVariant::ClaimPredicate,
        TypeVariant::ClaimantType,
        TypeVariant::Claimant,
        TypeVariant::ClaimantV0,
        TypeVariant::ClaimableBalanceIdType,
        TypeVariant::ClaimableBalanceId,
        TypeVariant::ClaimableBalanceFlags,
        TypeVariant::ClaimableBalanceEntryExtensionV1,
        TypeVariant::ClaimableBalanceEntryExtensionV1Ext,
        TypeVariant::ClaimableBalanceEntry,
        TypeVariant::ClaimableBalanceEntryExt,
        TypeVariant::LiquidityPoolConstantProductParameters,
        TypeVariant::LiquidityPoolEntry,
        TypeVariant::LiquidityPoolEntryBody,
        TypeVariant::LiquidityPoolEntryConstantProduct,
        TypeVariant::ContractDataEntry,
        TypeVariant::ContractCodeEntry,
        TypeVariant::ConfigSettingType,
        TypeVariant::ConfigSetting,
        TypeVariant::ConfigSettingId,
        TypeVariant::ConfigSettingEntry,
        TypeVariant::ConfigSettingEntryExt,
        TypeVariant::LedgerEntryExtensionV1,
        TypeVariant::LedgerEntryExtensionV1Ext,
        TypeVariant::LedgerEntry,
        TypeVariant::LedgerEntryData,
        TypeVariant::LedgerEntryExt,
        TypeVariant::LedgerKey,
        TypeVariant::LedgerKeyAccount,
        TypeVariant::LedgerKeyTrustLine,
        TypeVariant::LedgerKeyOffer,
        TypeVariant::LedgerKeyData,
        TypeVariant::LedgerKeyClaimableBalance,
        TypeVariant::LedgerKeyLiquidityPool,
        TypeVariant::LedgerKeyContractData,
        TypeVariant::LedgerKeyContractCode,
        TypeVariant::LedgerKeyConfigSetting,
        TypeVariant::EnvelopeType,
        TypeVariant::UpgradeType,
        TypeVariant::StellarValueType,
        TypeVariant::LedgerCloseValueSignature,
        TypeVariant::StellarValue,
        TypeVariant::StellarValueExt,
        TypeVariant::LedgerHeaderFlags,
        TypeVariant::LedgerHeaderExtensionV1,
        TypeVariant::LedgerHeaderExtensionV1Ext,
        TypeVariant::LedgerHeader,
        TypeVariant::LedgerHeaderExt,
        TypeVariant::LedgerUpgradeType,
        TypeVariant::LedgerUpgrade,
        TypeVariant::LedgerUpgradeConfigSetting,
        TypeVariant::BucketEntryType,
        TypeVariant::BucketMetadata,
        TypeVariant::BucketMetadataExt,
        TypeVariant::BucketEntry,
        TypeVariant::TxSetComponentType,
        TypeVariant::TxSetComponent,
        TypeVariant::TxSetComponentTxsMaybeDiscountedFee,
        TypeVariant::TransactionPhase,
        TypeVariant::TransactionSet,
        TypeVariant::TransactionSetV1,
        TypeVariant::GeneralizedTransactionSet,
        TypeVariant::TransactionResultPair,
        TypeVariant::TransactionResultSet,
        TypeVariant::TransactionHistoryEntry,
        TypeVariant::TransactionHistoryEntryExt,
        TypeVariant::TransactionHistoryResultEntry,
        TypeVariant::TransactionHistoryResultEntryExt,
        TypeVariant::TransactionResultPairV2,
        TypeVariant::TransactionResultSetV2,
        TypeVariant::TransactionHistoryResultEntryV2,
        TypeVariant::TransactionHistoryResultEntryV2Ext,
        TypeVariant::LedgerHeaderHistoryEntry,
        TypeVariant::LedgerHeaderHistoryEntryExt,
        TypeVariant::LedgerScpMessages,
        TypeVariant::ScpHistoryEntryV0,
        TypeVariant::ScpHistoryEntry,
        TypeVariant::LedgerEntryChangeType,
        TypeVariant::LedgerEntryChange,
        TypeVariant::LedgerEntryChanges,
        TypeVariant::OperationMeta,
        TypeVariant::TransactionMetaV1,
        TypeVariant::TransactionMetaV2,
        TypeVariant::ContractEventType,
        TypeVariant::ContractEvent,
        TypeVariant::ContractEventBody,
        TypeVariant::ContractEventV0,
        TypeVariant::OperationEvents,
        TypeVariant::TransactionMetaV3,
        TypeVariant::TransactionMeta,
        TypeVariant::TransactionResultMeta,
        TypeVariant::TransactionResultMetaV2,
        TypeVariant::UpgradeEntryMeta,
        TypeVariant::LedgerCloseMetaV0,
        TypeVariant::LedgerCloseMetaV1,
        TypeVariant::LedgerCloseMetaV2,
        TypeVariant::LedgerCloseMeta,
        TypeVariant::ErrorCode,
        TypeVariant::SError,
        TypeVariant::SendMore,
        TypeVariant::AuthCert,
        TypeVariant::Hello,
        TypeVariant::Auth,
        TypeVariant::IpAddrType,
        TypeVariant::PeerAddress,
        TypeVariant::PeerAddressIp,
        TypeVariant::MessageType,
        TypeVariant::DontHave,
        TypeVariant::SurveyMessageCommandType,
        TypeVariant::SurveyRequestMessage,
        TypeVariant::SignedSurveyRequestMessage,
        TypeVariant::EncryptedBody,
        TypeVariant::SurveyResponseMessage,
        TypeVariant::SignedSurveyResponseMessage,
        TypeVariant::PeerStats,
        TypeVariant::PeerStatList,
        TypeVariant::TopologyResponseBody,
        TypeVariant::SurveyResponseBody,
        TypeVariant::TxAdvertVector,
        TypeVariant::FloodAdvert,
        TypeVariant::TxDemandVector,
        TypeVariant::FloodDemand,
        TypeVariant::StellarMessage,
        TypeVariant::AuthenticatedMessage,
        TypeVariant::AuthenticatedMessageV0,
        TypeVariant::LiquidityPoolParameters,
        TypeVariant::MuxedAccount,
        TypeVariant::MuxedAccountMed25519,
        TypeVariant::DecoratedSignature,
        TypeVariant::LedgerFootprint,
        TypeVariant::OperationType,
        TypeVariant::CreateAccountOp,
        TypeVariant::PaymentOp,
        TypeVariant::PathPaymentStrictReceiveOp,
        TypeVariant::PathPaymentStrictSendOp,
        TypeVariant::ManageSellOfferOp,
        TypeVariant::ManageBuyOfferOp,
        TypeVariant::CreatePassiveSellOfferOp,
        TypeVariant::SetOptionsOp,
        TypeVariant::ChangeTrustAsset,
        TypeVariant::ChangeTrustOp,
        TypeVariant::AllowTrustOp,
        TypeVariant::ManageDataOp,
        TypeVariant::BumpSequenceOp,
        TypeVariant::CreateClaimableBalanceOp,
        TypeVariant::ClaimClaimableBalanceOp,
        TypeVariant::BeginSponsoringFutureReservesOp,
        TypeVariant::RevokeSponsorshipType,
        TypeVariant::RevokeSponsorshipOp,
        TypeVariant::RevokeSponsorshipOpSigner,
        TypeVariant::ClawbackOp,
        TypeVariant::ClawbackClaimableBalanceOp,
        TypeVariant::SetTrustLineFlagsOp,
        TypeVariant::LiquidityPoolDepositOp,
        TypeVariant::LiquidityPoolWithdrawOp,
        TypeVariant::HostFunctionType,
        TypeVariant::ContractIdType,
        TypeVariant::ContractIdPublicKeyType,
        TypeVariant::InstallContractCodeArgs,
        TypeVariant::ContractId,
        TypeVariant::ContractIdFromEd25519PublicKey,
        TypeVariant::CreateContractArgs,
        TypeVariant::HostFunction,
        TypeVariant::InvokeHostFunctionOp,
        TypeVariant::Operation,
        TypeVariant::OperationBody,
        TypeVariant::HashIdPreimage,
        TypeVariant::HashIdPreimageOperationId,
        TypeVariant::HashIdPreimageRevokeId,
        TypeVariant::HashIdPreimageEd25519ContractId,
        TypeVariant::HashIdPreimageContractId,
        TypeVariant::HashIdPreimageFromAsset,
        TypeVariant::HashIdPreimageSourceAccountContractId,
        TypeVariant::HashIdPreimageCreateContractArgs,
        TypeVariant::MemoType,
        TypeVariant::Memo,
        TypeVariant::TimeBounds,
        TypeVariant::LedgerBounds,
        TypeVariant::PreconditionsV2,
        TypeVariant::PreconditionType,
        TypeVariant::Preconditions,
        TypeVariant::TransactionV0,
        TypeVariant::TransactionV0Ext,
        TypeVariant::TransactionV0Envelope,
        TypeVariant::Transaction,
        TypeVariant::TransactionExt,
        TypeVariant::TransactionV1Envelope,
        TypeVariant::FeeBumpTransaction,
        TypeVariant::FeeBumpTransactionInnerTx,
        TypeVariant::FeeBumpTransactionExt,
        TypeVariant::FeeBumpTransactionEnvelope,
        TypeVariant::TransactionEnvelope,
        TypeVariant::TransactionSignaturePayload,
        TypeVariant::TransactionSignaturePayloadTaggedTransaction,
        TypeVariant::ClaimAtomType,
        TypeVariant::ClaimOfferAtomV0,
        TypeVariant::ClaimOfferAtom,
        TypeVariant::ClaimLiquidityAtom,
        TypeVariant::ClaimAtom,
        TypeVariant::CreateAccountResultCode,
        TypeVariant::CreateAccountResult,
        TypeVariant::PaymentResultCode,
        TypeVariant::PaymentResult,
        TypeVariant::PathPaymentStrictReceiveResultCode,
        TypeVariant::SimplePaymentResult,
        TypeVariant::PathPaymentStrictReceiveResult,
        TypeVariant::PathPaymentStrictReceiveResultSuccess,
        TypeVariant::PathPaymentStrictSendResultCode,
        TypeVariant::PathPaymentStrictSendResult,
        TypeVariant::PathPaymentStrictSendResultSuccess,
        TypeVariant::ManageSellOfferResultCode,
        TypeVariant::ManageOfferEffect,
        TypeVariant::ManageOfferSuccessResult,
        TypeVariant::ManageOfferSuccessResultOffer,
        TypeVariant::ManageSellOfferResult,
        TypeVariant::ManageBuyOfferResultCode,
        TypeVariant::ManageBuyOfferResult,
        TypeVariant::SetOptionsResultCode,
        TypeVariant::SetOptionsResult,
        TypeVariant::ChangeTrustResultCode,
        TypeVariant::ChangeTrustResult,
        TypeVariant::AllowTrustResultCode,
        TypeVariant::AllowTrustResult,
        TypeVariant::AccountMergeResultCode,
        TypeVariant::AccountMergeResult,
        TypeVariant::InflationResultCode,
        TypeVariant::InflationPayout,
        TypeVariant::InflationResult,
        TypeVariant::ManageDataResultCode,
        TypeVariant::ManageDataResult,
        TypeVariant::BumpSequenceResultCode,
        TypeVariant::BumpSequenceResult,
        TypeVariant::CreateClaimableBalanceResultCode,
        TypeVariant::CreateClaimableBalanceResult,
        TypeVariant::ClaimClaimableBalanceResultCode,
        TypeVariant::ClaimClaimableBalanceResult,
        TypeVariant::BeginSponsoringFutureReservesResultCode,
        TypeVariant::BeginSponsoringFutureReservesResult,
        TypeVariant::EndSponsoringFutureReservesResultCode,
        TypeVariant::EndSponsoringFutureReservesResult,
        TypeVariant::RevokeSponsorshipResultCode,
        TypeVariant::RevokeSponsorshipResult,
        TypeVariant::ClawbackResultCode,
        TypeVariant::ClawbackResult,
        TypeVariant::ClawbackClaimableBalanceResultCode,
        TypeVariant::ClawbackClaimableBalanceResult,
        TypeVariant::SetTrustLineFlagsResultCode,
        TypeVariant::SetTrustLineFlagsResult,
        TypeVariant::LiquidityPoolDepositResultCode,
        TypeVariant::LiquidityPoolDepositResult,
        TypeVariant::LiquidityPoolWithdrawResultCode,
        TypeVariant::LiquidityPoolWithdrawResult,
        TypeVariant::InvokeHostFunctionResultCode,
        TypeVariant::InvokeHostFunctionResult,
        TypeVariant::OperationResultCode,
        TypeVariant::OperationResult,
        TypeVariant::OperationResultTr,
        TypeVariant::TransactionResultCode,
        TypeVariant::InnerTransactionResult,
        TypeVariant::InnerTransactionResultResult,
        TypeVariant::InnerTransactionResultExt,
        TypeVariant::InnerTransactionResultPair,
        TypeVariant::TransactionResult,
        TypeVariant::TransactionResultResult,
        TypeVariant::TransactionResultExt,
        TypeVariant::Hash,
        TypeVariant::Uint256,
        TypeVariant::Uint32,
        TypeVariant::Int32,
        TypeVariant::Uint64,
        TypeVariant::Int64,
        TypeVariant::ExtensionPoint,
        TypeVariant::CryptoKeyType,
        TypeVariant::PublicKeyType,
        TypeVariant::SignerKeyType,
        TypeVariant::PublicKey,
        TypeVariant::SignerKey,
        TypeVariant::SignerKeyEd25519SignedPayload,
        TypeVariant::Signature,
        TypeVariant::SignatureHint,
        TypeVariant::NodeId,
        TypeVariant::AccountId,
        TypeVariant::Curve25519Secret,
        TypeVariant::Curve25519Public,
        TypeVariant::HmacSha256Key,
        TypeVariant::HmacSha256Mac,
    ];
    pub const VARIANTS_STR: [&'static str; 390] = [
        "Value",
        "ScpBallot",
        "ScpStatementType",
        "ScpNomination",
        "ScpStatement",
        "ScpStatementPledges",
        "ScpStatementPrepare",
        "ScpStatementConfirm",
        "ScpStatementExternalize",
        "ScpEnvelope",
        "ScpQuorumSet",
        "ScEnvMetaKind",
        "ScEnvMetaEntry",
        "ScSpecType",
        "ScSpecTypeOption",
        "ScSpecTypeResult",
        "ScSpecTypeVec",
        "ScSpecTypeMap",
        "ScSpecTypeSet",
        "ScSpecTypeTuple",
        "ScSpecTypeBytesN",
        "ScSpecTypeUdt",
        "ScSpecTypeDef",
        "ScSpecUdtStructFieldV0",
        "ScSpecUdtStructV0",
        "ScSpecUdtUnionCaseV0",
        "ScSpecUdtUnionV0",
        "ScSpecUdtEnumCaseV0",
        "ScSpecUdtEnumV0",
        "ScSpecUdtErrorEnumCaseV0",
        "ScSpecUdtErrorEnumV0",
        "ScSpecFunctionInputV0",
        "ScSpecFunctionV0",
        "ScSpecEntryKind",
        "ScSpecEntry",
        "ScSymbol",
        "ScValType",
        "ScStatic",
        "ScStatusType",
        "ScHostValErrorCode",
        "ScHostObjErrorCode",
        "ScHostFnErrorCode",
        "ScHostStorageErrorCode",
        "ScHostContextErrorCode",
        "ScVmErrorCode",
        "ScUnknownErrorCode",
        "ScStatus",
        "ScVal",
        "ScObjectType",
        "ScMapEntry",
        "ScVec",
        "ScMap",
        "ScContractCodeType",
        "ScContractCode",
        "Int128Parts",
        "ScObject",
        "StoredTransactionSet",
        "PersistedScpStateV0",
        "PersistedScpStateV1",
        "PersistedScpState",
        "Thresholds",
        "String32",
        "String64",
        "SequenceNumber",
        "TimePoint",
        "Duration",
        "DataValue",
        "PoolId",
        "AssetCode4",
        "AssetCode12",
        "AssetType",
        "AssetCode",
        "AlphaNum4",
        "AlphaNum12",
        "Asset",
        "Price",
        "Liabilities",
        "ThresholdIndexes",
        "LedgerEntryType",
        "Signer",
        "AccountFlags",
        "SponsorshipDescriptor",
        "AccountEntryExtensionV3",
        "AccountEntryExtensionV2",
        "AccountEntryExtensionV2Ext",
        "AccountEntryExtensionV1",
        "AccountEntryExtensionV1Ext",
        "AccountEntry",
        "AccountEntryExt",
        "TrustLineFlags",
        "LiquidityPoolType",
        "TrustLineAsset",
        "TrustLineEntryExtensionV2",
        "TrustLineEntryExtensionV2Ext",
        "TrustLineEntry",
        "TrustLineEntryExt",
        "TrustLineEntryV1",
        "TrustLineEntryV1Ext",
        "OfferEntryFlags",
        "OfferEntry",
        "OfferEntryExt",
        "DataEntry",
        "DataEntryExt",
        "ClaimPredicateType",
        "ClaimPredicate",
        "ClaimantType",
        "Claimant",
        "ClaimantV0",
        "ClaimableBalanceIdType",
        "ClaimableBalanceId",
        "ClaimableBalanceFlags",
        "ClaimableBalanceEntryExtensionV1",
        "ClaimableBalanceEntryExtensionV1Ext",
        "ClaimableBalanceEntry",
        "ClaimableBalanceEntryExt",
        "LiquidityPoolConstantProductParameters",
        "LiquidityPoolEntry",
        "LiquidityPoolEntryBody",
        "LiquidityPoolEntryConstantProduct",
        "ContractDataEntry",
        "ContractCodeEntry",
        "ConfigSettingType",
        "ConfigSetting",
        "ConfigSettingId",
        "ConfigSettingEntry",
        "ConfigSettingEntryExt",
        "LedgerEntryExtensionV1",
        "LedgerEntryExtensionV1Ext",
        "LedgerEntry",
        "LedgerEntryData",
        "LedgerEntryExt",
        "LedgerKey",
        "LedgerKeyAccount",
        "LedgerKeyTrustLine",
        "LedgerKeyOffer",
        "LedgerKeyData",
        "LedgerKeyClaimableBalance",
        "LedgerKeyLiquidityPool",
        "LedgerKeyContractData",
        "LedgerKeyContractCode",
        "LedgerKeyConfigSetting",
        "EnvelopeType",
        "UpgradeType",
        "StellarValueType",
        "LedgerCloseValueSignature",
        "StellarValue",
        "StellarValueExt",
        "LedgerHeaderFlags",
        "LedgerHeaderExtensionV1",
        "LedgerHeaderExtensionV1Ext",
        "LedgerHeader",
        "LedgerHeaderExt",
        "LedgerUpgradeType",
        "LedgerUpgrade",
        "LedgerUpgradeConfigSetting",
        "BucketEntryType",
        "BucketMetadata",
        "BucketMetadataExt",
        "BucketEntry",
        "TxSetComponentType",
        "TxSetComponent",
        "TxSetComponentTxsMaybeDiscountedFee",
        "TransactionPhase",
        "TransactionSet",
        "TransactionSetV1",
        "GeneralizedTransactionSet",
        "TransactionResultPair",
        "TransactionResultSet",
        "TransactionHistoryEntry",
        "TransactionHistoryEntryExt",
        "TransactionHistoryResultEntry",
        "TransactionHistoryResultEntryExt",
        "TransactionResultPairV2",
        "TransactionResultSetV2",
        "TransactionHistoryResultEntryV2",
        "TransactionHistoryResultEntryV2Ext",
        "LedgerHeaderHistoryEntry",
        "LedgerHeaderHistoryEntryExt",
        "LedgerScpMessages",
        "ScpHistoryEntryV0",
        "ScpHistoryEntry",
        "LedgerEntryChangeType",
        "LedgerEntryChange",
        "LedgerEntryChanges",
        "OperationMeta",
        "TransactionMetaV1",
        "TransactionMetaV2",
        "ContractEventType",
        "ContractEvent",
        "ContractEventBody",
        "ContractEventV0",
        "OperationEvents",
        "TransactionMetaV3",
        "TransactionMeta",
        "TransactionResultMeta",
        "TransactionResultMetaV2",
        "UpgradeEntryMeta",
        "LedgerCloseMetaV0",
        "LedgerCloseMetaV1",
        "LedgerCloseMetaV2",
        "LedgerCloseMeta",
        "ErrorCode",
        "SError",
        "SendMore",
        "AuthCert",
        "Hello",
        "Auth",
        "IpAddrType",
        "PeerAddress",
        "PeerAddressIp",
        "MessageType",
        "DontHave",
        "SurveyMessageCommandType",
        "SurveyRequestMessage",
        "SignedSurveyRequestMessage",
        "EncryptedBody",
        "SurveyResponseMessage",
        "SignedSurveyResponseMessage",
        "PeerStats",
        "PeerStatList",
        "TopologyResponseBody",
        "SurveyResponseBody",
        "TxAdvertVector",
        "FloodAdvert",
        "TxDemandVector",
        "FloodDemand",
        "StellarMessage",
        "AuthenticatedMessage",
        "AuthenticatedMessageV0",
        "LiquidityPoolParameters",
        "MuxedAccount",
        "MuxedAccountMed25519",
        "DecoratedSignature",
        "LedgerFootprint",
        "OperationType",
        "CreateAccountOp",
        "PaymentOp",
        "PathPaymentStrictReceiveOp",
        "PathPaymentStrictSendOp",
        "ManageSellOfferOp",
        "ManageBuyOfferOp",
        "CreatePassiveSellOfferOp",
        "SetOptionsOp",
        "ChangeTrustAsset",
        "ChangeTrustOp",
        "AllowTrustOp",
        "ManageDataOp",
        "BumpSequenceOp",
        "CreateClaimableBalanceOp",
        "ClaimClaimableBalanceOp",
        "BeginSponsoringFutureReservesOp",
        "RevokeSponsorshipType",
        "RevokeSponsorshipOp",
        "RevokeSponsorshipOpSigner",
        "ClawbackOp",
        "ClawbackClaimableBalanceOp",
        "SetTrustLineFlagsOp",
        "LiquidityPoolDepositOp",
        "LiquidityPoolWithdrawOp",
        "HostFunctionType",
        "ContractIdType",
        "ContractIdPublicKeyType",
        "InstallContractCodeArgs",
        "ContractId",
        "ContractIdFromEd25519PublicKey",
        "CreateContractArgs",
        "HostFunction",
        "InvokeHostFunctionOp",
        "Operation",
        "OperationBody",
        "HashIdPreimage",
        "HashIdPreimageOperationId",
        "HashIdPreimageRevokeId",
        "HashIdPreimageEd25519ContractId",
        "HashIdPreimageContractId",
        "HashIdPreimageFromAsset",
        "HashIdPreimageSourceAccountContractId",
        "HashIdPreimageCreateContractArgs",
        "MemoType",
        "Memo",
        "TimeBounds",
        "LedgerBounds",
        "PreconditionsV2",
        "PreconditionType",
        "Preconditions",
        "TransactionV0",
        "TransactionV0Ext",
        "TransactionV0Envelope",
        "Transaction",
        "TransactionExt",
        "TransactionV1Envelope",
        "FeeBumpTransaction",
        "FeeBumpTransactionInnerTx",
        "FeeBumpTransactionExt",
        "FeeBumpTransactionEnvelope",
        "TransactionEnvelope",
        "TransactionSignaturePayload",
        "TransactionSignaturePayloadTaggedTransaction",
        "ClaimAtomType",
        "ClaimOfferAtomV0",
        "ClaimOfferAtom",
        "ClaimLiquidityAtom",
        "ClaimAtom",
        "CreateAccountResultCode",
        "CreateAccountResult",
        "PaymentResultCode",
        "PaymentResult",
        "PathPaymentStrictReceiveResultCode",
        "SimplePaymentResult",
        "PathPaymentStrictReceiveResult",
        "PathPaymentStrictReceiveResultSuccess",
        "PathPaymentStrictSendResultCode",
        "PathPaymentStrictSendResult",
        "PathPaymentStrictSendResultSuccess",
        "ManageSellOfferResultCode",
        "ManageOfferEffect",
        "ManageOfferSuccessResult",
        "ManageOfferSuccessResultOffer",
        "ManageSellOfferResult",
        "ManageBuyOfferResultCode",
        "ManageBuyOfferResult",
        "SetOptionsResultCode",
        "SetOptionsResult",
        "ChangeTrustResultCode",
        "ChangeTrustResult",
        "AllowTrustResultCode",
        "AllowTrustResult",
        "AccountMergeResultCode",
        "AccountMergeResult",
        "InflationResultCode",
        "InflationPayout",
        "InflationResult",
        "ManageDataResultCode",
        "ManageDataResult",
        "BumpSequenceResultCode",
        "BumpSequenceResult",
        "CreateClaimableBalanceResultCode",
        "CreateClaimableBalanceResult",
        "ClaimClaimableBalanceResultCode",
        "ClaimClaimableBalanceResult",
        "BeginSponsoringFutureReservesResultCode",
        "BeginSponsoringFutureReservesResult",
        "EndSponsoringFutureReservesResultCode",
        "EndSponsoringFutureReservesResult",
        "RevokeSponsorshipResultCode",
        "RevokeSponsorshipResult",
        "ClawbackResultCode",
        "ClawbackResult",
        "ClawbackClaimableBalanceResultCode",
        "ClawbackClaimableBalanceResult",
        "SetTrustLineFlagsResultCode",
        "SetTrustLineFlagsResult",
        "LiquidityPoolDepositResultCode",
        "LiquidityPoolDepositResult",
        "LiquidityPoolWithdrawResultCode",
        "LiquidityPoolWithdrawResult",
        "InvokeHostFunctionResultCode",
        "InvokeHostFunctionResult",
        "OperationResultCode",
        "OperationResult",
        "OperationResultTr",
        "TransactionResultCode",
        "InnerTransactionResult",
        "InnerTransactionResultResult",
        "InnerTransactionResultExt",
        "InnerTransactionResultPair",
        "TransactionResult",
        "TransactionResultResult",
        "TransactionResultExt",
        "Hash",
        "Uint256",
        "Uint32",
        "Int32",
        "Uint64",
        "Int64",
        "ExtensionPoint",
        "CryptoKeyType",
        "PublicKeyType",
        "SignerKeyType",
        "PublicKey",
        "SignerKey",
        "SignerKeyEd25519SignedPayload",
        "Signature",
        "SignatureHint",
        "NodeId",
        "AccountId",
        "Curve25519Secret",
        "Curve25519Public",
        "HmacSha256Key",
        "HmacSha256Mac",
    ];

    #[must_use]
    #[allow(clippy::too_many_lines)]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Value => "Value",
            Self::ScpBallot => "ScpBallot",
            Self::ScpStatementType => "ScpStatementType",
            Self::ScpNomination => "ScpNomination",
            Self::ScpStatement => "ScpStatement",
            Self::ScpStatementPledges => "ScpStatementPledges",
            Self::ScpStatementPrepare => "ScpStatementPrepare",
            Self::ScpStatementConfirm => "ScpStatementConfirm",
            Self::ScpStatementExternalize => "ScpStatementExternalize",
            Self::ScpEnvelope => "ScpEnvelope",
            Self::ScpQuorumSet => "ScpQuorumSet",
            Self::ScEnvMetaKind => "ScEnvMetaKind",
            Self::ScEnvMetaEntry => "ScEnvMetaEntry",
            Self::ScSpecType => "ScSpecType",
            Self::ScSpecTypeOption => "ScSpecTypeOption",
            Self::ScSpecTypeResult => "ScSpecTypeResult",
            Self::ScSpecTypeVec => "ScSpecTypeVec",
            Self::ScSpecTypeMap => "ScSpecTypeMap",
            Self::ScSpecTypeSet => "ScSpecTypeSet",
            Self::ScSpecTypeTuple => "ScSpecTypeTuple",
            Self::ScSpecTypeBytesN => "ScSpecTypeBytesN",
            Self::ScSpecTypeUdt => "ScSpecTypeUdt",
            Self::ScSpecTypeDef => "ScSpecTypeDef",
            Self::ScSpecUdtStructFieldV0 => "ScSpecUdtStructFieldV0",
            Self::ScSpecUdtStructV0 => "ScSpecUdtStructV0",
            Self::ScSpecUdtUnionCaseV0 => "ScSpecUdtUnionCaseV0",
            Self::ScSpecUdtUnionV0 => "ScSpecUdtUnionV0",
            Self::ScSpecUdtEnumCaseV0 => "ScSpecUdtEnumCaseV0",
            Self::ScSpecUdtEnumV0 => "ScSpecUdtEnumV0",
            Self::ScSpecUdtErrorEnumCaseV0 => "ScSpecUdtErrorEnumCaseV0",
            Self::ScSpecUdtErrorEnumV0 => "ScSpecUdtErrorEnumV0",
            Self::ScSpecFunctionInputV0 => "ScSpecFunctionInputV0",
            Self::ScSpecFunctionV0 => "ScSpecFunctionV0",
            Self::ScSpecEntryKind => "ScSpecEntryKind",
            Self::ScSpecEntry => "ScSpecEntry",
            Self::ScSymbol => "ScSymbol",
            Self::ScValType => "ScValType",
            Self::ScStatic => "ScStatic",
            Self::ScStatusType => "ScStatusType",
            Self::ScHostValErrorCode => "ScHostValErrorCode",
            Self::ScHostObjErrorCode => "ScHostObjErrorCode",
            Self::ScHostFnErrorCode => "ScHostFnErrorCode",
            Self::ScHostStorageErrorCode => "ScHostStorageErrorCode",
            Self::ScHostContextErrorCode => "ScHostContextErrorCode",
            Self::ScVmErrorCode => "ScVmErrorCode",
            Self::ScUnknownErrorCode => "ScUnknownErrorCode",
            Self::ScStatus => "ScStatus",
            Self::ScVal => "ScVal",
            Self::ScObjectType => "ScObjectType",
            Self::ScMapEntry => "ScMapEntry",
            Self::ScVec => "ScVec",
            Self::ScMap => "ScMap",
            Self::ScContractCodeType => "ScContractCodeType",
            Self::ScContractCode => "ScContractCode",
            Self::Int128Parts => "Int128Parts",
            Self::ScObject => "ScObject",
            Self::StoredTransactionSet => "StoredTransactionSet",
            Self::PersistedScpStateV0 => "PersistedScpStateV0",
            Self::PersistedScpStateV1 => "PersistedScpStateV1",
            Self::PersistedScpState => "PersistedScpState",
            Self::Thresholds => "Thresholds",
            Self::String32 => "String32",
            Self::String64 => "String64",
            Self::SequenceNumber => "SequenceNumber",
            Self::TimePoint => "TimePoint",
            Self::Duration => "Duration",
            Self::DataValue => "DataValue",
            Self::PoolId => "PoolId",
            Self::AssetCode4 => "AssetCode4",
            Self::AssetCode12 => "AssetCode12",
            Self::AssetType => "AssetType",
            Self::AssetCode => "AssetCode",
            Self::AlphaNum4 => "AlphaNum4",
            Self::AlphaNum12 => "AlphaNum12",
            Self::Asset => "Asset",
            Self::Price => "Price",
            Self::Liabilities => "Liabilities",
            Self::ThresholdIndexes => "ThresholdIndexes",
            Self::LedgerEntryType => "LedgerEntryType",
            Self::Signer => "Signer",
            Self::AccountFlags => "AccountFlags",
            Self::SponsorshipDescriptor => "SponsorshipDescriptor",
            Self::AccountEntryExtensionV3 => "AccountEntryExtensionV3",
            Self::AccountEntryExtensionV2 => "AccountEntryExtensionV2",
            Self::AccountEntryExtensionV2Ext => "AccountEntryExtensionV2Ext",
            Self::AccountEntryExtensionV1 => "AccountEntryExtensionV1",
            Self::AccountEntryExtensionV1Ext => "AccountEntryExtensionV1Ext",
            Self::AccountEntry => "AccountEntry",
            Self::AccountEntryExt => "AccountEntryExt",
            Self::TrustLineFlags => "TrustLineFlags",
            Self::LiquidityPoolType => "LiquidityPoolType",
            Self::TrustLineAsset => "TrustLineAsset",
            Self::TrustLineEntryExtensionV2 => "TrustLineEntryExtensionV2",
            Self::TrustLineEntryExtensionV2Ext => "TrustLineEntryExtensionV2Ext",
            Self::TrustLineEntry => "TrustLineEntry",
            Self::TrustLineEntryExt => "TrustLineEntryExt",
            Self::TrustLineEntryV1 => "TrustLineEntryV1",
            Self::TrustLineEntryV1Ext => "TrustLineEntryV1Ext",
            Self::OfferEntryFlags => "OfferEntryFlags",
            Self::OfferEntry => "OfferEntry",
            Self::OfferEntryExt => "OfferEntryExt",
            Self::DataEntry => "DataEntry",
            Self::DataEntryExt => "DataEntryExt",
            Self::ClaimPredicateType => "ClaimPredicateType",
            Self::ClaimPredicate => "ClaimPredicate",
            Self::ClaimantType => "ClaimantType",
            Self::Claimant => "Claimant",
            Self::ClaimantV0 => "ClaimantV0",
            Self::ClaimableBalanceIdType => "ClaimableBalanceIdType",
            Self::ClaimableBalanceId => "ClaimableBalanceId",
            Self::ClaimableBalanceFlags => "ClaimableBalanceFlags",
            Self::ClaimableBalanceEntryExtensionV1 => "ClaimableBalanceEntryExtensionV1",
            Self::ClaimableBalanceEntryExtensionV1Ext => "ClaimableBalanceEntryExtensionV1Ext",
            Self::ClaimableBalanceEntry => "ClaimableBalanceEntry",
            Self::ClaimableBalanceEntryExt => "ClaimableBalanceEntryExt",
            Self::LiquidityPoolConstantProductParameters => {
                "LiquidityPoolConstantProductParameters"
            }
            Self::LiquidityPoolEntry => "LiquidityPoolEntry",
            Self::LiquidityPoolEntryBody => "LiquidityPoolEntryBody",
            Self::LiquidityPoolEntryConstantProduct => "LiquidityPoolEntryConstantProduct",
            Self::ContractDataEntry => "ContractDataEntry",
            Self::ContractCodeEntry => "ContractCodeEntry",
            Self::ConfigSettingType => "ConfigSettingType",
            Self::ConfigSetting => "ConfigSetting",
            Self::ConfigSettingId => "ConfigSettingId",
            Self::ConfigSettingEntry => "ConfigSettingEntry",
            Self::ConfigSettingEntryExt => "ConfigSettingEntryExt",
            Self::LedgerEntryExtensionV1 => "LedgerEntryExtensionV1",
            Self::LedgerEntryExtensionV1Ext => "LedgerEntryExtensionV1Ext",
            Self::LedgerEntry => "LedgerEntry",
            Self::LedgerEntryData => "LedgerEntryData",
            Self::LedgerEntryExt => "LedgerEntryExt",
            Self::LedgerKey => "LedgerKey",
            Self::LedgerKeyAccount => "LedgerKeyAccount",
            Self::LedgerKeyTrustLine => "LedgerKeyTrustLine",
            Self::LedgerKeyOffer => "LedgerKeyOffer",
            Self::LedgerKeyData => "LedgerKeyData",
            Self::LedgerKeyClaimableBalance => "LedgerKeyClaimableBalance",
            Self::LedgerKeyLiquidityPool => "LedgerKeyLiquidityPool",
            Self::LedgerKeyContractData => "LedgerKeyContractData",
            Self::LedgerKeyContractCode => "LedgerKeyContractCode",
            Self::LedgerKeyConfigSetting => "LedgerKeyConfigSetting",
            Self::EnvelopeType => "EnvelopeType",
            Self::UpgradeType => "UpgradeType",
            Self::StellarValueType => "StellarValueType",
            Self::LedgerCloseValueSignature => "LedgerCloseValueSignature",
            Self::StellarValue => "StellarValue",
            Self::StellarValueExt => "StellarValueExt",
            Self::LedgerHeaderFlags => "LedgerHeaderFlags",
            Self::LedgerHeaderExtensionV1 => "LedgerHeaderExtensionV1",
            Self::LedgerHeaderExtensionV1Ext => "LedgerHeaderExtensionV1Ext",
            Self::LedgerHeader => "LedgerHeader",
            Self::LedgerHeaderExt => "LedgerHeaderExt",
            Self::LedgerUpgradeType => "LedgerUpgradeType",
            Self::LedgerUpgrade => "LedgerUpgrade",
            Self::LedgerUpgradeConfigSetting => "LedgerUpgradeConfigSetting",
            Self::BucketEntryType => "BucketEntryType",
            Self::BucketMetadata => "BucketMetadata",
            Self::BucketMetadataExt => "BucketMetadataExt",
            Self::BucketEntry => "BucketEntry",
            Self::TxSetComponentType => "TxSetComponentType",
            Self::TxSetComponent => "TxSetComponent",
            Self::TxSetComponentTxsMaybeDiscountedFee => "TxSetComponentTxsMaybeDiscountedFee",
            Self::TransactionPhase => "TransactionPhase",
            Self::TransactionSet => "TransactionSet",
            Self::TransactionSetV1 => "TransactionSetV1",
            Self::GeneralizedTransactionSet => "GeneralizedTransactionSet",
            Self::TransactionResultPair => "TransactionResultPair",
            Self::TransactionResultSet => "TransactionResultSet",
            Self::TransactionHistoryEntry => "TransactionHistoryEntry",
            Self::TransactionHistoryEntryExt => "TransactionHistoryEntryExt",
            Self::TransactionHistoryResultEntry => "TransactionHistoryResultEntry",
            Self::TransactionHistoryResultEntryExt => "TransactionHistoryResultEntryExt",
            Self::TransactionResultPairV2 => "TransactionResultPairV2",
            Self::TransactionResultSetV2 => "TransactionResultSetV2",
            Self::TransactionHistoryResultEntryV2 => "TransactionHistoryResultEntryV2",
            Self::TransactionHistoryResultEntryV2Ext => "TransactionHistoryResultEntryV2Ext",
            Self::LedgerHeaderHistoryEntry => "LedgerHeaderHistoryEntry",
            Self::LedgerHeaderHistoryEntryExt => "LedgerHeaderHistoryEntryExt",
            Self::LedgerScpMessages => "LedgerScpMessages",
            Self::ScpHistoryEntryV0 => "ScpHistoryEntryV0",
            Self::ScpHistoryEntry => "ScpHistoryEntry",
            Self::LedgerEntryChangeType => "LedgerEntryChangeType",
            Self::LedgerEntryChange => "LedgerEntryChange",
            Self::LedgerEntryChanges => "LedgerEntryChanges",
            Self::OperationMeta => "OperationMeta",
            Self::TransactionMetaV1 => "TransactionMetaV1",
            Self::TransactionMetaV2 => "TransactionMetaV2",
            Self::ContractEventType => "ContractEventType",
            Self::ContractEvent => "ContractEvent",
            Self::ContractEventBody => "ContractEventBody",
            Self::ContractEventV0 => "ContractEventV0",
            Self::OperationEvents => "OperationEvents",
            Self::TransactionMetaV3 => "TransactionMetaV3",
            Self::TransactionMeta => "TransactionMeta",
            Self::TransactionResultMeta => "TransactionResultMeta",
            Self::TransactionResultMetaV2 => "TransactionResultMetaV2",
            Self::UpgradeEntryMeta => "UpgradeEntryMeta",
            Self::LedgerCloseMetaV0 => "LedgerCloseMetaV0",
            Self::LedgerCloseMetaV1 => "LedgerCloseMetaV1",
            Self::LedgerCloseMetaV2 => "LedgerCloseMetaV2",
            Self::LedgerCloseMeta => "LedgerCloseMeta",
            Self::ErrorCode => "ErrorCode",
            Self::SError => "SError",
            Self::SendMore => "SendMore",
            Self::AuthCert => "AuthCert",
            Self::Hello => "Hello",
            Self::Auth => "Auth",
            Self::IpAddrType => "IpAddrType",
            Self::PeerAddress => "PeerAddress",
            Self::PeerAddressIp => "PeerAddressIp",
            Self::MessageType => "MessageType",
            Self::DontHave => "DontHave",
            Self::SurveyMessageCommandType => "SurveyMessageCommandType",
            Self::SurveyRequestMessage => "SurveyRequestMessage",
            Self::SignedSurveyRequestMessage => "SignedSurveyRequestMessage",
            Self::EncryptedBody => "EncryptedBody",
            Self::SurveyResponseMessage => "SurveyResponseMessage",
            Self::SignedSurveyResponseMessage => "SignedSurveyResponseMessage",
            Self::PeerStats => "PeerStats",
            Self::PeerStatList => "PeerStatList",
            Self::TopologyResponseBody => "TopologyResponseBody",
            Self::SurveyResponseBody => "SurveyResponseBody",
            Self::TxAdvertVector => "TxAdvertVector",
            Self::FloodAdvert => "FloodAdvert",
            Self::TxDemandVector => "TxDemandVector",
            Self::FloodDemand => "FloodDemand",
            Self::StellarMessage => "StellarMessage",
            Self::AuthenticatedMessage => "AuthenticatedMessage",
            Self::AuthenticatedMessageV0 => "AuthenticatedMessageV0",
            Self::LiquidityPoolParameters => "LiquidityPoolParameters",
            Self::MuxedAccount => "MuxedAccount",
            Self::MuxedAccountMed25519 => "MuxedAccountMed25519",
            Self::DecoratedSignature => "DecoratedSignature",
            Self::LedgerFootprint => "LedgerFootprint",
            Self::OperationType => "OperationType",
            Self::CreateAccountOp => "CreateAccountOp",
            Self::PaymentOp => "PaymentOp",
            Self::PathPaymentStrictReceiveOp => "PathPaymentStrictReceiveOp",
            Self::PathPaymentStrictSendOp => "PathPaymentStrictSendOp",
            Self::ManageSellOfferOp => "ManageSellOfferOp",
            Self::ManageBuyOfferOp => "ManageBuyOfferOp",
            Self::CreatePassiveSellOfferOp => "CreatePassiveSellOfferOp",
            Self::SetOptionsOp => "SetOptionsOp",
            Self::ChangeTrustAsset => "ChangeTrustAsset",
            Self::ChangeTrustOp => "ChangeTrustOp",
            Self::AllowTrustOp => "AllowTrustOp",
            Self::ManageDataOp => "ManageDataOp",
            Self::BumpSequenceOp => "BumpSequenceOp",
            Self::CreateClaimableBalanceOp => "CreateClaimableBalanceOp",
            Self::ClaimClaimableBalanceOp => "ClaimClaimableBalanceOp",
            Self::BeginSponsoringFutureReservesOp => "BeginSponsoringFutureReservesOp",
            Self::RevokeSponsorshipType => "RevokeSponsorshipType",
            Self::RevokeSponsorshipOp => "RevokeSponsorshipOp",
            Self::RevokeSponsorshipOpSigner => "RevokeSponsorshipOpSigner",
            Self::ClawbackOp => "ClawbackOp",
            Self::ClawbackClaimableBalanceOp => "ClawbackClaimableBalanceOp",
            Self::SetTrustLineFlagsOp => "SetTrustLineFlagsOp",
            Self::LiquidityPoolDepositOp => "LiquidityPoolDepositOp",
            Self::LiquidityPoolWithdrawOp => "LiquidityPoolWithdrawOp",
            Self::HostFunctionType => "HostFunctionType",
            Self::ContractIdType => "ContractIdType",
            Self::ContractIdPublicKeyType => "ContractIdPublicKeyType",
            Self::InstallContractCodeArgs => "InstallContractCodeArgs",
            Self::ContractId => "ContractId",
            Self::ContractIdFromEd25519PublicKey => "ContractIdFromEd25519PublicKey",
            Self::CreateContractArgs => "CreateContractArgs",
            Self::HostFunction => "HostFunction",
            Self::InvokeHostFunctionOp => "InvokeHostFunctionOp",
            Self::Operation => "Operation",
            Self::OperationBody => "OperationBody",
            Self::HashIdPreimage => "HashIdPreimage",
            Self::HashIdPreimageOperationId => "HashIdPreimageOperationId",
            Self::HashIdPreimageRevokeId => "HashIdPreimageRevokeId",
            Self::HashIdPreimageEd25519ContractId => "HashIdPreimageEd25519ContractId",
            Self::HashIdPreimageContractId => "HashIdPreimageContractId",
            Self::HashIdPreimageFromAsset => "HashIdPreimageFromAsset",
            Self::HashIdPreimageSourceAccountContractId => "HashIdPreimageSourceAccountContractId",
            Self::HashIdPreimageCreateContractArgs => "HashIdPreimageCreateContractArgs",
            Self::MemoType => "MemoType",
            Self::Memo => "Memo",
            Self::TimeBounds => "TimeBounds",
            Self::LedgerBounds => "LedgerBounds",
            Self::PreconditionsV2 => "PreconditionsV2",
            Self::PreconditionType => "PreconditionType",
            Self::Preconditions => "Preconditions",
            Self::TransactionV0 => "TransactionV0",
            Self::TransactionV0Ext => "TransactionV0Ext",
            Self::TransactionV0Envelope => "TransactionV0Envelope",
            Self::Transaction => "Transaction",
            Self::TransactionExt => "TransactionExt",
            Self::TransactionV1Envelope => "TransactionV1Envelope",
            Self::FeeBumpTransaction => "FeeBumpTransaction",
            Self::FeeBumpTransactionInnerTx => "FeeBumpTransactionInnerTx",
            Self::FeeBumpTransactionExt => "FeeBumpTransactionExt",
            Self::FeeBumpTransactionEnvelope => "FeeBumpTransactionEnvelope",
            Self::TransactionEnvelope => "TransactionEnvelope",
            Self::TransactionSignaturePayload => "TransactionSignaturePayload",
            Self::TransactionSignaturePayloadTaggedTransaction => {
                "TransactionSignaturePayloadTaggedTransaction"
            }
            Self::ClaimAtomType => "ClaimAtomType",
            Self::ClaimOfferAtomV0 => "ClaimOfferAtomV0",
            Self::ClaimOfferAtom => "ClaimOfferAtom",
            Self::ClaimLiquidityAtom => "ClaimLiquidityAtom",
            Self::ClaimAtom => "ClaimAtom",
            Self::CreateAccountResultCode => "CreateAccountResultCode",
            Self::CreateAccountResult => "CreateAccountResult",
            Self::PaymentResultCode => "PaymentResultCode",
            Self::PaymentResult => "PaymentResult",
            Self::PathPaymentStrictReceiveResultCode => "PathPaymentStrictReceiveResultCode",
            Self::SimplePaymentResult => "SimplePaymentResult",
            Self::PathPaymentStrictReceiveResult => "PathPaymentStrictReceiveResult",
            Self::PathPaymentStrictReceiveResultSuccess => "PathPaymentStrictReceiveResultSuccess",
            Self::PathPaymentStrictSendResultCode => "PathPaymentStrictSendResultCode",
            Self::PathPaymentStrictSendResult => "PathPaymentStrictSendResult",
            Self::PathPaymentStrictSendResultSuccess => "PathPaymentStrictSendResultSuccess",
            Self::ManageSellOfferResultCode => "ManageSellOfferResultCode",
            Self::ManageOfferEffect => "ManageOfferEffect",
            Self::ManageOfferSuccessResult => "ManageOfferSuccessResult",
            Self::ManageOfferSuccessResultOffer => "ManageOfferSuccessResultOffer",
            Self::ManageSellOfferResult => "ManageSellOfferResult",
            Self::ManageBuyOfferResultCode => "ManageBuyOfferResultCode",
            Self::ManageBuyOfferResult => "ManageBuyOfferResult",
            Self::SetOptionsResultCode => "SetOptionsResultCode",
            Self::SetOptionsResult => "SetOptionsResult",
            Self::ChangeTrustResultCode => "ChangeTrustResultCode",
            Self::ChangeTrustResult => "ChangeTrustResult",
            Self::AllowTrustResultCode => "AllowTrustResultCode",
            Self::AllowTrustResult => "AllowTrustResult",
            Self::AccountMergeResultCode => "AccountMergeResultCode",
            Self::AccountMergeResult => "AccountMergeResult",
            Self::InflationResultCode => "InflationResultCode",
            Self::InflationPayout => "InflationPayout",
            Self::InflationResult => "InflationResult",
            Self::ManageDataResultCode => "ManageDataResultCode",
            Self::ManageDataResult => "ManageDataResult",
            Self::BumpSequenceResultCode => "BumpSequenceResultCode",
            Self::BumpSequenceResult => "BumpSequenceResult",
            Self::CreateClaimableBalanceResultCode => "CreateClaimableBalanceResultCode",
            Self::CreateClaimableBalanceResult => "CreateClaimableBalanceResult",
            Self::ClaimClaimableBalanceResultCode => "ClaimClaimableBalanceResultCode",
            Self::ClaimClaimableBalanceResult => "ClaimClaimableBalanceResult",
            Self::BeginSponsoringFutureReservesResultCode => {
                "BeginSponsoringFutureReservesResultCode"
            }
            Self::BeginSponsoringFutureReservesResult => "BeginSponsoringFutureReservesResult",
            Self::EndSponsoringFutureReservesResultCode => "EndSponsoringFutureReservesResultCode",
            Self::EndSponsoringFutureReservesResult => "EndSponsoringFutureReservesResult",
            Self::RevokeSponsorshipResultCode => "RevokeSponsorshipResultCode",
            Self::RevokeSponsorshipResult => "RevokeSponsorshipResult",
            Self::ClawbackResultCode => "ClawbackResultCode",
            Self::ClawbackResult => "ClawbackResult",
            Self::ClawbackClaimableBalanceResultCode => "ClawbackClaimableBalanceResultCode",
            Self::ClawbackClaimableBalanceResult => "ClawbackClaimableBalanceResult",
            Self::SetTrustLineFlagsResultCode => "SetTrustLineFlagsResultCode",
            Self::SetTrustLineFlagsResult => "SetTrustLineFlagsResult",
            Self::LiquidityPoolDepositResultCode => "LiquidityPoolDepositResultCode",
            Self::LiquidityPoolDepositResult => "LiquidityPoolDepositResult",
            Self::LiquidityPoolWithdrawResultCode => "LiquidityPoolWithdrawResultCode",
            Self::LiquidityPoolWithdrawResult => "LiquidityPoolWithdrawResult",
            Self::InvokeHostFunctionResultCode => "InvokeHostFunctionResultCode",
            Self::InvokeHostFunctionResult => "InvokeHostFunctionResult",
            Self::OperationResultCode => "OperationResultCode",
            Self::OperationResult => "OperationResult",
            Self::OperationResultTr => "OperationResultTr",
            Self::TransactionResultCode => "TransactionResultCode",
            Self::InnerTransactionResult => "InnerTransactionResult",
            Self::InnerTransactionResultResult => "InnerTransactionResultResult",
            Self::InnerTransactionResultExt => "InnerTransactionResultExt",
            Self::InnerTransactionResultPair => "InnerTransactionResultPair",
            Self::TransactionResult => "TransactionResult",
            Self::TransactionResultResult => "TransactionResultResult",
            Self::TransactionResultExt => "TransactionResultExt",
            Self::Hash => "Hash",
            Self::Uint256 => "Uint256",
            Self::Uint32 => "Uint32",
            Self::Int32 => "Int32",
            Self::Uint64 => "Uint64",
            Self::Int64 => "Int64",
            Self::ExtensionPoint => "ExtensionPoint",
            Self::CryptoKeyType => "CryptoKeyType",
            Self::PublicKeyType => "PublicKeyType",
            Self::SignerKeyType => "SignerKeyType",
            Self::PublicKey => "PublicKey",
            Self::SignerKey => "SignerKey",
            Self::SignerKeyEd25519SignedPayload => "SignerKeyEd25519SignedPayload",
            Self::Signature => "Signature",
            Self::SignatureHint => "SignatureHint",
            Self::NodeId => "NodeId",
            Self::AccountId => "AccountId",
            Self::Curve25519Secret => "Curve25519Secret",
            Self::Curve25519Public => "Curve25519Public",
            Self::HmacSha256Key => "HmacSha256Key",
            Self::HmacSha256Mac => "HmacSha256Mac",
        }
    }

    #[must_use]
    #[allow(clippy::too_many_lines)]
    pub const fn variants() -> [TypeVariant; 390] {
        Self::VARIANTS
    }
}

impl Name for TypeVariant {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<TypeVariant> for TypeVariant {
    fn variants() -> slice::Iter<'static, TypeVariant> {
        Self::VARIANTS.iter()
    }
}

impl core::str::FromStr for TypeVariant {
    type Err = Error;
    #[allow(clippy::too_many_lines)]
    fn from_str(s: &str) -> Result<Self> {
        match s {
            "Value" => Ok(Self::Value),
            "ScpBallot" => Ok(Self::ScpBallot),
            "ScpStatementType" => Ok(Self::ScpStatementType),
            "ScpNomination" => Ok(Self::ScpNomination),
            "ScpStatement" => Ok(Self::ScpStatement),
            "ScpStatementPledges" => Ok(Self::ScpStatementPledges),
            "ScpStatementPrepare" => Ok(Self::ScpStatementPrepare),
            "ScpStatementConfirm" => Ok(Self::ScpStatementConfirm),
            "ScpStatementExternalize" => Ok(Self::ScpStatementExternalize),
            "ScpEnvelope" => Ok(Self::ScpEnvelope),
            "ScpQuorumSet" => Ok(Self::ScpQuorumSet),
            "ScEnvMetaKind" => Ok(Self::ScEnvMetaKind),
            "ScEnvMetaEntry" => Ok(Self::ScEnvMetaEntry),
            "ScSpecType" => Ok(Self::ScSpecType),
            "ScSpecTypeOption" => Ok(Self::ScSpecTypeOption),
            "ScSpecTypeResult" => Ok(Self::ScSpecTypeResult),
            "ScSpecTypeVec" => Ok(Self::ScSpecTypeVec),
            "ScSpecTypeMap" => Ok(Self::ScSpecTypeMap),
            "ScSpecTypeSet" => Ok(Self::ScSpecTypeSet),
            "ScSpecTypeTuple" => Ok(Self::ScSpecTypeTuple),
            "ScSpecTypeBytesN" => Ok(Self::ScSpecTypeBytesN),
            "ScSpecTypeUdt" => Ok(Self::ScSpecTypeUdt),
            "ScSpecTypeDef" => Ok(Self::ScSpecTypeDef),
            "ScSpecUdtStructFieldV0" => Ok(Self::ScSpecUdtStructFieldV0),
            "ScSpecUdtStructV0" => Ok(Self::ScSpecUdtStructV0),
            "ScSpecUdtUnionCaseV0" => Ok(Self::ScSpecUdtUnionCaseV0),
            "ScSpecUdtUnionV0" => Ok(Self::ScSpecUdtUnionV0),
            "ScSpecUdtEnumCaseV0" => Ok(Self::ScSpecUdtEnumCaseV0),
            "ScSpecUdtEnumV0" => Ok(Self::ScSpecUdtEnumV0),
            "ScSpecUdtErrorEnumCaseV0" => Ok(Self::ScSpecUdtErrorEnumCaseV0),
            "ScSpecUdtErrorEnumV0" => Ok(Self::ScSpecUdtErrorEnumV0),
            "ScSpecFunctionInputV0" => Ok(Self::ScSpecFunctionInputV0),
            "ScSpecFunctionV0" => Ok(Self::ScSpecFunctionV0),
            "ScSpecEntryKind" => Ok(Self::ScSpecEntryKind),
            "ScSpecEntry" => Ok(Self::ScSpecEntry),
            "ScSymbol" => Ok(Self::ScSymbol),
            "ScValType" => Ok(Self::ScValType),
            "ScStatic" => Ok(Self::ScStatic),
            "ScStatusType" => Ok(Self::ScStatusType),
            "ScHostValErrorCode" => Ok(Self::ScHostValErrorCode),
            "ScHostObjErrorCode" => Ok(Self::ScHostObjErrorCode),
            "ScHostFnErrorCode" => Ok(Self::ScHostFnErrorCode),
            "ScHostStorageErrorCode" => Ok(Self::ScHostStorageErrorCode),
            "ScHostContextErrorCode" => Ok(Self::ScHostContextErrorCode),
            "ScVmErrorCode" => Ok(Self::ScVmErrorCode),
            "ScUnknownErrorCode" => Ok(Self::ScUnknownErrorCode),
            "ScStatus" => Ok(Self::ScStatus),
            "ScVal" => Ok(Self::ScVal),
            "ScObjectType" => Ok(Self::ScObjectType),
            "ScMapEntry" => Ok(Self::ScMapEntry),
            "ScVec" => Ok(Self::ScVec),
            "ScMap" => Ok(Self::ScMap),
            "ScContractCodeType" => Ok(Self::ScContractCodeType),
            "ScContractCode" => Ok(Self::ScContractCode),
            "Int128Parts" => Ok(Self::Int128Parts),
            "ScObject" => Ok(Self::ScObject),
            "StoredTransactionSet" => Ok(Self::StoredTransactionSet),
            "PersistedScpStateV0" => Ok(Self::PersistedScpStateV0),
            "PersistedScpStateV1" => Ok(Self::PersistedScpStateV1),
            "PersistedScpState" => Ok(Self::PersistedScpState),
            "Thresholds" => Ok(Self::Thresholds),
            "String32" => Ok(Self::String32),
            "String64" => Ok(Self::String64),
            "SequenceNumber" => Ok(Self::SequenceNumber),
            "TimePoint" => Ok(Self::TimePoint),
            "Duration" => Ok(Self::Duration),
            "DataValue" => Ok(Self::DataValue),
            "PoolId" => Ok(Self::PoolId),
            "AssetCode4" => Ok(Self::AssetCode4),
            "AssetCode12" => Ok(Self::AssetCode12),
            "AssetType" => Ok(Self::AssetType),
            "AssetCode" => Ok(Self::AssetCode),
            "AlphaNum4" => Ok(Self::AlphaNum4),
            "AlphaNum12" => Ok(Self::AlphaNum12),
            "Asset" => Ok(Self::Asset),
            "Price" => Ok(Self::Price),
            "Liabilities" => Ok(Self::Liabilities),
            "ThresholdIndexes" => Ok(Self::ThresholdIndexes),
            "LedgerEntryType" => Ok(Self::LedgerEntryType),
            "Signer" => Ok(Self::Signer),
            "AccountFlags" => Ok(Self::AccountFlags),
            "SponsorshipDescriptor" => Ok(Self::SponsorshipDescriptor),
            "AccountEntryExtensionV3" => Ok(Self::AccountEntryExtensionV3),
            "AccountEntryExtensionV2" => Ok(Self::AccountEntryExtensionV2),
            "AccountEntryExtensionV2Ext" => Ok(Self::AccountEntryExtensionV2Ext),
            "AccountEntryExtensionV1" => Ok(Self::AccountEntryExtensionV1),
            "AccountEntryExtensionV1Ext" => Ok(Self::AccountEntryExtensionV1Ext),
            "AccountEntry" => Ok(Self::AccountEntry),
            "AccountEntryExt" => Ok(Self::AccountEntryExt),
            "TrustLineFlags" => Ok(Self::TrustLineFlags),
            "LiquidityPoolType" => Ok(Self::LiquidityPoolType),
            "TrustLineAsset" => Ok(Self::TrustLineAsset),
            "TrustLineEntryExtensionV2" => Ok(Self::TrustLineEntryExtensionV2),
            "TrustLineEntryExtensionV2Ext" => Ok(Self::TrustLineEntryExtensionV2Ext),
            "TrustLineEntry" => Ok(Self::TrustLineEntry),
            "TrustLineEntryExt" => Ok(Self::TrustLineEntryExt),
            "TrustLineEntryV1" => Ok(Self::TrustLineEntryV1),
            "TrustLineEntryV1Ext" => Ok(Self::TrustLineEntryV1Ext),
            "OfferEntryFlags" => Ok(Self::OfferEntryFlags),
            "OfferEntry" => Ok(Self::OfferEntry),
            "OfferEntryExt" => Ok(Self::OfferEntryExt),
            "DataEntry" => Ok(Self::DataEntry),
            "DataEntryExt" => Ok(Self::DataEntryExt),
            "ClaimPredicateType" => Ok(Self::ClaimPredicateType),
            "ClaimPredicate" => Ok(Self::ClaimPredicate),
            "ClaimantType" => Ok(Self::ClaimantType),
            "Claimant" => Ok(Self::Claimant),
            "ClaimantV0" => Ok(Self::ClaimantV0),
            "ClaimableBalanceIdType" => Ok(Self::ClaimableBalanceIdType),
            "ClaimableBalanceId" => Ok(Self::ClaimableBalanceId),
            "ClaimableBalanceFlags" => Ok(Self::ClaimableBalanceFlags),
            "ClaimableBalanceEntryExtensionV1" => Ok(Self::ClaimableBalanceEntryExtensionV1),
            "ClaimableBalanceEntryExtensionV1Ext" => Ok(Self::ClaimableBalanceEntryExtensionV1Ext),
            "ClaimableBalanceEntry" => Ok(Self::ClaimableBalanceEntry),
            "ClaimableBalanceEntryExt" => Ok(Self::ClaimableBalanceEntryExt),
            "LiquidityPoolConstantProductParameters" => {
                Ok(Self::LiquidityPoolConstantProductParameters)
            }
            "LiquidityPoolEntry" => Ok(Self::LiquidityPoolEntry),
            "LiquidityPoolEntryBody" => Ok(Self::LiquidityPoolEntryBody),
            "LiquidityPoolEntryConstantProduct" => Ok(Self::LiquidityPoolEntryConstantProduct),
            "ContractDataEntry" => Ok(Self::ContractDataEntry),
            "ContractCodeEntry" => Ok(Self::ContractCodeEntry),
            "ConfigSettingType" => Ok(Self::ConfigSettingType),
            "ConfigSetting" => Ok(Self::ConfigSetting),
            "ConfigSettingId" => Ok(Self::ConfigSettingId),
            "ConfigSettingEntry" => Ok(Self::ConfigSettingEntry),
            "ConfigSettingEntryExt" => Ok(Self::ConfigSettingEntryExt),
            "LedgerEntryExtensionV1" => Ok(Self::LedgerEntryExtensionV1),
            "LedgerEntryExtensionV1Ext" => Ok(Self::LedgerEntryExtensionV1Ext),
            "LedgerEntry" => Ok(Self::LedgerEntry),
            "LedgerEntryData" => Ok(Self::LedgerEntryData),
            "LedgerEntryExt" => Ok(Self::LedgerEntryExt),
            "LedgerKey" => Ok(Self::LedgerKey),
            "LedgerKeyAccount" => Ok(Self::LedgerKeyAccount),
            "LedgerKeyTrustLine" => Ok(Self::LedgerKeyTrustLine),
            "LedgerKeyOffer" => Ok(Self::LedgerKeyOffer),
            "LedgerKeyData" => Ok(Self::LedgerKeyData),
            "LedgerKeyClaimableBalance" => Ok(Self::LedgerKeyClaimableBalance),
            "LedgerKeyLiquidityPool" => Ok(Self::LedgerKeyLiquidityPool),
            "LedgerKeyContractData" => Ok(Self::LedgerKeyContractData),
            "LedgerKeyContractCode" => Ok(Self::LedgerKeyContractCode),
            "LedgerKeyConfigSetting" => Ok(Self::LedgerKeyConfigSetting),
            "EnvelopeType" => Ok(Self::EnvelopeType),
            "UpgradeType" => Ok(Self::UpgradeType),
            "StellarValueType" => Ok(Self::StellarValueType),
            "LedgerCloseValueSignature" => Ok(Self::LedgerCloseValueSignature),
            "StellarValue" => Ok(Self::StellarValue),
            "StellarValueExt" => Ok(Self::StellarValueExt),
            "LedgerHeaderFlags" => Ok(Self::LedgerHeaderFlags),
            "LedgerHeaderExtensionV1" => Ok(Self::LedgerHeaderExtensionV1),
            "LedgerHeaderExtensionV1Ext" => Ok(Self::LedgerHeaderExtensionV1Ext),
            "LedgerHeader" => Ok(Self::LedgerHeader),
            "LedgerHeaderExt" => Ok(Self::LedgerHeaderExt),
            "LedgerUpgradeType" => Ok(Self::LedgerUpgradeType),
            "LedgerUpgrade" => Ok(Self::LedgerUpgrade),
            "LedgerUpgradeConfigSetting" => Ok(Self::LedgerUpgradeConfigSetting),
            "BucketEntryType" => Ok(Self::BucketEntryType),
            "BucketMetadata" => Ok(Self::BucketMetadata),
            "BucketMetadataExt" => Ok(Self::BucketMetadataExt),
            "BucketEntry" => Ok(Self::BucketEntry),
            "TxSetComponentType" => Ok(Self::TxSetComponentType),
            "TxSetComponent" => Ok(Self::TxSetComponent),
            "TxSetComponentTxsMaybeDiscountedFee" => Ok(Self::TxSetComponentTxsMaybeDiscountedFee),
            "TransactionPhase" => Ok(Self::TransactionPhase),
            "TransactionSet" => Ok(Self::TransactionSet),
            "TransactionSetV1" => Ok(Self::TransactionSetV1),
            "GeneralizedTransactionSet" => Ok(Self::GeneralizedTransactionSet),
            "TransactionResultPair" => Ok(Self::TransactionResultPair),
            "TransactionResultSet" => Ok(Self::TransactionResultSet),
            "TransactionHistoryEntry" => Ok(Self::TransactionHistoryEntry),
            "TransactionHistoryEntryExt" => Ok(Self::TransactionHistoryEntryExt),
            "TransactionHistoryResultEntry" => Ok(Self::TransactionHistoryResultEntry),
            "TransactionHistoryResultEntryExt" => Ok(Self::TransactionHistoryResultEntryExt),
            "TransactionResultPairV2" => Ok(Self::TransactionResultPairV2),
            "TransactionResultSetV2" => Ok(Self::TransactionResultSetV2),
            "TransactionHistoryResultEntryV2" => Ok(Self::TransactionHistoryResultEntryV2),
            "TransactionHistoryResultEntryV2Ext" => Ok(Self::TransactionHistoryResultEntryV2Ext),
            "LedgerHeaderHistoryEntry" => Ok(Self::LedgerHeaderHistoryEntry),
            "LedgerHeaderHistoryEntryExt" => Ok(Self::LedgerHeaderHistoryEntryExt),
            "LedgerScpMessages" => Ok(Self::LedgerScpMessages),
            "ScpHistoryEntryV0" => Ok(Self::ScpHistoryEntryV0),
            "ScpHistoryEntry" => Ok(Self::ScpHistoryEntry),
            "LedgerEntryChangeType" => Ok(Self::LedgerEntryChangeType),
            "LedgerEntryChange" => Ok(Self::LedgerEntryChange),
            "LedgerEntryChanges" => Ok(Self::LedgerEntryChanges),
            "OperationMeta" => Ok(Self::OperationMeta),
            "TransactionMetaV1" => Ok(Self::TransactionMetaV1),
            "TransactionMetaV2" => Ok(Self::TransactionMetaV2),
            "ContractEventType" => Ok(Self::ContractEventType),
            "ContractEvent" => Ok(Self::ContractEvent),
            "ContractEventBody" => Ok(Self::ContractEventBody),
            "ContractEventV0" => Ok(Self::ContractEventV0),
            "OperationEvents" => Ok(Self::OperationEvents),
            "TransactionMetaV3" => Ok(Self::TransactionMetaV3),
            "TransactionMeta" => Ok(Self::TransactionMeta),
            "TransactionResultMeta" => Ok(Self::TransactionResultMeta),
            "TransactionResultMetaV2" => Ok(Self::TransactionResultMetaV2),
            "UpgradeEntryMeta" => Ok(Self::UpgradeEntryMeta),
            "LedgerCloseMetaV0" => Ok(Self::LedgerCloseMetaV0),
            "LedgerCloseMetaV1" => Ok(Self::LedgerCloseMetaV1),
            "LedgerCloseMetaV2" => Ok(Self::LedgerCloseMetaV2),
            "LedgerCloseMeta" => Ok(Self::LedgerCloseMeta),
            "ErrorCode" => Ok(Self::ErrorCode),
            "SError" => Ok(Self::SError),
            "SendMore" => Ok(Self::SendMore),
            "AuthCert" => Ok(Self::AuthCert),
            "Hello" => Ok(Self::Hello),
            "Auth" => Ok(Self::Auth),
            "IpAddrType" => Ok(Self::IpAddrType),
            "PeerAddress" => Ok(Self::PeerAddress),
            "PeerAddressIp" => Ok(Self::PeerAddressIp),
            "MessageType" => Ok(Self::MessageType),
            "DontHave" => Ok(Self::DontHave),
            "SurveyMessageCommandType" => Ok(Self::SurveyMessageCommandType),
            "SurveyRequestMessage" => Ok(Self::SurveyRequestMessage),
            "SignedSurveyRequestMessage" => Ok(Self::SignedSurveyRequestMessage),
            "EncryptedBody" => Ok(Self::EncryptedBody),
            "SurveyResponseMessage" => Ok(Self::SurveyResponseMessage),
            "SignedSurveyResponseMessage" => Ok(Self::SignedSurveyResponseMessage),
            "PeerStats" => Ok(Self::PeerStats),
            "PeerStatList" => Ok(Self::PeerStatList),
            "TopologyResponseBody" => Ok(Self::TopologyResponseBody),
            "SurveyResponseBody" => Ok(Self::SurveyResponseBody),
            "TxAdvertVector" => Ok(Self::TxAdvertVector),
            "FloodAdvert" => Ok(Self::FloodAdvert),
            "TxDemandVector" => Ok(Self::TxDemandVector),
            "FloodDemand" => Ok(Self::FloodDemand),
            "StellarMessage" => Ok(Self::StellarMessage),
            "AuthenticatedMessage" => Ok(Self::AuthenticatedMessage),
            "AuthenticatedMessageV0" => Ok(Self::AuthenticatedMessageV0),
            "LiquidityPoolParameters" => Ok(Self::LiquidityPoolParameters),
            "MuxedAccount" => Ok(Self::MuxedAccount),
            "MuxedAccountMed25519" => Ok(Self::MuxedAccountMed25519),
            "DecoratedSignature" => Ok(Self::DecoratedSignature),
            "LedgerFootprint" => Ok(Self::LedgerFootprint),
            "OperationType" => Ok(Self::OperationType),
            "CreateAccountOp" => Ok(Self::CreateAccountOp),
            "PaymentOp" => Ok(Self::PaymentOp),
            "PathPaymentStrictReceiveOp" => Ok(Self::PathPaymentStrictReceiveOp),
            "PathPaymentStrictSendOp" => Ok(Self::PathPaymentStrictSendOp),
            "ManageSellOfferOp" => Ok(Self::ManageSellOfferOp),
            "ManageBuyOfferOp" => Ok(Self::ManageBuyOfferOp),
            "CreatePassiveSellOfferOp" => Ok(Self::CreatePassiveSellOfferOp),
            "SetOptionsOp" => Ok(Self::SetOptionsOp),
            "ChangeTrustAsset" => Ok(Self::ChangeTrustAsset),
            "ChangeTrustOp" => Ok(Self::ChangeTrustOp),
            "AllowTrustOp" => Ok(Self::AllowTrustOp),
            "ManageDataOp" => Ok(Self::ManageDataOp),
            "BumpSequenceOp" => Ok(Self::BumpSequenceOp),
            "CreateClaimableBalanceOp" => Ok(Self::CreateClaimableBalanceOp),
            "ClaimClaimableBalanceOp" => Ok(Self::ClaimClaimableBalanceOp),
            "BeginSponsoringFutureReservesOp" => Ok(Self::BeginSponsoringFutureReservesOp),
            "RevokeSponsorshipType" => Ok(Self::RevokeSponsorshipType),
            "RevokeSponsorshipOp" => Ok(Self::RevokeSponsorshipOp),
            "RevokeSponsorshipOpSigner" => Ok(Self::RevokeSponsorshipOpSigner),
            "ClawbackOp" => Ok(Self::ClawbackOp),
            "ClawbackClaimableBalanceOp" => Ok(Self::ClawbackClaimableBalanceOp),
            "SetTrustLineFlagsOp" => Ok(Self::SetTrustLineFlagsOp),
            "LiquidityPoolDepositOp" => Ok(Self::LiquidityPoolDepositOp),
            "LiquidityPoolWithdrawOp" => Ok(Self::LiquidityPoolWithdrawOp),
            "HostFunctionType" => Ok(Self::HostFunctionType),
            "ContractIdType" => Ok(Self::ContractIdType),
            "ContractIdPublicKeyType" => Ok(Self::ContractIdPublicKeyType),
            "InstallContractCodeArgs" => Ok(Self::InstallContractCodeArgs),
            "ContractId" => Ok(Self::ContractId),
            "ContractIdFromEd25519PublicKey" => Ok(Self::ContractIdFromEd25519PublicKey),
            "CreateContractArgs" => Ok(Self::CreateContractArgs),
            "HostFunction" => Ok(Self::HostFunction),
            "InvokeHostFunctionOp" => Ok(Self::InvokeHostFunctionOp),
            "Operation" => Ok(Self::Operation),
            "OperationBody" => Ok(Self::OperationBody),
            "HashIdPreimage" => Ok(Self::HashIdPreimage),
            "HashIdPreimageOperationId" => Ok(Self::HashIdPreimageOperationId),
            "HashIdPreimageRevokeId" => Ok(Self::HashIdPreimageRevokeId),
            "HashIdPreimageEd25519ContractId" => Ok(Self::HashIdPreimageEd25519ContractId),
            "HashIdPreimageContractId" => Ok(Self::HashIdPreimageContractId),
            "HashIdPreimageFromAsset" => Ok(Self::HashIdPreimageFromAsset),
            "HashIdPreimageSourceAccountContractId" => {
                Ok(Self::HashIdPreimageSourceAccountContractId)
            }
            "HashIdPreimageCreateContractArgs" => Ok(Self::HashIdPreimageCreateContractArgs),
            "MemoType" => Ok(Self::MemoType),
            "Memo" => Ok(Self::Memo),
            "TimeBounds" => Ok(Self::TimeBounds),
            "LedgerBounds" => Ok(Self::LedgerBounds),
            "PreconditionsV2" => Ok(Self::PreconditionsV2),
            "PreconditionType" => Ok(Self::PreconditionType),
            "Preconditions" => Ok(Self::Preconditions),
            "TransactionV0" => Ok(Self::TransactionV0),
            "TransactionV0Ext" => Ok(Self::TransactionV0Ext),
            "TransactionV0Envelope" => Ok(Self::TransactionV0Envelope),
            "Transaction" => Ok(Self::Transaction),
            "TransactionExt" => Ok(Self::TransactionExt),
            "TransactionV1Envelope" => Ok(Self::TransactionV1Envelope),
            "FeeBumpTransaction" => Ok(Self::FeeBumpTransaction),
            "FeeBumpTransactionInnerTx" => Ok(Self::FeeBumpTransactionInnerTx),
            "FeeBumpTransactionExt" => Ok(Self::FeeBumpTransactionExt),
            "FeeBumpTransactionEnvelope" => Ok(Self::FeeBumpTransactionEnvelope),
            "TransactionEnvelope" => Ok(Self::TransactionEnvelope),
            "TransactionSignaturePayload" => Ok(Self::TransactionSignaturePayload),
            "TransactionSignaturePayloadTaggedTransaction" => {
                Ok(Self::TransactionSignaturePayloadTaggedTransaction)
            }
            "ClaimAtomType" => Ok(Self::ClaimAtomType),
            "ClaimOfferAtomV0" => Ok(Self::ClaimOfferAtomV0),
            "ClaimOfferAtom" => Ok(Self::ClaimOfferAtom),
            "ClaimLiquidityAtom" => Ok(Self::ClaimLiquidityAtom),
            "ClaimAtom" => Ok(Self::ClaimAtom),
            "CreateAccountResultCode" => Ok(Self::CreateAccountResultCode),
            "CreateAccountResult" => Ok(Self::CreateAccountResult),
            "PaymentResultCode" => Ok(Self::PaymentResultCode),
            "PaymentResult" => Ok(Self::PaymentResult),
            "PathPaymentStrictReceiveResultCode" => Ok(Self::PathPaymentStrictReceiveResultCode),
            "SimplePaymentResult" => Ok(Self::SimplePaymentResult),
            "PathPaymentStrictReceiveResult" => Ok(Self::PathPaymentStrictReceiveResult),
            "PathPaymentStrictReceiveResultSuccess" => {
                Ok(Self::PathPaymentStrictReceiveResultSuccess)
            }
            "PathPaymentStrictSendResultCode" => Ok(Self::PathPaymentStrictSendResultCode),
            "PathPaymentStrictSendResult" => Ok(Self::PathPaymentStrictSendResult),
            "PathPaymentStrictSendResultSuccess" => Ok(Self::PathPaymentStrictSendResultSuccess),
            "ManageSellOfferResultCode" => Ok(Self::ManageSellOfferResultCode),
            "ManageOfferEffect" => Ok(Self::ManageOfferEffect),
            "ManageOfferSuccessResult" => Ok(Self::ManageOfferSuccessResult),
            "ManageOfferSuccessResultOffer" => Ok(Self::ManageOfferSuccessResultOffer),
            "ManageSellOfferResult" => Ok(Self::ManageSellOfferResult),
            "ManageBuyOfferResultCode" => Ok(Self::ManageBuyOfferResultCode),
            "ManageBuyOfferResult" => Ok(Self::ManageBuyOfferResult),
            "SetOptionsResultCode" => Ok(Self::SetOptionsResultCode),
            "SetOptionsResult" => Ok(Self::SetOptionsResult),
            "ChangeTrustResultCode" => Ok(Self::ChangeTrustResultCode),
            "ChangeTrustResult" => Ok(Self::ChangeTrustResult),
            "AllowTrustResultCode" => Ok(Self::AllowTrustResultCode),
            "AllowTrustResult" => Ok(Self::AllowTrustResult),
            "AccountMergeResultCode" => Ok(Self::AccountMergeResultCode),
            "AccountMergeResult" => Ok(Self::AccountMergeResult),
            "InflationResultCode" => Ok(Self::InflationResultCode),
            "InflationPayout" => Ok(Self::InflationPayout),
            "InflationResult" => Ok(Self::InflationResult),
            "ManageDataResultCode" => Ok(Self::ManageDataResultCode),
            "ManageDataResult" => Ok(Self::ManageDataResult),
            "BumpSequenceResultCode" => Ok(Self::BumpSequenceResultCode),
            "BumpSequenceResult" => Ok(Self::BumpSequenceResult),
            "CreateClaimableBalanceResultCode" => Ok(Self::CreateClaimableBalanceResultCode),
            "CreateClaimableBalanceResult" => Ok(Self::CreateClaimableBalanceResult),
            "ClaimClaimableBalanceResultCode" => Ok(Self::ClaimClaimableBalanceResultCode),
            "ClaimClaimableBalanceResult" => Ok(Self::ClaimClaimableBalanceResult),
            "BeginSponsoringFutureReservesResultCode" => {
                Ok(Self::BeginSponsoringFutureReservesResultCode)
            }
            "BeginSponsoringFutureReservesResult" => Ok(Self::BeginSponsoringFutureReservesResult),
            "EndSponsoringFutureReservesResultCode" => {
                Ok(Self::EndSponsoringFutureReservesResultCode)
            }
            "EndSponsoringFutureReservesResult" => Ok(Self::EndSponsoringFutureReservesResult),
            "RevokeSponsorshipResultCode" => Ok(Self::RevokeSponsorshipResultCode),
            "RevokeSponsorshipResult" => Ok(Self::RevokeSponsorshipResult),
            "ClawbackResultCode" => Ok(Self::ClawbackResultCode),
            "ClawbackResult" => Ok(Self::ClawbackResult),
            "ClawbackClaimableBalanceResultCode" => Ok(Self::ClawbackClaimableBalanceResultCode),
            "ClawbackClaimableBalanceResult" => Ok(Self::ClawbackClaimableBalanceResult),
            "SetTrustLineFlagsResultCode" => Ok(Self::SetTrustLineFlagsResultCode),
            "SetTrustLineFlagsResult" => Ok(Self::SetTrustLineFlagsResult),
            "LiquidityPoolDepositResultCode" => Ok(Self::LiquidityPoolDepositResultCode),
            "LiquidityPoolDepositResult" => Ok(Self::LiquidityPoolDepositResult),
            "LiquidityPoolWithdrawResultCode" => Ok(Self::LiquidityPoolWithdrawResultCode),
            "LiquidityPoolWithdrawResult" => Ok(Self::LiquidityPoolWithdrawResult),
            "InvokeHostFunctionResultCode" => Ok(Self::InvokeHostFunctionResultCode),
            "InvokeHostFunctionResult" => Ok(Self::InvokeHostFunctionResult),
            "OperationResultCode" => Ok(Self::OperationResultCode),
            "OperationResult" => Ok(Self::OperationResult),
            "OperationResultTr" => Ok(Self::OperationResultTr),
            "TransactionResultCode" => Ok(Self::TransactionResultCode),
            "InnerTransactionResult" => Ok(Self::InnerTransactionResult),
            "InnerTransactionResultResult" => Ok(Self::InnerTransactionResultResult),
            "InnerTransactionResultExt" => Ok(Self::InnerTransactionResultExt),
            "InnerTransactionResultPair" => Ok(Self::InnerTransactionResultPair),
            "TransactionResult" => Ok(Self::TransactionResult),
            "TransactionResultResult" => Ok(Self::TransactionResultResult),
            "TransactionResultExt" => Ok(Self::TransactionResultExt),
            "Hash" => Ok(Self::Hash),
            "Uint256" => Ok(Self::Uint256),
            "Uint32" => Ok(Self::Uint32),
            "Int32" => Ok(Self::Int32),
            "Uint64" => Ok(Self::Uint64),
            "Int64" => Ok(Self::Int64),
            "ExtensionPoint" => Ok(Self::ExtensionPoint),
            "CryptoKeyType" => Ok(Self::CryptoKeyType),
            "PublicKeyType" => Ok(Self::PublicKeyType),
            "SignerKeyType" => Ok(Self::SignerKeyType),
            "PublicKey" => Ok(Self::PublicKey),
            "SignerKey" => Ok(Self::SignerKey),
            "SignerKeyEd25519SignedPayload" => Ok(Self::SignerKeyEd25519SignedPayload),
            "Signature" => Ok(Self::Signature),
            "SignatureHint" => Ok(Self::SignatureHint),
            "NodeId" => Ok(Self::NodeId),
            "AccountId" => Ok(Self::AccountId),
            "Curve25519Secret" => Ok(Self::Curve25519Secret),
            "Curve25519Public" => Ok(Self::Curve25519Public),
            "HmacSha256Key" => Ok(Self::HmacSha256Key),
            "HmacSha256Mac" => Ok(Self::HmacSha256Mac),
            _ => Err(Error::Invalid),
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(
    all(feature = "serde", feature = "alloc"),
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "snake_case"),
    serde(untagged)
)]
pub enum Type {
    Value(Box<Value>),
    ScpBallot(Box<ScpBallot>),
    ScpStatementType(Box<ScpStatementType>),
    ScpNomination(Box<ScpNomination>),
    ScpStatement(Box<ScpStatement>),
    ScpStatementPledges(Box<ScpStatementPledges>),
    ScpStatementPrepare(Box<ScpStatementPrepare>),
    ScpStatementConfirm(Box<ScpStatementConfirm>),
    ScpStatementExternalize(Box<ScpStatementExternalize>),
    ScpEnvelope(Box<ScpEnvelope>),
    ScpQuorumSet(Box<ScpQuorumSet>),
    ScEnvMetaKind(Box<ScEnvMetaKind>),
    ScEnvMetaEntry(Box<ScEnvMetaEntry>),
    ScSpecType(Box<ScSpecType>),
    ScSpecTypeOption(Box<ScSpecTypeOption>),
    ScSpecTypeResult(Box<ScSpecTypeResult>),
    ScSpecTypeVec(Box<ScSpecTypeVec>),
    ScSpecTypeMap(Box<ScSpecTypeMap>),
    ScSpecTypeSet(Box<ScSpecTypeSet>),
    ScSpecTypeTuple(Box<ScSpecTypeTuple>),
    ScSpecTypeBytesN(Box<ScSpecTypeBytesN>),
    ScSpecTypeUdt(Box<ScSpecTypeUdt>),
    ScSpecTypeDef(Box<ScSpecTypeDef>),
    ScSpecUdtStructFieldV0(Box<ScSpecUdtStructFieldV0>),
    ScSpecUdtStructV0(Box<ScSpecUdtStructV0>),
    ScSpecUdtUnionCaseV0(Box<ScSpecUdtUnionCaseV0>),
    ScSpecUdtUnionV0(Box<ScSpecUdtUnionV0>),
    ScSpecUdtEnumCaseV0(Box<ScSpecUdtEnumCaseV0>),
    ScSpecUdtEnumV0(Box<ScSpecUdtEnumV0>),
    ScSpecUdtErrorEnumCaseV0(Box<ScSpecUdtErrorEnumCaseV0>),
    ScSpecUdtErrorEnumV0(Box<ScSpecUdtErrorEnumV0>),
    ScSpecFunctionInputV0(Box<ScSpecFunctionInputV0>),
    ScSpecFunctionV0(Box<ScSpecFunctionV0>),
    ScSpecEntryKind(Box<ScSpecEntryKind>),
    ScSpecEntry(Box<ScSpecEntry>),
    ScSymbol(Box<ScSymbol>),
    ScValType(Box<ScValType>),
    ScStatic(Box<ScStatic>),
    ScStatusType(Box<ScStatusType>),
    ScHostValErrorCode(Box<ScHostValErrorCode>),
    ScHostObjErrorCode(Box<ScHostObjErrorCode>),
    ScHostFnErrorCode(Box<ScHostFnErrorCode>),
    ScHostStorageErrorCode(Box<ScHostStorageErrorCode>),
    ScHostContextErrorCode(Box<ScHostContextErrorCode>),
    ScVmErrorCode(Box<ScVmErrorCode>),
    ScUnknownErrorCode(Box<ScUnknownErrorCode>),
    ScStatus(Box<ScStatus>),
    ScVal(Box<ScVal>),
    ScObjectType(Box<ScObjectType>),
    ScMapEntry(Box<ScMapEntry>),
    ScVec(Box<ScVec>),
    ScMap(Box<ScMap>),
    ScContractCodeType(Box<ScContractCodeType>),
    ScContractCode(Box<ScContractCode>),
    Int128Parts(Box<Int128Parts>),
    ScObject(Box<ScObject>),
    StoredTransactionSet(Box<StoredTransactionSet>),
    PersistedScpStateV0(Box<PersistedScpStateV0>),
    PersistedScpStateV1(Box<PersistedScpStateV1>),
    PersistedScpState(Box<PersistedScpState>),
    Thresholds(Box<Thresholds>),
    String32(Box<String32>),
    String64(Box<String64>),
    SequenceNumber(Box<SequenceNumber>),
    TimePoint(Box<TimePoint>),
    Duration(Box<Duration>),
    DataValue(Box<DataValue>),
    PoolId(Box<PoolId>),
    AssetCode4(Box<AssetCode4>),
    AssetCode12(Box<AssetCode12>),
    AssetType(Box<AssetType>),
    AssetCode(Box<AssetCode>),
    AlphaNum4(Box<AlphaNum4>),
    AlphaNum12(Box<AlphaNum12>),
    Asset(Box<Asset>),
    Price(Box<Price>),
    Liabilities(Box<Liabilities>),
    ThresholdIndexes(Box<ThresholdIndexes>),
    LedgerEntryType(Box<LedgerEntryType>),
    Signer(Box<Signer>),
    AccountFlags(Box<AccountFlags>),
    SponsorshipDescriptor(Box<SponsorshipDescriptor>),
    AccountEntryExtensionV3(Box<AccountEntryExtensionV3>),
    AccountEntryExtensionV2(Box<AccountEntryExtensionV2>),
    AccountEntryExtensionV2Ext(Box<AccountEntryExtensionV2Ext>),
    AccountEntryExtensionV1(Box<AccountEntryExtensionV1>),
    AccountEntryExtensionV1Ext(Box<AccountEntryExtensionV1Ext>),
    AccountEntry(Box<AccountEntry>),
    AccountEntryExt(Box<AccountEntryExt>),
    TrustLineFlags(Box<TrustLineFlags>),
    LiquidityPoolType(Box<LiquidityPoolType>),
    TrustLineAsset(Box<TrustLineAsset>),
    TrustLineEntryExtensionV2(Box<TrustLineEntryExtensionV2>),
    TrustLineEntryExtensionV2Ext(Box<TrustLineEntryExtensionV2Ext>),
    TrustLineEntry(Box<TrustLineEntry>),
    TrustLineEntryExt(Box<TrustLineEntryExt>),
    TrustLineEntryV1(Box<TrustLineEntryV1>),
    TrustLineEntryV1Ext(Box<TrustLineEntryV1Ext>),
    OfferEntryFlags(Box<OfferEntryFlags>),
    OfferEntry(Box<OfferEntry>),
    OfferEntryExt(Box<OfferEntryExt>),
    DataEntry(Box<DataEntry>),
    DataEntryExt(Box<DataEntryExt>),
    ClaimPredicateType(Box<ClaimPredicateType>),
    ClaimPredicate(Box<ClaimPredicate>),
    ClaimantType(Box<ClaimantType>),
    Claimant(Box<Claimant>),
    ClaimantV0(Box<ClaimantV0>),
    ClaimableBalanceIdType(Box<ClaimableBalanceIdType>),
    ClaimableBalanceId(Box<ClaimableBalanceId>),
    ClaimableBalanceFlags(Box<ClaimableBalanceFlags>),
    ClaimableBalanceEntryExtensionV1(Box<ClaimableBalanceEntryExtensionV1>),
    ClaimableBalanceEntryExtensionV1Ext(Box<ClaimableBalanceEntryExtensionV1Ext>),
    ClaimableBalanceEntry(Box<ClaimableBalanceEntry>),
    ClaimableBalanceEntryExt(Box<ClaimableBalanceEntryExt>),
    LiquidityPoolConstantProductParameters(Box<LiquidityPoolConstantProductParameters>),
    LiquidityPoolEntry(Box<LiquidityPoolEntry>),
    LiquidityPoolEntryBody(Box<LiquidityPoolEntryBody>),
    LiquidityPoolEntryConstantProduct(Box<LiquidityPoolEntryConstantProduct>),
    ContractDataEntry(Box<ContractDataEntry>),
    ContractCodeEntry(Box<ContractCodeEntry>),
    ConfigSettingType(Box<ConfigSettingType>),
    ConfigSetting(Box<ConfigSetting>),
    ConfigSettingId(Box<ConfigSettingId>),
    ConfigSettingEntry(Box<ConfigSettingEntry>),
    ConfigSettingEntryExt(Box<ConfigSettingEntryExt>),
    LedgerEntryExtensionV1(Box<LedgerEntryExtensionV1>),
    LedgerEntryExtensionV1Ext(Box<LedgerEntryExtensionV1Ext>),
    LedgerEntry(Box<LedgerEntry>),
    LedgerEntryData(Box<LedgerEntryData>),
    LedgerEntryExt(Box<LedgerEntryExt>),
    LedgerKey(Box<LedgerKey>),
    LedgerKeyAccount(Box<LedgerKeyAccount>),
    LedgerKeyTrustLine(Box<LedgerKeyTrustLine>),
    LedgerKeyOffer(Box<LedgerKeyOffer>),
    LedgerKeyData(Box<LedgerKeyData>),
    LedgerKeyClaimableBalance(Box<LedgerKeyClaimableBalance>),
    LedgerKeyLiquidityPool(Box<LedgerKeyLiquidityPool>),
    LedgerKeyContractData(Box<LedgerKeyContractData>),
    LedgerKeyContractCode(Box<LedgerKeyContractCode>),
    LedgerKeyConfigSetting(Box<LedgerKeyConfigSetting>),
    EnvelopeType(Box<EnvelopeType>),
    UpgradeType(Box<UpgradeType>),
    StellarValueType(Box<StellarValueType>),
    LedgerCloseValueSignature(Box<LedgerCloseValueSignature>),
    StellarValue(Box<StellarValue>),
    StellarValueExt(Box<StellarValueExt>),
    LedgerHeaderFlags(Box<LedgerHeaderFlags>),
    LedgerHeaderExtensionV1(Box<LedgerHeaderExtensionV1>),
    LedgerHeaderExtensionV1Ext(Box<LedgerHeaderExtensionV1Ext>),
    LedgerHeader(Box<LedgerHeader>),
    LedgerHeaderExt(Box<LedgerHeaderExt>),
    LedgerUpgradeType(Box<LedgerUpgradeType>),
    LedgerUpgrade(Box<LedgerUpgrade>),
    LedgerUpgradeConfigSetting(Box<LedgerUpgradeConfigSetting>),
    BucketEntryType(Box<BucketEntryType>),
    BucketMetadata(Box<BucketMetadata>),
    BucketMetadataExt(Box<BucketMetadataExt>),
    BucketEntry(Box<BucketEntry>),
    TxSetComponentType(Box<TxSetComponentType>),
    TxSetComponent(Box<TxSetComponent>),
    TxSetComponentTxsMaybeDiscountedFee(Box<TxSetComponentTxsMaybeDiscountedFee>),
    TransactionPhase(Box<TransactionPhase>),
    TransactionSet(Box<TransactionSet>),
    TransactionSetV1(Box<TransactionSetV1>),
    GeneralizedTransactionSet(Box<GeneralizedTransactionSet>),
    TransactionResultPair(Box<TransactionResultPair>),
    TransactionResultSet(Box<TransactionResultSet>),
    TransactionHistoryEntry(Box<TransactionHistoryEntry>),
    TransactionHistoryEntryExt(Box<TransactionHistoryEntryExt>),
    TransactionHistoryResultEntry(Box<TransactionHistoryResultEntry>),
    TransactionHistoryResultEntryExt(Box<TransactionHistoryResultEntryExt>),
    TransactionResultPairV2(Box<TransactionResultPairV2>),
    TransactionResultSetV2(Box<TransactionResultSetV2>),
    TransactionHistoryResultEntryV2(Box<TransactionHistoryResultEntryV2>),
    TransactionHistoryResultEntryV2Ext(Box<TransactionHistoryResultEntryV2Ext>),
    LedgerHeaderHistoryEntry(Box<LedgerHeaderHistoryEntry>),
    LedgerHeaderHistoryEntryExt(Box<LedgerHeaderHistoryEntryExt>),
    LedgerScpMessages(Box<LedgerScpMessages>),
    ScpHistoryEntryV0(Box<ScpHistoryEntryV0>),
    ScpHistoryEntry(Box<ScpHistoryEntry>),
    LedgerEntryChangeType(Box<LedgerEntryChangeType>),
    LedgerEntryChange(Box<LedgerEntryChange>),
    LedgerEntryChanges(Box<LedgerEntryChanges>),
    OperationMeta(Box<OperationMeta>),
    TransactionMetaV1(Box<TransactionMetaV1>),
    TransactionMetaV2(Box<TransactionMetaV2>),
    ContractEventType(Box<ContractEventType>),
    ContractEvent(Box<ContractEvent>),
    ContractEventBody(Box<ContractEventBody>),
    ContractEventV0(Box<ContractEventV0>),
    OperationEvents(Box<OperationEvents>),
    TransactionMetaV3(Box<TransactionMetaV3>),
    TransactionMeta(Box<TransactionMeta>),
    TransactionResultMeta(Box<TransactionResultMeta>),
    TransactionResultMetaV2(Box<TransactionResultMetaV2>),
    UpgradeEntryMeta(Box<UpgradeEntryMeta>),
    LedgerCloseMetaV0(Box<LedgerCloseMetaV0>),
    LedgerCloseMetaV1(Box<LedgerCloseMetaV1>),
    LedgerCloseMetaV2(Box<LedgerCloseMetaV2>),
    LedgerCloseMeta(Box<LedgerCloseMeta>),
    ErrorCode(Box<ErrorCode>),
    SError(Box<SError>),
    SendMore(Box<SendMore>),
    AuthCert(Box<AuthCert>),
    Hello(Box<Hello>),
    Auth(Box<Auth>),
    IpAddrType(Box<IpAddrType>),
    PeerAddress(Box<PeerAddress>),
    PeerAddressIp(Box<PeerAddressIp>),
    MessageType(Box<MessageType>),
    DontHave(Box<DontHave>),
    SurveyMessageCommandType(Box<SurveyMessageCommandType>),
    SurveyRequestMessage(Box<SurveyRequestMessage>),
    SignedSurveyRequestMessage(Box<SignedSurveyRequestMessage>),
    EncryptedBody(Box<EncryptedBody>),
    SurveyResponseMessage(Box<SurveyResponseMessage>),
    SignedSurveyResponseMessage(Box<SignedSurveyResponseMessage>),
    PeerStats(Box<PeerStats>),
    PeerStatList(Box<PeerStatList>),
    TopologyResponseBody(Box<TopologyResponseBody>),
    SurveyResponseBody(Box<SurveyResponseBody>),
    TxAdvertVector(Box<TxAdvertVector>),
    FloodAdvert(Box<FloodAdvert>),
    TxDemandVector(Box<TxDemandVector>),
    FloodDemand(Box<FloodDemand>),
    StellarMessage(Box<StellarMessage>),
    AuthenticatedMessage(Box<AuthenticatedMessage>),
    AuthenticatedMessageV0(Box<AuthenticatedMessageV0>),
    LiquidityPoolParameters(Box<LiquidityPoolParameters>),
    MuxedAccount(Box<MuxedAccount>),
    MuxedAccountMed25519(Box<MuxedAccountMed25519>),
    DecoratedSignature(Box<DecoratedSignature>),
    LedgerFootprint(Box<LedgerFootprint>),
    OperationType(Box<OperationType>),
    CreateAccountOp(Box<CreateAccountOp>),
    PaymentOp(Box<PaymentOp>),
    PathPaymentStrictReceiveOp(Box<PathPaymentStrictReceiveOp>),
    PathPaymentStrictSendOp(Box<PathPaymentStrictSendOp>),
    ManageSellOfferOp(Box<ManageSellOfferOp>),
    ManageBuyOfferOp(Box<ManageBuyOfferOp>),
    CreatePassiveSellOfferOp(Box<CreatePassiveSellOfferOp>),
    SetOptionsOp(Box<SetOptionsOp>),
    ChangeTrustAsset(Box<ChangeTrustAsset>),
    ChangeTrustOp(Box<ChangeTrustOp>),
    AllowTrustOp(Box<AllowTrustOp>),
    ManageDataOp(Box<ManageDataOp>),
    BumpSequenceOp(Box<BumpSequenceOp>),
    CreateClaimableBalanceOp(Box<CreateClaimableBalanceOp>),
    ClaimClaimableBalanceOp(Box<ClaimClaimableBalanceOp>),
    BeginSponsoringFutureReservesOp(Box<BeginSponsoringFutureReservesOp>),
    RevokeSponsorshipType(Box<RevokeSponsorshipType>),
    RevokeSponsorshipOp(Box<RevokeSponsorshipOp>),
    RevokeSponsorshipOpSigner(Box<RevokeSponsorshipOpSigner>),
    ClawbackOp(Box<ClawbackOp>),
    ClawbackClaimableBalanceOp(Box<ClawbackClaimableBalanceOp>),
    SetTrustLineFlagsOp(Box<SetTrustLineFlagsOp>),
    LiquidityPoolDepositOp(Box<LiquidityPoolDepositOp>),
    LiquidityPoolWithdrawOp(Box<LiquidityPoolWithdrawOp>),
    HostFunctionType(Box<HostFunctionType>),
    ContractIdType(Box<ContractIdType>),
    ContractIdPublicKeyType(Box<ContractIdPublicKeyType>),
    InstallContractCodeArgs(Box<InstallContractCodeArgs>),
    ContractId(Box<ContractId>),
    ContractIdFromEd25519PublicKey(Box<ContractIdFromEd25519PublicKey>),
    CreateContractArgs(Box<CreateContractArgs>),
    HostFunction(Box<HostFunction>),
    InvokeHostFunctionOp(Box<InvokeHostFunctionOp>),
    Operation(Box<Operation>),
    OperationBody(Box<OperationBody>),
    HashIdPreimage(Box<HashIdPreimage>),
    HashIdPreimageOperationId(Box<HashIdPreimageOperationId>),
    HashIdPreimageRevokeId(Box<HashIdPreimageRevokeId>),
    HashIdPreimageEd25519ContractId(Box<HashIdPreimageEd25519ContractId>),
    HashIdPreimageContractId(Box<HashIdPreimageContractId>),
    HashIdPreimageFromAsset(Box<HashIdPreimageFromAsset>),
    HashIdPreimageSourceAccountContractId(Box<HashIdPreimageSourceAccountContractId>),
    HashIdPreimageCreateContractArgs(Box<HashIdPreimageCreateContractArgs>),
    MemoType(Box<MemoType>),
    Memo(Box<Memo>),
    TimeBounds(Box<TimeBounds>),
    LedgerBounds(Box<LedgerBounds>),
    PreconditionsV2(Box<PreconditionsV2>),
    PreconditionType(Box<PreconditionType>),
    Preconditions(Box<Preconditions>),
    TransactionV0(Box<TransactionV0>),
    TransactionV0Ext(Box<TransactionV0Ext>),
    TransactionV0Envelope(Box<TransactionV0Envelope>),
    Transaction(Box<Transaction>),
    TransactionExt(Box<TransactionExt>),
    TransactionV1Envelope(Box<TransactionV1Envelope>),
    FeeBumpTransaction(Box<FeeBumpTransaction>),
    FeeBumpTransactionInnerTx(Box<FeeBumpTransactionInnerTx>),
    FeeBumpTransactionExt(Box<FeeBumpTransactionExt>),
    FeeBumpTransactionEnvelope(Box<FeeBumpTransactionEnvelope>),
    TransactionEnvelope(Box<TransactionEnvelope>),
    TransactionSignaturePayload(Box<TransactionSignaturePayload>),
    TransactionSignaturePayloadTaggedTransaction(Box<TransactionSignaturePayloadTaggedTransaction>),
    ClaimAtomType(Box<ClaimAtomType>),
    ClaimOfferAtomV0(Box<ClaimOfferAtomV0>),
    ClaimOfferAtom(Box<ClaimOfferAtom>),
    ClaimLiquidityAtom(Box<ClaimLiquidityAtom>),
    ClaimAtom(Box<ClaimAtom>),
    CreateAccountResultCode(Box<CreateAccountResultCode>),
    CreateAccountResult(Box<CreateAccountResult>),
    PaymentResultCode(Box<PaymentResultCode>),
    PaymentResult(Box<PaymentResult>),
    PathPaymentStrictReceiveResultCode(Box<PathPaymentStrictReceiveResultCode>),
    SimplePaymentResult(Box<SimplePaymentResult>),
    PathPaymentStrictReceiveResult(Box<PathPaymentStrictReceiveResult>),
    PathPaymentStrictReceiveResultSuccess(Box<PathPaymentStrictReceiveResultSuccess>),
    PathPaymentStrictSendResultCode(Box<PathPaymentStrictSendResultCode>),
    PathPaymentStrictSendResult(Box<PathPaymentStrictSendResult>),
    PathPaymentStrictSendResultSuccess(Box<PathPaymentStrictSendResultSuccess>),
    ManageSellOfferResultCode(Box<ManageSellOfferResultCode>),
    ManageOfferEffect(Box<ManageOfferEffect>),
    ManageOfferSuccessResult(Box<ManageOfferSuccessResult>),
    ManageOfferSuccessResultOffer(Box<ManageOfferSuccessResultOffer>),
    ManageSellOfferResult(Box<ManageSellOfferResult>),
    ManageBuyOfferResultCode(Box<ManageBuyOfferResultCode>),
    ManageBuyOfferResult(Box<ManageBuyOfferResult>),
    SetOptionsResultCode(Box<SetOptionsResultCode>),
    SetOptionsResult(Box<SetOptionsResult>),
    ChangeTrustResultCode(Box<ChangeTrustResultCode>),
    ChangeTrustResult(Box<ChangeTrustResult>),
    AllowTrustResultCode(Box<AllowTrustResultCode>),
    AllowTrustResult(Box<AllowTrustResult>),
    AccountMergeResultCode(Box<AccountMergeResultCode>),
    AccountMergeResult(Box<AccountMergeResult>),
    InflationResultCode(Box<InflationResultCode>),
    InflationPayout(Box<InflationPayout>),
    InflationResult(Box<InflationResult>),
    ManageDataResultCode(Box<ManageDataResultCode>),
    ManageDataResult(Box<ManageDataResult>),
    BumpSequenceResultCode(Box<BumpSequenceResultCode>),
    BumpSequenceResult(Box<BumpSequenceResult>),
    CreateClaimableBalanceResultCode(Box<CreateClaimableBalanceResultCode>),
    CreateClaimableBalanceResult(Box<CreateClaimableBalanceResult>),
    ClaimClaimableBalanceResultCode(Box<ClaimClaimableBalanceResultCode>),
    ClaimClaimableBalanceResult(Box<ClaimClaimableBalanceResult>),
    BeginSponsoringFutureReservesResultCode(Box<BeginSponsoringFutureReservesResultCode>),
    BeginSponsoringFutureReservesResult(Box<BeginSponsoringFutureReservesResult>),
    EndSponsoringFutureReservesResultCode(Box<EndSponsoringFutureReservesResultCode>),
    EndSponsoringFutureReservesResult(Box<EndSponsoringFutureReservesResult>),
    RevokeSponsorshipResultCode(Box<RevokeSponsorshipResultCode>),
    RevokeSponsorshipResult(Box<RevokeSponsorshipResult>),
    ClawbackResultCode(Box<ClawbackResultCode>),
    ClawbackResult(Box<ClawbackResult>),
    ClawbackClaimableBalanceResultCode(Box<ClawbackClaimableBalanceResultCode>),
    ClawbackClaimableBalanceResult(Box<ClawbackClaimableBalanceResult>),
    SetTrustLineFlagsResultCode(Box<SetTrustLineFlagsResultCode>),
    SetTrustLineFlagsResult(Box<SetTrustLineFlagsResult>),
    LiquidityPoolDepositResultCode(Box<LiquidityPoolDepositResultCode>),
    LiquidityPoolDepositResult(Box<LiquidityPoolDepositResult>),
    LiquidityPoolWithdrawResultCode(Box<LiquidityPoolWithdrawResultCode>),
    LiquidityPoolWithdrawResult(Box<LiquidityPoolWithdrawResult>),
    InvokeHostFunctionResultCode(Box<InvokeHostFunctionResultCode>),
    InvokeHostFunctionResult(Box<InvokeHostFunctionResult>),
    OperationResultCode(Box<OperationResultCode>),
    OperationResult(Box<OperationResult>),
    OperationResultTr(Box<OperationResultTr>),
    TransactionResultCode(Box<TransactionResultCode>),
    InnerTransactionResult(Box<InnerTransactionResult>),
    InnerTransactionResultResult(Box<InnerTransactionResultResult>),
    InnerTransactionResultExt(Box<InnerTransactionResultExt>),
    InnerTransactionResultPair(Box<InnerTransactionResultPair>),
    TransactionResult(Box<TransactionResult>),
    TransactionResultResult(Box<TransactionResultResult>),
    TransactionResultExt(Box<TransactionResultExt>),
    Hash(Box<Hash>),
    Uint256(Box<Uint256>),
    Uint32(Box<Uint32>),
    Int32(Box<Int32>),
    Uint64(Box<Uint64>),
    Int64(Box<Int64>),
    ExtensionPoint(Box<ExtensionPoint>),
    CryptoKeyType(Box<CryptoKeyType>),
    PublicKeyType(Box<PublicKeyType>),
    SignerKeyType(Box<SignerKeyType>),
    PublicKey(Box<PublicKey>),
    SignerKey(Box<SignerKey>),
    SignerKeyEd25519SignedPayload(Box<SignerKeyEd25519SignedPayload>),
    Signature(Box<Signature>),
    SignatureHint(Box<SignatureHint>),
    NodeId(Box<NodeId>),
    AccountId(Box<AccountId>),
    Curve25519Secret(Box<Curve25519Secret>),
    Curve25519Public(Box<Curve25519Public>),
    HmacSha256Key(Box<HmacSha256Key>),
    HmacSha256Mac(Box<HmacSha256Mac>),
}

impl Type {
    pub const VARIANTS: [TypeVariant; 390] = [
        TypeVariant::Value,
        TypeVariant::ScpBallot,
        TypeVariant::ScpStatementType,
        TypeVariant::ScpNomination,
        TypeVariant::ScpStatement,
        TypeVariant::ScpStatementPledges,
        TypeVariant::ScpStatementPrepare,
        TypeVariant::ScpStatementConfirm,
        TypeVariant::ScpStatementExternalize,
        TypeVariant::ScpEnvelope,
        TypeVariant::ScpQuorumSet,
        TypeVariant::ScEnvMetaKind,
        TypeVariant::ScEnvMetaEntry,
        TypeVariant::ScSpecType,
        TypeVariant::ScSpecTypeOption,
        TypeVariant::ScSpecTypeResult,
        TypeVariant::ScSpecTypeVec,
        TypeVariant::ScSpecTypeMap,
        TypeVariant::ScSpecTypeSet,
        TypeVariant::ScSpecTypeTuple,
        TypeVariant::ScSpecTypeBytesN,
        TypeVariant::ScSpecTypeUdt,
        TypeVariant::ScSpecTypeDef,
        TypeVariant::ScSpecUdtStructFieldV0,
        TypeVariant::ScSpecUdtStructV0,
        TypeVariant::ScSpecUdtUnionCaseV0,
        TypeVariant::ScSpecUdtUnionV0,
        TypeVariant::ScSpecUdtEnumCaseV0,
        TypeVariant::ScSpecUdtEnumV0,
        TypeVariant::ScSpecUdtErrorEnumCaseV0,
        TypeVariant::ScSpecUdtErrorEnumV0,
        TypeVariant::ScSpecFunctionInputV0,
        TypeVariant::ScSpecFunctionV0,
        TypeVariant::ScSpecEntryKind,
        TypeVariant::ScSpecEntry,
        TypeVariant::ScSymbol,
        TypeVariant::ScValType,
        TypeVariant::ScStatic,
        TypeVariant::ScStatusType,
        TypeVariant::ScHostValErrorCode,
        TypeVariant::ScHostObjErrorCode,
        TypeVariant::ScHostFnErrorCode,
        TypeVariant::ScHostStorageErrorCode,
        TypeVariant::ScHostContextErrorCode,
        TypeVariant::ScVmErrorCode,
        TypeVariant::ScUnknownErrorCode,
        TypeVariant::ScStatus,
        TypeVariant::ScVal,
        TypeVariant::ScObjectType,
        TypeVariant::ScMapEntry,
        TypeVariant::ScVec,
        TypeVariant::ScMap,
        TypeVariant::ScContractCodeType,
        TypeVariant::ScContractCode,
        TypeVariant::Int128Parts,
        TypeVariant::ScObject,
        TypeVariant::StoredTransactionSet,
        TypeVariant::PersistedScpStateV0,
        TypeVariant::PersistedScpStateV1,
        TypeVariant::PersistedScpState,
        TypeVariant::Thresholds,
        TypeVariant::String32,
        TypeVariant::String64,
        TypeVariant::SequenceNumber,
        TypeVariant::TimePoint,
        TypeVariant::Duration,
        TypeVariant::DataValue,
        TypeVariant::PoolId,
        TypeVariant::AssetCode4,
        TypeVariant::AssetCode12,
        TypeVariant::AssetType,
        TypeVariant::AssetCode,
        TypeVariant::AlphaNum4,
        TypeVariant::AlphaNum12,
        TypeVariant::Asset,
        TypeVariant::Price,
        TypeVariant::Liabilities,
        TypeVariant::ThresholdIndexes,
        TypeVariant::LedgerEntryType,
        TypeVariant::Signer,
        TypeVariant::AccountFlags,
        TypeVariant::SponsorshipDescriptor,
        TypeVariant::AccountEntryExtensionV3,
        TypeVariant::AccountEntryExtensionV2,
        TypeVariant::AccountEntryExtensionV2Ext,
        TypeVariant::AccountEntryExtensionV1,
        TypeVariant::AccountEntryExtensionV1Ext,
        TypeVariant::AccountEntry,
        TypeVariant::AccountEntryExt,
        TypeVariant::TrustLineFlags,
        TypeVariant::LiquidityPoolType,
        TypeVariant::TrustLineAsset,
        TypeVariant::TrustLineEntryExtensionV2,
        TypeVariant::TrustLineEntryExtensionV2Ext,
        TypeVariant::TrustLineEntry,
        TypeVariant::TrustLineEntryExt,
        TypeVariant::TrustLineEntryV1,
        TypeVariant::TrustLineEntryV1Ext,
        TypeVariant::OfferEntryFlags,
        TypeVariant::OfferEntry,
        TypeVariant::OfferEntryExt,
        TypeVariant::DataEntry,
        TypeVariant::DataEntryExt,
        TypeVariant::ClaimPredicateType,
        TypeVariant::ClaimPredicate,
        TypeVariant::ClaimantType,
        TypeVariant::Claimant,
        TypeVariant::ClaimantV0,
        TypeVariant::ClaimableBalanceIdType,
        TypeVariant::ClaimableBalanceId,
        TypeVariant::ClaimableBalanceFlags,
        TypeVariant::ClaimableBalanceEntryExtensionV1,
        TypeVariant::ClaimableBalanceEntryExtensionV1Ext,
        TypeVariant::ClaimableBalanceEntry,
        TypeVariant::ClaimableBalanceEntryExt,
        TypeVariant::LiquidityPoolConstantProductParameters,
        TypeVariant::LiquidityPoolEntry,
        TypeVariant::LiquidityPoolEntryBody,
        TypeVariant::LiquidityPoolEntryConstantProduct,
        TypeVariant::ContractDataEntry,
        TypeVariant::ContractCodeEntry,
        TypeVariant::ConfigSettingType,
        TypeVariant::ConfigSetting,
        TypeVariant::ConfigSettingId,
        TypeVariant::ConfigSettingEntry,
        TypeVariant::ConfigSettingEntryExt,
        TypeVariant::LedgerEntryExtensionV1,
        TypeVariant::LedgerEntryExtensionV1Ext,
        TypeVariant::LedgerEntry,
        TypeVariant::LedgerEntryData,
        TypeVariant::LedgerEntryExt,
        TypeVariant::LedgerKey,
        TypeVariant::LedgerKeyAccount,
        TypeVariant::LedgerKeyTrustLine,
        TypeVariant::LedgerKeyOffer,
        TypeVariant::LedgerKeyData,
        TypeVariant::LedgerKeyClaimableBalance,
        TypeVariant::LedgerKeyLiquidityPool,
        TypeVariant::LedgerKeyContractData,
        TypeVariant::LedgerKeyContractCode,
        TypeVariant::LedgerKeyConfigSetting,
        TypeVariant::EnvelopeType,
        TypeVariant::UpgradeType,
        TypeVariant::StellarValueType,
        TypeVariant::LedgerCloseValueSignature,
        TypeVariant::StellarValue,
        TypeVariant::StellarValueExt,
        TypeVariant::LedgerHeaderFlags,
        TypeVariant::LedgerHeaderExtensionV1,
        TypeVariant::LedgerHeaderExtensionV1Ext,
        TypeVariant::LedgerHeader,
        TypeVariant::LedgerHeaderExt,
        TypeVariant::LedgerUpgradeType,
        TypeVariant::LedgerUpgrade,
        TypeVariant::LedgerUpgradeConfigSetting,
        TypeVariant::BucketEntryType,
        TypeVariant::BucketMetadata,
        TypeVariant::BucketMetadataExt,
        TypeVariant::BucketEntry,
        TypeVariant::TxSetComponentType,
        TypeVariant::TxSetComponent,
        TypeVariant::TxSetComponentTxsMaybeDiscountedFee,
        TypeVariant::TransactionPhase,
        TypeVariant::TransactionSet,
        TypeVariant::TransactionSetV1,
        TypeVariant::GeneralizedTransactionSet,
        TypeVariant::TransactionResultPair,
        TypeVariant::TransactionResultSet,
        TypeVariant::TransactionHistoryEntry,
        TypeVariant::TransactionHistoryEntryExt,
        TypeVariant::TransactionHistoryResultEntry,
        TypeVariant::TransactionHistoryResultEntryExt,
        TypeVariant::TransactionResultPairV2,
        TypeVariant::TransactionResultSetV2,
        TypeVariant::TransactionHistoryResultEntryV2,
        TypeVariant::TransactionHistoryResultEntryV2Ext,
        TypeVariant::LedgerHeaderHistoryEntry,
        TypeVariant::LedgerHeaderHistoryEntryExt,
        TypeVariant::LedgerScpMessages,
        TypeVariant::ScpHistoryEntryV0,
        TypeVariant::ScpHistoryEntry,
        TypeVariant::LedgerEntryChangeType,
        TypeVariant::LedgerEntryChange,
        TypeVariant::LedgerEntryChanges,
        TypeVariant::OperationMeta,
        TypeVariant::TransactionMetaV1,
        TypeVariant::TransactionMetaV2,
        TypeVariant::ContractEventType,
        TypeVariant::ContractEvent,
        TypeVariant::ContractEventBody,
        TypeVariant::ContractEventV0,
        TypeVariant::OperationEvents,
        TypeVariant::TransactionMetaV3,
        TypeVariant::TransactionMeta,
        TypeVariant::TransactionResultMeta,
        TypeVariant::TransactionResultMetaV2,
        TypeVariant::UpgradeEntryMeta,
        TypeVariant::LedgerCloseMetaV0,
        TypeVariant::LedgerCloseMetaV1,
        TypeVariant::LedgerCloseMetaV2,
        TypeVariant::LedgerCloseMeta,
        TypeVariant::ErrorCode,
        TypeVariant::SError,
        TypeVariant::SendMore,
        TypeVariant::AuthCert,
        TypeVariant::Hello,
        TypeVariant::Auth,
        TypeVariant::IpAddrType,
        TypeVariant::PeerAddress,
        TypeVariant::PeerAddressIp,
        TypeVariant::MessageType,
        TypeVariant::DontHave,
        TypeVariant::SurveyMessageCommandType,
        TypeVariant::SurveyRequestMessage,
        TypeVariant::SignedSurveyRequestMessage,
        TypeVariant::EncryptedBody,
        TypeVariant::SurveyResponseMessage,
        TypeVariant::SignedSurveyResponseMessage,
        TypeVariant::PeerStats,
        TypeVariant::PeerStatList,
        TypeVariant::TopologyResponseBody,
        TypeVariant::SurveyResponseBody,
        TypeVariant::TxAdvertVector,
        TypeVariant::FloodAdvert,
        TypeVariant::TxDemandVector,
        TypeVariant::FloodDemand,
        TypeVariant::StellarMessage,
        TypeVariant::AuthenticatedMessage,
        TypeVariant::AuthenticatedMessageV0,
        TypeVariant::LiquidityPoolParameters,
        TypeVariant::MuxedAccount,
        TypeVariant::MuxedAccountMed25519,
        TypeVariant::DecoratedSignature,
        TypeVariant::LedgerFootprint,
        TypeVariant::OperationType,
        TypeVariant::CreateAccountOp,
        TypeVariant::PaymentOp,
        TypeVariant::PathPaymentStrictReceiveOp,
        TypeVariant::PathPaymentStrictSendOp,
        TypeVariant::ManageSellOfferOp,
        TypeVariant::ManageBuyOfferOp,
        TypeVariant::CreatePassiveSellOfferOp,
        TypeVariant::SetOptionsOp,
        TypeVariant::ChangeTrustAsset,
        TypeVariant::ChangeTrustOp,
        TypeVariant::AllowTrustOp,
        TypeVariant::ManageDataOp,
        TypeVariant::BumpSequenceOp,
        TypeVariant::CreateClaimableBalanceOp,
        TypeVariant::ClaimClaimableBalanceOp,
        TypeVariant::BeginSponsoringFutureReservesOp,
        TypeVariant::RevokeSponsorshipType,
        TypeVariant::RevokeSponsorshipOp,
        TypeVariant::RevokeSponsorshipOpSigner,
        TypeVariant::ClawbackOp,
        TypeVariant::ClawbackClaimableBalanceOp,
        TypeVariant::SetTrustLineFlagsOp,
        TypeVariant::LiquidityPoolDepositOp,
        TypeVariant::LiquidityPoolWithdrawOp,
        TypeVariant::HostFunctionType,
        TypeVariant::ContractIdType,
        TypeVariant::ContractIdPublicKeyType,
        TypeVariant::InstallContractCodeArgs,
        TypeVariant::ContractId,
        TypeVariant::ContractIdFromEd25519PublicKey,
        TypeVariant::CreateContractArgs,
        TypeVariant::HostFunction,
        TypeVariant::InvokeHostFunctionOp,
        TypeVariant::Operation,
        TypeVariant::OperationBody,
        TypeVariant::HashIdPreimage,
        TypeVariant::HashIdPreimageOperationId,
        TypeVariant::HashIdPreimageRevokeId,
        TypeVariant::HashIdPreimageEd25519ContractId,
        TypeVariant::HashIdPreimageContractId,
        TypeVariant::HashIdPreimageFromAsset,
        TypeVariant::HashIdPreimageSourceAccountContractId,
        TypeVariant::HashIdPreimageCreateContractArgs,
        TypeVariant::MemoType,
        TypeVariant::Memo,
        TypeVariant::TimeBounds,
        TypeVariant::LedgerBounds,
        TypeVariant::PreconditionsV2,
        TypeVariant::PreconditionType,
        TypeVariant::Preconditions,
        TypeVariant::TransactionV0,
        TypeVariant::TransactionV0Ext,
        TypeVariant::TransactionV0Envelope,
        TypeVariant::Transaction,
        TypeVariant::TransactionExt,
        TypeVariant::TransactionV1Envelope,
        TypeVariant::FeeBumpTransaction,
        TypeVariant::FeeBumpTransactionInnerTx,
        TypeVariant::FeeBumpTransactionExt,
        TypeVariant::FeeBumpTransactionEnvelope,
        TypeVariant::TransactionEnvelope,
        TypeVariant::TransactionSignaturePayload,
        TypeVariant::TransactionSignaturePayloadTaggedTransaction,
        TypeVariant::ClaimAtomType,
        TypeVariant::ClaimOfferAtomV0,
        TypeVariant::ClaimOfferAtom,
        TypeVariant::ClaimLiquidityAtom,
        TypeVariant::ClaimAtom,
        TypeVariant::CreateAccountResultCode,
        TypeVariant::CreateAccountResult,
        TypeVariant::PaymentResultCode,
        TypeVariant::PaymentResult,
        TypeVariant::PathPaymentStrictReceiveResultCode,
        TypeVariant::SimplePaymentResult,
        TypeVariant::PathPaymentStrictReceiveResult,
        TypeVariant::PathPaymentStrictReceiveResultSuccess,
        TypeVariant::PathPaymentStrictSendResultCode,
        TypeVariant::PathPaymentStrictSendResult,
        TypeVariant::PathPaymentStrictSendResultSuccess,
        TypeVariant::ManageSellOfferResultCode,
        TypeVariant::ManageOfferEffect,
        TypeVariant::ManageOfferSuccessResult,
        TypeVariant::ManageOfferSuccessResultOffer,
        TypeVariant::ManageSellOfferResult,
        TypeVariant::ManageBuyOfferResultCode,
        TypeVariant::ManageBuyOfferResult,
        TypeVariant::SetOptionsResultCode,
        TypeVariant::SetOptionsResult,
        TypeVariant::ChangeTrustResultCode,
        TypeVariant::ChangeTrustResult,
        TypeVariant::AllowTrustResultCode,
        TypeVariant::AllowTrustResult,
        TypeVariant::AccountMergeResultCode,
        TypeVariant::AccountMergeResult,
        TypeVariant::InflationResultCode,
        TypeVariant::InflationPayout,
        TypeVariant::InflationResult,
        TypeVariant::ManageDataResultCode,
        TypeVariant::ManageDataResult,
        TypeVariant::BumpSequenceResultCode,
        TypeVariant::BumpSequenceResult,
        TypeVariant::CreateClaimableBalanceResultCode,
        TypeVariant::CreateClaimableBalanceResult,
        TypeVariant::ClaimClaimableBalanceResultCode,
        TypeVariant::ClaimClaimableBalanceResult,
        TypeVariant::BeginSponsoringFutureReservesResultCode,
        TypeVariant::BeginSponsoringFutureReservesResult,
        TypeVariant::EndSponsoringFutureReservesResultCode,
        TypeVariant::EndSponsoringFutureReservesResult,
        TypeVariant::RevokeSponsorshipResultCode,
        TypeVariant::RevokeSponsorshipResult,
        TypeVariant::ClawbackResultCode,
        TypeVariant::ClawbackResult,
        TypeVariant::ClawbackClaimableBalanceResultCode,
        TypeVariant::ClawbackClaimableBalanceResult,
        TypeVariant::SetTrustLineFlagsResultCode,
        TypeVariant::SetTrustLineFlagsResult,
        TypeVariant::LiquidityPoolDepositResultCode,
        TypeVariant::LiquidityPoolDepositResult,
        TypeVariant::LiquidityPoolWithdrawResultCode,
        TypeVariant::LiquidityPoolWithdrawResult,
        TypeVariant::InvokeHostFunctionResultCode,
        TypeVariant::InvokeHostFunctionResult,
        TypeVariant::OperationResultCode,
        TypeVariant::OperationResult,
        TypeVariant::OperationResultTr,
        TypeVariant::TransactionResultCode,
        TypeVariant::InnerTransactionResult,
        TypeVariant::InnerTransactionResultResult,
        TypeVariant::InnerTransactionResultExt,
        TypeVariant::InnerTransactionResultPair,
        TypeVariant::TransactionResult,
        TypeVariant::TransactionResultResult,
        TypeVariant::TransactionResultExt,
        TypeVariant::Hash,
        TypeVariant::Uint256,
        TypeVariant::Uint32,
        TypeVariant::Int32,
        TypeVariant::Uint64,
        TypeVariant::Int64,
        TypeVariant::ExtensionPoint,
        TypeVariant::CryptoKeyType,
        TypeVariant::PublicKeyType,
        TypeVariant::SignerKeyType,
        TypeVariant::PublicKey,
        TypeVariant::SignerKey,
        TypeVariant::SignerKeyEd25519SignedPayload,
        TypeVariant::Signature,
        TypeVariant::SignatureHint,
        TypeVariant::NodeId,
        TypeVariant::AccountId,
        TypeVariant::Curve25519Secret,
        TypeVariant::Curve25519Public,
        TypeVariant::HmacSha256Key,
        TypeVariant::HmacSha256Mac,
    ];
    pub const VARIANTS_STR: [&'static str; 390] = [
        "Value",
        "ScpBallot",
        "ScpStatementType",
        "ScpNomination",
        "ScpStatement",
        "ScpStatementPledges",
        "ScpStatementPrepare",
        "ScpStatementConfirm",
        "ScpStatementExternalize",
        "ScpEnvelope",
        "ScpQuorumSet",
        "ScEnvMetaKind",
        "ScEnvMetaEntry",
        "ScSpecType",
        "ScSpecTypeOption",
        "ScSpecTypeResult",
        "ScSpecTypeVec",
        "ScSpecTypeMap",
        "ScSpecTypeSet",
        "ScSpecTypeTuple",
        "ScSpecTypeBytesN",
        "ScSpecTypeUdt",
        "ScSpecTypeDef",
        "ScSpecUdtStructFieldV0",
        "ScSpecUdtStructV0",
        "ScSpecUdtUnionCaseV0",
        "ScSpecUdtUnionV0",
        "ScSpecUdtEnumCaseV0",
        "ScSpecUdtEnumV0",
        "ScSpecUdtErrorEnumCaseV0",
        "ScSpecUdtErrorEnumV0",
        "ScSpecFunctionInputV0",
        "ScSpecFunctionV0",
        "ScSpecEntryKind",
        "ScSpecEntry",
        "ScSymbol",
        "ScValType",
        "ScStatic",
        "ScStatusType",
        "ScHostValErrorCode",
        "ScHostObjErrorCode",
        "ScHostFnErrorCode",
        "ScHostStorageErrorCode",
        "ScHostContextErrorCode",
        "ScVmErrorCode",
        "ScUnknownErrorCode",
        "ScStatus",
        "ScVal",
        "ScObjectType",
        "ScMapEntry",
        "ScVec",
        "ScMap",
        "ScContractCodeType",
        "ScContractCode",
        "Int128Parts",
        "ScObject",
        "StoredTransactionSet",
        "PersistedScpStateV0",
        "PersistedScpStateV1",
        "PersistedScpState",
        "Thresholds",
        "String32",
        "String64",
        "SequenceNumber",
        "TimePoint",
        "Duration",
        "DataValue",
        "PoolId",
        "AssetCode4",
        "AssetCode12",
        "AssetType",
        "AssetCode",
        "AlphaNum4",
        "AlphaNum12",
        "Asset",
        "Price",
        "Liabilities",
        "ThresholdIndexes",
        "LedgerEntryType",
        "Signer",
        "AccountFlags",
        "SponsorshipDescriptor",
        "AccountEntryExtensionV3",
        "AccountEntryExtensionV2",
        "AccountEntryExtensionV2Ext",
        "AccountEntryExtensionV1",
        "AccountEntryExtensionV1Ext",
        "AccountEntry",
        "AccountEntryExt",
        "TrustLineFlags",
        "LiquidityPoolType",
        "TrustLineAsset",
        "TrustLineEntryExtensionV2",
        "TrustLineEntryExtensionV2Ext",
        "TrustLineEntry",
        "TrustLineEntryExt",
        "TrustLineEntryV1",
        "TrustLineEntryV1Ext",
        "OfferEntryFlags",
        "OfferEntry",
        "OfferEntryExt",
        "DataEntry",
        "DataEntryExt",
        "ClaimPredicateType",
        "ClaimPredicate",
        "ClaimantType",
        "Claimant",
        "ClaimantV0",
        "ClaimableBalanceIdType",
        "ClaimableBalanceId",
        "ClaimableBalanceFlags",
        "ClaimableBalanceEntryExtensionV1",
        "ClaimableBalanceEntryExtensionV1Ext",
        "ClaimableBalanceEntry",
        "ClaimableBalanceEntryExt",
        "LiquidityPoolConstantProductParameters",
        "LiquidityPoolEntry",
        "LiquidityPoolEntryBody",
        "LiquidityPoolEntryConstantProduct",
        "ContractDataEntry",
        "ContractCodeEntry",
        "ConfigSettingType",
        "ConfigSetting",
        "ConfigSettingId",
        "ConfigSettingEntry",
        "ConfigSettingEntryExt",
        "LedgerEntryExtensionV1",
        "LedgerEntryExtensionV1Ext",
        "LedgerEntry",
        "LedgerEntryData",
        "LedgerEntryExt",
        "LedgerKey",
        "LedgerKeyAccount",
        "LedgerKeyTrustLine",
        "LedgerKeyOffer",
        "LedgerKeyData",
        "LedgerKeyClaimableBalance",
        "LedgerKeyLiquidityPool",
        "LedgerKeyContractData",
        "LedgerKeyContractCode",
        "LedgerKeyConfigSetting",
        "EnvelopeType",
        "UpgradeType",
        "StellarValueType",
        "LedgerCloseValueSignature",
        "StellarValue",
        "StellarValueExt",
        "LedgerHeaderFlags",
        "LedgerHeaderExtensionV1",
        "LedgerHeaderExtensionV1Ext",
        "LedgerHeader",
        "LedgerHeaderExt",
        "LedgerUpgradeType",
        "LedgerUpgrade",
        "LedgerUpgradeConfigSetting",
        "BucketEntryType",
        "BucketMetadata",
        "BucketMetadataExt",
        "BucketEntry",
        "TxSetComponentType",
        "TxSetComponent",
        "TxSetComponentTxsMaybeDiscountedFee",
        "TransactionPhase",
        "TransactionSet",
        "TransactionSetV1",
        "GeneralizedTransactionSet",
        "TransactionResultPair",
        "TransactionResultSet",
        "TransactionHistoryEntry",
        "TransactionHistoryEntryExt",
        "TransactionHistoryResultEntry",
        "TransactionHistoryResultEntryExt",
        "TransactionResultPairV2",
        "TransactionResultSetV2",
        "TransactionHistoryResultEntryV2",
        "TransactionHistoryResultEntryV2Ext",
        "LedgerHeaderHistoryEntry",
        "LedgerHeaderHistoryEntryExt",
        "LedgerScpMessages",
        "ScpHistoryEntryV0",
        "ScpHistoryEntry",
        "LedgerEntryChangeType",
        "LedgerEntryChange",
        "LedgerEntryChanges",
        "OperationMeta",
        "TransactionMetaV1",
        "TransactionMetaV2",
        "ContractEventType",
        "ContractEvent",
        "ContractEventBody",
        "ContractEventV0",
        "OperationEvents",
        "TransactionMetaV3",
        "TransactionMeta",
        "TransactionResultMeta",
        "TransactionResultMetaV2",
        "UpgradeEntryMeta",
        "LedgerCloseMetaV0",
        "LedgerCloseMetaV1",
        "LedgerCloseMetaV2",
        "LedgerCloseMeta",
        "ErrorCode",
        "SError",
        "SendMore",
        "AuthCert",
        "Hello",
        "Auth",
        "IpAddrType",
        "PeerAddress",
        "PeerAddressIp",
        "MessageType",
        "DontHave",
        "SurveyMessageCommandType",
        "SurveyRequestMessage",
        "SignedSurveyRequestMessage",
        "EncryptedBody",
        "SurveyResponseMessage",
        "SignedSurveyResponseMessage",
        "PeerStats",
        "PeerStatList",
        "TopologyResponseBody",
        "SurveyResponseBody",
        "TxAdvertVector",
        "FloodAdvert",
        "TxDemandVector",
        "FloodDemand",
        "StellarMessage",
        "AuthenticatedMessage",
        "AuthenticatedMessageV0",
        "LiquidityPoolParameters",
        "MuxedAccount",
        "MuxedAccountMed25519",
        "DecoratedSignature",
        "LedgerFootprint",
        "OperationType",
        "CreateAccountOp",
        "PaymentOp",
        "PathPaymentStrictReceiveOp",
        "PathPaymentStrictSendOp",
        "ManageSellOfferOp",
        "ManageBuyOfferOp",
        "CreatePassiveSellOfferOp",
        "SetOptionsOp",
        "ChangeTrustAsset",
        "ChangeTrustOp",
        "AllowTrustOp",
        "ManageDataOp",
        "BumpSequenceOp",
        "CreateClaimableBalanceOp",
        "ClaimClaimableBalanceOp",
        "BeginSponsoringFutureReservesOp",
        "RevokeSponsorshipType",
        "RevokeSponsorshipOp",
        "RevokeSponsorshipOpSigner",
        "ClawbackOp",
        "ClawbackClaimableBalanceOp",
        "SetTrustLineFlagsOp",
        "LiquidityPoolDepositOp",
        "LiquidityPoolWithdrawOp",
        "HostFunctionType",
        "ContractIdType",
        "ContractIdPublicKeyType",
        "InstallContractCodeArgs",
        "ContractId",
        "ContractIdFromEd25519PublicKey",
        "CreateContractArgs",
        "HostFunction",
        "InvokeHostFunctionOp",
        "Operation",
        "OperationBody",
        "HashIdPreimage",
        "HashIdPreimageOperationId",
        "HashIdPreimageRevokeId",
        "HashIdPreimageEd25519ContractId",
        "HashIdPreimageContractId",
        "HashIdPreimageFromAsset",
        "HashIdPreimageSourceAccountContractId",
        "HashIdPreimageCreateContractArgs",
        "MemoType",
        "Memo",
        "TimeBounds",
        "LedgerBounds",
        "PreconditionsV2",
        "PreconditionType",
        "Preconditions",
        "TransactionV0",
        "TransactionV0Ext",
        "TransactionV0Envelope",
        "Transaction",
        "TransactionExt",
        "TransactionV1Envelope",
        "FeeBumpTransaction",
        "FeeBumpTransactionInnerTx",
        "FeeBumpTransactionExt",
        "FeeBumpTransactionEnvelope",
        "TransactionEnvelope",
        "TransactionSignaturePayload",
        "TransactionSignaturePayloadTaggedTransaction",
        "ClaimAtomType",
        "ClaimOfferAtomV0",
        "ClaimOfferAtom",
        "ClaimLiquidityAtom",
        "ClaimAtom",
        "CreateAccountResultCode",
        "CreateAccountResult",
        "PaymentResultCode",
        "PaymentResult",
        "PathPaymentStrictReceiveResultCode",
        "SimplePaymentResult",
        "PathPaymentStrictReceiveResult",
        "PathPaymentStrictReceiveResultSuccess",
        "PathPaymentStrictSendResultCode",
        "PathPaymentStrictSendResult",
        "PathPaymentStrictSendResultSuccess",
        "ManageSellOfferResultCode",
        "ManageOfferEffect",
        "ManageOfferSuccessResult",
        "ManageOfferSuccessResultOffer",
        "ManageSellOfferResult",
        "ManageBuyOfferResultCode",
        "ManageBuyOfferResult",
        "SetOptionsResultCode",
        "SetOptionsResult",
        "ChangeTrustResultCode",
        "ChangeTrustResult",
        "AllowTrustResultCode",
        "AllowTrustResult",
        "AccountMergeResultCode",
        "AccountMergeResult",
        "InflationResultCode",
        "InflationPayout",
        "InflationResult",
        "ManageDataResultCode",
        "ManageDataResult",
        "BumpSequenceResultCode",
        "BumpSequenceResult",
        "CreateClaimableBalanceResultCode",
        "CreateClaimableBalanceResult",
        "ClaimClaimableBalanceResultCode",
        "ClaimClaimableBalanceResult",
        "BeginSponsoringFutureReservesResultCode",
        "BeginSponsoringFutureReservesResult",
        "EndSponsoringFutureReservesResultCode",
        "EndSponsoringFutureReservesResult",
        "RevokeSponsorshipResultCode",
        "RevokeSponsorshipResult",
        "ClawbackResultCode",
        "ClawbackResult",
        "ClawbackClaimableBalanceResultCode",
        "ClawbackClaimableBalanceResult",
        "SetTrustLineFlagsResultCode",
        "SetTrustLineFlagsResult",
        "LiquidityPoolDepositResultCode",
        "LiquidityPoolDepositResult",
        "LiquidityPoolWithdrawResultCode",
        "LiquidityPoolWithdrawResult",
        "InvokeHostFunctionResultCode",
        "InvokeHostFunctionResult",
        "OperationResultCode",
        "OperationResult",
        "OperationResultTr",
        "TransactionResultCode",
        "InnerTransactionResult",
        "InnerTransactionResultResult",
        "InnerTransactionResultExt",
        "InnerTransactionResultPair",
        "TransactionResult",
        "TransactionResultResult",
        "TransactionResultExt",
        "Hash",
        "Uint256",
        "Uint32",
        "Int32",
        "Uint64",
        "Int64",
        "ExtensionPoint",
        "CryptoKeyType",
        "PublicKeyType",
        "SignerKeyType",
        "PublicKey",
        "SignerKey",
        "SignerKeyEd25519SignedPayload",
        "Signature",
        "SignatureHint",
        "NodeId",
        "AccountId",
        "Curve25519Secret",
        "Curve25519Public",
        "HmacSha256Key",
        "HmacSha256Mac",
    ];

    #[cfg(feature = "std")]
    #[allow(clippy::too_many_lines)]
    pub fn read_xdr(v: TypeVariant, r: &mut impl Read) -> Result<Self> {
        match v {
            TypeVariant::Value => Ok(Self::Value(Box::new(Value::read_xdr(r)?))),
            TypeVariant::ScpBallot => Ok(Self::ScpBallot(Box::new(ScpBallot::read_xdr(r)?))),
            TypeVariant::ScpStatementType => Ok(Self::ScpStatementType(Box::new(
                ScpStatementType::read_xdr(r)?,
            ))),
            TypeVariant::ScpNomination => {
                Ok(Self::ScpNomination(Box::new(ScpNomination::read_xdr(r)?)))
            }
            TypeVariant::ScpStatement => {
                Ok(Self::ScpStatement(Box::new(ScpStatement::read_xdr(r)?)))
            }
            TypeVariant::ScpStatementPledges => Ok(Self::ScpStatementPledges(Box::new(
                ScpStatementPledges::read_xdr(r)?,
            ))),
            TypeVariant::ScpStatementPrepare => Ok(Self::ScpStatementPrepare(Box::new(
                ScpStatementPrepare::read_xdr(r)?,
            ))),
            TypeVariant::ScpStatementConfirm => Ok(Self::ScpStatementConfirm(Box::new(
                ScpStatementConfirm::read_xdr(r)?,
            ))),
            TypeVariant::ScpStatementExternalize => Ok(Self::ScpStatementExternalize(Box::new(
                ScpStatementExternalize::read_xdr(r)?,
            ))),
            TypeVariant::ScpEnvelope => Ok(Self::ScpEnvelope(Box::new(ScpEnvelope::read_xdr(r)?))),
            TypeVariant::ScpQuorumSet => {
                Ok(Self::ScpQuorumSet(Box::new(ScpQuorumSet::read_xdr(r)?)))
            }
            TypeVariant::ScEnvMetaKind => {
                Ok(Self::ScEnvMetaKind(Box::new(ScEnvMetaKind::read_xdr(r)?)))
            }
            TypeVariant::ScEnvMetaEntry => {
                Ok(Self::ScEnvMetaEntry(Box::new(ScEnvMetaEntry::read_xdr(r)?)))
            }
            TypeVariant::ScSpecType => Ok(Self::ScSpecType(Box::new(ScSpecType::read_xdr(r)?))),
            TypeVariant::ScSpecTypeOption => Ok(Self::ScSpecTypeOption(Box::new(
                ScSpecTypeOption::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecTypeResult => Ok(Self::ScSpecTypeResult(Box::new(
                ScSpecTypeResult::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecTypeVec => {
                Ok(Self::ScSpecTypeVec(Box::new(ScSpecTypeVec::read_xdr(r)?)))
            }
            TypeVariant::ScSpecTypeMap => {
                Ok(Self::ScSpecTypeMap(Box::new(ScSpecTypeMap::read_xdr(r)?)))
            }
            TypeVariant::ScSpecTypeSet => {
                Ok(Self::ScSpecTypeSet(Box::new(ScSpecTypeSet::read_xdr(r)?)))
            }
            TypeVariant::ScSpecTypeTuple => Ok(Self::ScSpecTypeTuple(Box::new(
                ScSpecTypeTuple::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecTypeBytesN => Ok(Self::ScSpecTypeBytesN(Box::new(
                ScSpecTypeBytesN::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecTypeUdt => {
                Ok(Self::ScSpecTypeUdt(Box::new(ScSpecTypeUdt::read_xdr(r)?)))
            }
            TypeVariant::ScSpecTypeDef => {
                Ok(Self::ScSpecTypeDef(Box::new(ScSpecTypeDef::read_xdr(r)?)))
            }
            TypeVariant::ScSpecUdtStructFieldV0 => Ok(Self::ScSpecUdtStructFieldV0(Box::new(
                ScSpecUdtStructFieldV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecUdtStructV0 => Ok(Self::ScSpecUdtStructV0(Box::new(
                ScSpecUdtStructV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecUdtUnionCaseV0 => Ok(Self::ScSpecUdtUnionCaseV0(Box::new(
                ScSpecUdtUnionCaseV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecUdtUnionV0 => Ok(Self::ScSpecUdtUnionV0(Box::new(
                ScSpecUdtUnionV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecUdtEnumCaseV0 => Ok(Self::ScSpecUdtEnumCaseV0(Box::new(
                ScSpecUdtEnumCaseV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecUdtEnumV0 => Ok(Self::ScSpecUdtEnumV0(Box::new(
                ScSpecUdtEnumV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecUdtErrorEnumCaseV0 => Ok(Self::ScSpecUdtErrorEnumCaseV0(Box::new(
                ScSpecUdtErrorEnumCaseV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecUdtErrorEnumV0 => Ok(Self::ScSpecUdtErrorEnumV0(Box::new(
                ScSpecUdtErrorEnumV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecFunctionInputV0 => Ok(Self::ScSpecFunctionInputV0(Box::new(
                ScSpecFunctionInputV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecFunctionV0 => Ok(Self::ScSpecFunctionV0(Box::new(
                ScSpecFunctionV0::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecEntryKind => Ok(Self::ScSpecEntryKind(Box::new(
                ScSpecEntryKind::read_xdr(r)?,
            ))),
            TypeVariant::ScSpecEntry => Ok(Self::ScSpecEntry(Box::new(ScSpecEntry::read_xdr(r)?))),
            TypeVariant::ScSymbol => Ok(Self::ScSymbol(Box::new(ScSymbol::read_xdr(r)?))),
            TypeVariant::ScValType => Ok(Self::ScValType(Box::new(ScValType::read_xdr(r)?))),
            TypeVariant::ScStatic => Ok(Self::ScStatic(Box::new(ScStatic::read_xdr(r)?))),
            TypeVariant::ScStatusType => {
                Ok(Self::ScStatusType(Box::new(ScStatusType::read_xdr(r)?)))
            }
            TypeVariant::ScHostValErrorCode => Ok(Self::ScHostValErrorCode(Box::new(
                ScHostValErrorCode::read_xdr(r)?,
            ))),
            TypeVariant::ScHostObjErrorCode => Ok(Self::ScHostObjErrorCode(Box::new(
                ScHostObjErrorCode::read_xdr(r)?,
            ))),
            TypeVariant::ScHostFnErrorCode => Ok(Self::ScHostFnErrorCode(Box::new(
                ScHostFnErrorCode::read_xdr(r)?,
            ))),
            TypeVariant::ScHostStorageErrorCode => Ok(Self::ScHostStorageErrorCode(Box::new(
                ScHostStorageErrorCode::read_xdr(r)?,
            ))),
            TypeVariant::ScHostContextErrorCode => Ok(Self::ScHostContextErrorCode(Box::new(
                ScHostContextErrorCode::read_xdr(r)?,
            ))),
            TypeVariant::ScVmErrorCode => {
                Ok(Self::ScVmErrorCode(Box::new(ScVmErrorCode::read_xdr(r)?)))
            }
            TypeVariant::ScUnknownErrorCode => Ok(Self::ScUnknownErrorCode(Box::new(
                ScUnknownErrorCode::read_xdr(r)?,
            ))),
            TypeVariant::ScStatus => Ok(Self::ScStatus(Box::new(ScStatus::read_xdr(r)?))),
            TypeVariant::ScVal => Ok(Self::ScVal(Box::new(ScVal::read_xdr(r)?))),
            TypeVariant::ScObjectType => {
                Ok(Self::ScObjectType(Box::new(ScObjectType::read_xdr(r)?)))
            }
            TypeVariant::ScMapEntry => Ok(Self::ScMapEntry(Box::new(ScMapEntry::read_xdr(r)?))),
            TypeVariant::ScVec => Ok(Self::ScVec(Box::new(ScVec::read_xdr(r)?))),
            TypeVariant::ScMap => Ok(Self::ScMap(Box::new(ScMap::read_xdr(r)?))),
            TypeVariant::ScContractCodeType => Ok(Self::ScContractCodeType(Box::new(
                ScContractCodeType::read_xdr(r)?,
            ))),
            TypeVariant::ScContractCode => {
                Ok(Self::ScContractCode(Box::new(ScContractCode::read_xdr(r)?)))
            }
            TypeVariant::Int128Parts => Ok(Self::Int128Parts(Box::new(Int128Parts::read_xdr(r)?))),
            TypeVariant::ScObject => Ok(Self::ScObject(Box::new(ScObject::read_xdr(r)?))),
            TypeVariant::StoredTransactionSet => Ok(Self::StoredTransactionSet(Box::new(
                StoredTransactionSet::read_xdr(r)?,
            ))),
            TypeVariant::PersistedScpStateV0 => Ok(Self::PersistedScpStateV0(Box::new(
                PersistedScpStateV0::read_xdr(r)?,
            ))),
            TypeVariant::PersistedScpStateV1 => Ok(Self::PersistedScpStateV1(Box::new(
                PersistedScpStateV1::read_xdr(r)?,
            ))),
            TypeVariant::PersistedScpState => Ok(Self::PersistedScpState(Box::new(
                PersistedScpState::read_xdr(r)?,
            ))),
            TypeVariant::Thresholds => Ok(Self::Thresholds(Box::new(Thresholds::read_xdr(r)?))),
            TypeVariant::String32 => Ok(Self::String32(Box::new(String32::read_xdr(r)?))),
            TypeVariant::String64 => Ok(Self::String64(Box::new(String64::read_xdr(r)?))),
            TypeVariant::SequenceNumber => {
                Ok(Self::SequenceNumber(Box::new(SequenceNumber::read_xdr(r)?)))
            }
            TypeVariant::TimePoint => Ok(Self::TimePoint(Box::new(TimePoint::read_xdr(r)?))),
            TypeVariant::Duration => Ok(Self::Duration(Box::new(Duration::read_xdr(r)?))),
            TypeVariant::DataValue => Ok(Self::DataValue(Box::new(DataValue::read_xdr(r)?))),
            TypeVariant::PoolId => Ok(Self::PoolId(Box::new(PoolId::read_xdr(r)?))),
            TypeVariant::AssetCode4 => Ok(Self::AssetCode4(Box::new(AssetCode4::read_xdr(r)?))),
            TypeVariant::AssetCode12 => Ok(Self::AssetCode12(Box::new(AssetCode12::read_xdr(r)?))),
            TypeVariant::AssetType => Ok(Self::AssetType(Box::new(AssetType::read_xdr(r)?))),
            TypeVariant::AssetCode => Ok(Self::AssetCode(Box::new(AssetCode::read_xdr(r)?))),
            TypeVariant::AlphaNum4 => Ok(Self::AlphaNum4(Box::new(AlphaNum4::read_xdr(r)?))),
            TypeVariant::AlphaNum12 => Ok(Self::AlphaNum12(Box::new(AlphaNum12::read_xdr(r)?))),
            TypeVariant::Asset => Ok(Self::Asset(Box::new(Asset::read_xdr(r)?))),
            TypeVariant::Price => Ok(Self::Price(Box::new(Price::read_xdr(r)?))),
            TypeVariant::Liabilities => Ok(Self::Liabilities(Box::new(Liabilities::read_xdr(r)?))),
            TypeVariant::ThresholdIndexes => Ok(Self::ThresholdIndexes(Box::new(
                ThresholdIndexes::read_xdr(r)?,
            ))),
            TypeVariant::LedgerEntryType => Ok(Self::LedgerEntryType(Box::new(
                LedgerEntryType::read_xdr(r)?,
            ))),
            TypeVariant::Signer => Ok(Self::Signer(Box::new(Signer::read_xdr(r)?))),
            TypeVariant::AccountFlags => {
                Ok(Self::AccountFlags(Box::new(AccountFlags::read_xdr(r)?)))
            }
            TypeVariant::SponsorshipDescriptor => Ok(Self::SponsorshipDescriptor(Box::new(
                SponsorshipDescriptor::read_xdr(r)?,
            ))),
            TypeVariant::AccountEntryExtensionV3 => Ok(Self::AccountEntryExtensionV3(Box::new(
                AccountEntryExtensionV3::read_xdr(r)?,
            ))),
            TypeVariant::AccountEntryExtensionV2 => Ok(Self::AccountEntryExtensionV2(Box::new(
                AccountEntryExtensionV2::read_xdr(r)?,
            ))),
            TypeVariant::AccountEntryExtensionV2Ext => Ok(Self::AccountEntryExtensionV2Ext(
                Box::new(AccountEntryExtensionV2Ext::read_xdr(r)?),
            )),
            TypeVariant::AccountEntryExtensionV1 => Ok(Self::AccountEntryExtensionV1(Box::new(
                AccountEntryExtensionV1::read_xdr(r)?,
            ))),
            TypeVariant::AccountEntryExtensionV1Ext => Ok(Self::AccountEntryExtensionV1Ext(
                Box::new(AccountEntryExtensionV1Ext::read_xdr(r)?),
            )),
            TypeVariant::AccountEntry => {
                Ok(Self::AccountEntry(Box::new(AccountEntry::read_xdr(r)?)))
            }
            TypeVariant::AccountEntryExt => Ok(Self::AccountEntryExt(Box::new(
                AccountEntryExt::read_xdr(r)?,
            ))),
            TypeVariant::TrustLineFlags => {
                Ok(Self::TrustLineFlags(Box::new(TrustLineFlags::read_xdr(r)?)))
            }
            TypeVariant::LiquidityPoolType => Ok(Self::LiquidityPoolType(Box::new(
                LiquidityPoolType::read_xdr(r)?,
            ))),
            TypeVariant::TrustLineAsset => {
                Ok(Self::TrustLineAsset(Box::new(TrustLineAsset::read_xdr(r)?)))
            }
            TypeVariant::TrustLineEntryExtensionV2 => Ok(Self::TrustLineEntryExtensionV2(
                Box::new(TrustLineEntryExtensionV2::read_xdr(r)?),
            )),
            TypeVariant::TrustLineEntryExtensionV2Ext => Ok(Self::TrustLineEntryExtensionV2Ext(
                Box::new(TrustLineEntryExtensionV2Ext::read_xdr(r)?),
            )),
            TypeVariant::TrustLineEntry => {
                Ok(Self::TrustLineEntry(Box::new(TrustLineEntry::read_xdr(r)?)))
            }
            TypeVariant::TrustLineEntryExt => Ok(Self::TrustLineEntryExt(Box::new(
                TrustLineEntryExt::read_xdr(r)?,
            ))),
            TypeVariant::TrustLineEntryV1 => Ok(Self::TrustLineEntryV1(Box::new(
                TrustLineEntryV1::read_xdr(r)?,
            ))),
            TypeVariant::TrustLineEntryV1Ext => Ok(Self::TrustLineEntryV1Ext(Box::new(
                TrustLineEntryV1Ext::read_xdr(r)?,
            ))),
            TypeVariant::OfferEntryFlags => Ok(Self::OfferEntryFlags(Box::new(
                OfferEntryFlags::read_xdr(r)?,
            ))),
            TypeVariant::OfferEntry => Ok(Self::OfferEntry(Box::new(OfferEntry::read_xdr(r)?))),
            TypeVariant::OfferEntryExt => {
                Ok(Self::OfferEntryExt(Box::new(OfferEntryExt::read_xdr(r)?)))
            }
            TypeVariant::DataEntry => Ok(Self::DataEntry(Box::new(DataEntry::read_xdr(r)?))),
            TypeVariant::DataEntryExt => {
                Ok(Self::DataEntryExt(Box::new(DataEntryExt::read_xdr(r)?)))
            }
            TypeVariant::ClaimPredicateType => Ok(Self::ClaimPredicateType(Box::new(
                ClaimPredicateType::read_xdr(r)?,
            ))),
            TypeVariant::ClaimPredicate => {
                Ok(Self::ClaimPredicate(Box::new(ClaimPredicate::read_xdr(r)?)))
            }
            TypeVariant::ClaimantType => {
                Ok(Self::ClaimantType(Box::new(ClaimantType::read_xdr(r)?)))
            }
            TypeVariant::Claimant => Ok(Self::Claimant(Box::new(Claimant::read_xdr(r)?))),
            TypeVariant::ClaimantV0 => Ok(Self::ClaimantV0(Box::new(ClaimantV0::read_xdr(r)?))),
            TypeVariant::ClaimableBalanceIdType => Ok(Self::ClaimableBalanceIdType(Box::new(
                ClaimableBalanceIdType::read_xdr(r)?,
            ))),
            TypeVariant::ClaimableBalanceId => Ok(Self::ClaimableBalanceId(Box::new(
                ClaimableBalanceId::read_xdr(r)?,
            ))),
            TypeVariant::ClaimableBalanceFlags => Ok(Self::ClaimableBalanceFlags(Box::new(
                ClaimableBalanceFlags::read_xdr(r)?,
            ))),
            TypeVariant::ClaimableBalanceEntryExtensionV1 => {
                Ok(Self::ClaimableBalanceEntryExtensionV1(Box::new(
                    ClaimableBalanceEntryExtensionV1::read_xdr(r)?,
                )))
            }
            TypeVariant::ClaimableBalanceEntryExtensionV1Ext => {
                Ok(Self::ClaimableBalanceEntryExtensionV1Ext(Box::new(
                    ClaimableBalanceEntryExtensionV1Ext::read_xdr(r)?,
                )))
            }
            TypeVariant::ClaimableBalanceEntry => Ok(Self::ClaimableBalanceEntry(Box::new(
                ClaimableBalanceEntry::read_xdr(r)?,
            ))),
            TypeVariant::ClaimableBalanceEntryExt => Ok(Self::ClaimableBalanceEntryExt(Box::new(
                ClaimableBalanceEntryExt::read_xdr(r)?,
            ))),
            TypeVariant::LiquidityPoolConstantProductParameters => {
                Ok(Self::LiquidityPoolConstantProductParameters(Box::new(
                    LiquidityPoolConstantProductParameters::read_xdr(r)?,
                )))
            }
            TypeVariant::LiquidityPoolEntry => Ok(Self::LiquidityPoolEntry(Box::new(
                LiquidityPoolEntry::read_xdr(r)?,
            ))),
            TypeVariant::LiquidityPoolEntryBody => Ok(Self::LiquidityPoolEntryBody(Box::new(
                LiquidityPoolEntryBody::read_xdr(r)?,
            ))),
            TypeVariant::LiquidityPoolEntryConstantProduct => {
                Ok(Self::LiquidityPoolEntryConstantProduct(Box::new(
                    LiquidityPoolEntryConstantProduct::read_xdr(r)?,
                )))
            }
            TypeVariant::ContractDataEntry => Ok(Self::ContractDataEntry(Box::new(
                ContractDataEntry::read_xdr(r)?,
            ))),
            TypeVariant::ContractCodeEntry => Ok(Self::ContractCodeEntry(Box::new(
                ContractCodeEntry::read_xdr(r)?,
            ))),
            TypeVariant::ConfigSettingType => Ok(Self::ConfigSettingType(Box::new(
                ConfigSettingType::read_xdr(r)?,
            ))),
            TypeVariant::ConfigSetting => {
                Ok(Self::ConfigSetting(Box::new(ConfigSetting::read_xdr(r)?)))
            }
            TypeVariant::ConfigSettingId => Ok(Self::ConfigSettingId(Box::new(
                ConfigSettingId::read_xdr(r)?,
            ))),
            TypeVariant::ConfigSettingEntry => Ok(Self::ConfigSettingEntry(Box::new(
                ConfigSettingEntry::read_xdr(r)?,
            ))),
            TypeVariant::ConfigSettingEntryExt => Ok(Self::ConfigSettingEntryExt(Box::new(
                ConfigSettingEntryExt::read_xdr(r)?,
            ))),
            TypeVariant::LedgerEntryExtensionV1 => Ok(Self::LedgerEntryExtensionV1(Box::new(
                LedgerEntryExtensionV1::read_xdr(r)?,
            ))),
            TypeVariant::LedgerEntryExtensionV1Ext => Ok(Self::LedgerEntryExtensionV1Ext(
                Box::new(LedgerEntryExtensionV1Ext::read_xdr(r)?),
            )),
            TypeVariant::LedgerEntry => Ok(Self::LedgerEntry(Box::new(LedgerEntry::read_xdr(r)?))),
            TypeVariant::LedgerEntryData => Ok(Self::LedgerEntryData(Box::new(
                LedgerEntryData::read_xdr(r)?,
            ))),
            TypeVariant::LedgerEntryExt => {
                Ok(Self::LedgerEntryExt(Box::new(LedgerEntryExt::read_xdr(r)?)))
            }
            TypeVariant::LedgerKey => Ok(Self::LedgerKey(Box::new(LedgerKey::read_xdr(r)?))),
            TypeVariant::LedgerKeyAccount => Ok(Self::LedgerKeyAccount(Box::new(
                LedgerKeyAccount::read_xdr(r)?,
            ))),
            TypeVariant::LedgerKeyTrustLine => Ok(Self::LedgerKeyTrustLine(Box::new(
                LedgerKeyTrustLine::read_xdr(r)?,
            ))),
            TypeVariant::LedgerKeyOffer => {
                Ok(Self::LedgerKeyOffer(Box::new(LedgerKeyOffer::read_xdr(r)?)))
            }
            TypeVariant::LedgerKeyData => {
                Ok(Self::LedgerKeyData(Box::new(LedgerKeyData::read_xdr(r)?)))
            }
            TypeVariant::LedgerKeyClaimableBalance => Ok(Self::LedgerKeyClaimableBalance(
                Box::new(LedgerKeyClaimableBalance::read_xdr(r)?),
            )),
            TypeVariant::LedgerKeyLiquidityPool => Ok(Self::LedgerKeyLiquidityPool(Box::new(
                LedgerKeyLiquidityPool::read_xdr(r)?,
            ))),
            TypeVariant::LedgerKeyContractData => Ok(Self::LedgerKeyContractData(Box::new(
                LedgerKeyContractData::read_xdr(r)?,
            ))),
            TypeVariant::LedgerKeyContractCode => Ok(Self::LedgerKeyContractCode(Box::new(
                LedgerKeyContractCode::read_xdr(r)?,
            ))),
            TypeVariant::LedgerKeyConfigSetting => Ok(Self::LedgerKeyConfigSetting(Box::new(
                LedgerKeyConfigSetting::read_xdr(r)?,
            ))),
            TypeVariant::EnvelopeType => {
                Ok(Self::EnvelopeType(Box::new(EnvelopeType::read_xdr(r)?)))
            }
            TypeVariant::UpgradeType => Ok(Self::UpgradeType(Box::new(UpgradeType::read_xdr(r)?))),
            TypeVariant::StellarValueType => Ok(Self::StellarValueType(Box::new(
                StellarValueType::read_xdr(r)?,
            ))),
            TypeVariant::LedgerCloseValueSignature => Ok(Self::LedgerCloseValueSignature(
                Box::new(LedgerCloseValueSignature::read_xdr(r)?),
            )),
            TypeVariant::StellarValue => {
                Ok(Self::StellarValue(Box::new(StellarValue::read_xdr(r)?)))
            }
            TypeVariant::StellarValueExt => Ok(Self::StellarValueExt(Box::new(
                StellarValueExt::read_xdr(r)?,
            ))),
            TypeVariant::LedgerHeaderFlags => Ok(Self::LedgerHeaderFlags(Box::new(
                LedgerHeaderFlags::read_xdr(r)?,
            ))),
            TypeVariant::LedgerHeaderExtensionV1 => Ok(Self::LedgerHeaderExtensionV1(Box::new(
                LedgerHeaderExtensionV1::read_xdr(r)?,
            ))),
            TypeVariant::LedgerHeaderExtensionV1Ext => Ok(Self::LedgerHeaderExtensionV1Ext(
                Box::new(LedgerHeaderExtensionV1Ext::read_xdr(r)?),
            )),
            TypeVariant::LedgerHeader => {
                Ok(Self::LedgerHeader(Box::new(LedgerHeader::read_xdr(r)?)))
            }
            TypeVariant::LedgerHeaderExt => Ok(Self::LedgerHeaderExt(Box::new(
                LedgerHeaderExt::read_xdr(r)?,
            ))),
            TypeVariant::LedgerUpgradeType => Ok(Self::LedgerUpgradeType(Box::new(
                LedgerUpgradeType::read_xdr(r)?,
            ))),
            TypeVariant::LedgerUpgrade => {
                Ok(Self::LedgerUpgrade(Box::new(LedgerUpgrade::read_xdr(r)?)))
            }
            TypeVariant::LedgerUpgradeConfigSetting => Ok(Self::LedgerUpgradeConfigSetting(
                Box::new(LedgerUpgradeConfigSetting::read_xdr(r)?),
            )),
            TypeVariant::BucketEntryType => Ok(Self::BucketEntryType(Box::new(
                BucketEntryType::read_xdr(r)?,
            ))),
            TypeVariant::BucketMetadata => {
                Ok(Self::BucketMetadata(Box::new(BucketMetadata::read_xdr(r)?)))
            }
            TypeVariant::BucketMetadataExt => Ok(Self::BucketMetadataExt(Box::new(
                BucketMetadataExt::read_xdr(r)?,
            ))),
            TypeVariant::BucketEntry => Ok(Self::BucketEntry(Box::new(BucketEntry::read_xdr(r)?))),
            TypeVariant::TxSetComponentType => Ok(Self::TxSetComponentType(Box::new(
                TxSetComponentType::read_xdr(r)?,
            ))),
            TypeVariant::TxSetComponent => {
                Ok(Self::TxSetComponent(Box::new(TxSetComponent::read_xdr(r)?)))
            }
            TypeVariant::TxSetComponentTxsMaybeDiscountedFee => {
                Ok(Self::TxSetComponentTxsMaybeDiscountedFee(Box::new(
                    TxSetComponentTxsMaybeDiscountedFee::read_xdr(r)?,
                )))
            }
            TypeVariant::TransactionPhase => Ok(Self::TransactionPhase(Box::new(
                TransactionPhase::read_xdr(r)?,
            ))),
            TypeVariant::TransactionSet => {
                Ok(Self::TransactionSet(Box::new(TransactionSet::read_xdr(r)?)))
            }
            TypeVariant::TransactionSetV1 => Ok(Self::TransactionSetV1(Box::new(
                TransactionSetV1::read_xdr(r)?,
            ))),
            TypeVariant::GeneralizedTransactionSet => Ok(Self::GeneralizedTransactionSet(
                Box::new(GeneralizedTransactionSet::read_xdr(r)?),
            )),
            TypeVariant::TransactionResultPair => Ok(Self::TransactionResultPair(Box::new(
                TransactionResultPair::read_xdr(r)?,
            ))),
            TypeVariant::TransactionResultSet => Ok(Self::TransactionResultSet(Box::new(
                TransactionResultSet::read_xdr(r)?,
            ))),
            TypeVariant::TransactionHistoryEntry => Ok(Self::TransactionHistoryEntry(Box::new(
                TransactionHistoryEntry::read_xdr(r)?,
            ))),
            TypeVariant::TransactionHistoryEntryExt => Ok(Self::TransactionHistoryEntryExt(
                Box::new(TransactionHistoryEntryExt::read_xdr(r)?),
            )),
            TypeVariant::TransactionHistoryResultEntry => Ok(Self::TransactionHistoryResultEntry(
                Box::new(TransactionHistoryResultEntry::read_xdr(r)?),
            )),
            TypeVariant::TransactionHistoryResultEntryExt => {
                Ok(Self::TransactionHistoryResultEntryExt(Box::new(
                    TransactionHistoryResultEntryExt::read_xdr(r)?,
                )))
            }
            TypeVariant::TransactionResultPairV2 => Ok(Self::TransactionResultPairV2(Box::new(
                TransactionResultPairV2::read_xdr(r)?,
            ))),
            TypeVariant::TransactionResultSetV2 => Ok(Self::TransactionResultSetV2(Box::new(
                TransactionResultSetV2::read_xdr(r)?,
            ))),
            TypeVariant::TransactionHistoryResultEntryV2 => {
                Ok(Self::TransactionHistoryResultEntryV2(Box::new(
                    TransactionHistoryResultEntryV2::read_xdr(r)?,
                )))
            }
            TypeVariant::TransactionHistoryResultEntryV2Ext => {
                Ok(Self::TransactionHistoryResultEntryV2Ext(Box::new(
                    TransactionHistoryResultEntryV2Ext::read_xdr(r)?,
                )))
            }
            TypeVariant::LedgerHeaderHistoryEntry => Ok(Self::LedgerHeaderHistoryEntry(Box::new(
                LedgerHeaderHistoryEntry::read_xdr(r)?,
            ))),
            TypeVariant::LedgerHeaderHistoryEntryExt => Ok(Self::LedgerHeaderHistoryEntryExt(
                Box::new(LedgerHeaderHistoryEntryExt::read_xdr(r)?),
            )),
            TypeVariant::LedgerScpMessages => Ok(Self::LedgerScpMessages(Box::new(
                LedgerScpMessages::read_xdr(r)?,
            ))),
            TypeVariant::ScpHistoryEntryV0 => Ok(Self::ScpHistoryEntryV0(Box::new(
                ScpHistoryEntryV0::read_xdr(r)?,
            ))),
            TypeVariant::ScpHistoryEntry => Ok(Self::ScpHistoryEntry(Box::new(
                ScpHistoryEntry::read_xdr(r)?,
            ))),
            TypeVariant::LedgerEntryChangeType => Ok(Self::LedgerEntryChangeType(Box::new(
                LedgerEntryChangeType::read_xdr(r)?,
            ))),
            TypeVariant::LedgerEntryChange => Ok(Self::LedgerEntryChange(Box::new(
                LedgerEntryChange::read_xdr(r)?,
            ))),
            TypeVariant::LedgerEntryChanges => Ok(Self::LedgerEntryChanges(Box::new(
                LedgerEntryChanges::read_xdr(r)?,
            ))),
            TypeVariant::OperationMeta => {
                Ok(Self::OperationMeta(Box::new(OperationMeta::read_xdr(r)?)))
            }
            TypeVariant::TransactionMetaV1 => Ok(Self::TransactionMetaV1(Box::new(
                TransactionMetaV1::read_xdr(r)?,
            ))),
            TypeVariant::TransactionMetaV2 => Ok(Self::TransactionMetaV2(Box::new(
                TransactionMetaV2::read_xdr(r)?,
            ))),
            TypeVariant::ContractEventType => Ok(Self::ContractEventType(Box::new(
                ContractEventType::read_xdr(r)?,
            ))),
            TypeVariant::ContractEvent => {
                Ok(Self::ContractEvent(Box::new(ContractEvent::read_xdr(r)?)))
            }
            TypeVariant::ContractEventBody => Ok(Self::ContractEventBody(Box::new(
                ContractEventBody::read_xdr(r)?,
            ))),
            TypeVariant::ContractEventV0 => Ok(Self::ContractEventV0(Box::new(
                ContractEventV0::read_xdr(r)?,
            ))),
            TypeVariant::OperationEvents => Ok(Self::OperationEvents(Box::new(
                OperationEvents::read_xdr(r)?,
            ))),
            TypeVariant::TransactionMetaV3 => Ok(Self::TransactionMetaV3(Box::new(
                TransactionMetaV3::read_xdr(r)?,
            ))),
            TypeVariant::TransactionMeta => Ok(Self::TransactionMeta(Box::new(
                TransactionMeta::read_xdr(r)?,
            ))),
            TypeVariant::TransactionResultMeta => Ok(Self::TransactionResultMeta(Box::new(
                TransactionResultMeta::read_xdr(r)?,
            ))),
            TypeVariant::TransactionResultMetaV2 => Ok(Self::TransactionResultMetaV2(Box::new(
                TransactionResultMetaV2::read_xdr(r)?,
            ))),
            TypeVariant::UpgradeEntryMeta => Ok(Self::UpgradeEntryMeta(Box::new(
                UpgradeEntryMeta::read_xdr(r)?,
            ))),
            TypeVariant::LedgerCloseMetaV0 => Ok(Self::LedgerCloseMetaV0(Box::new(
                LedgerCloseMetaV0::read_xdr(r)?,
            ))),
            TypeVariant::LedgerCloseMetaV1 => Ok(Self::LedgerCloseMetaV1(Box::new(
                LedgerCloseMetaV1::read_xdr(r)?,
            ))),
            TypeVariant::LedgerCloseMetaV2 => Ok(Self::LedgerCloseMetaV2(Box::new(
                LedgerCloseMetaV2::read_xdr(r)?,
            ))),
            TypeVariant::LedgerCloseMeta => Ok(Self::LedgerCloseMeta(Box::new(
                LedgerCloseMeta::read_xdr(r)?,
            ))),
            TypeVariant::ErrorCode => Ok(Self::ErrorCode(Box::new(ErrorCode::read_xdr(r)?))),
            TypeVariant::SError => Ok(Self::SError(Box::new(SError::read_xdr(r)?))),
            TypeVariant::SendMore => Ok(Self::SendMore(Box::new(SendMore::read_xdr(r)?))),
            TypeVariant::AuthCert => Ok(Self::AuthCert(Box::new(AuthCert::read_xdr(r)?))),
            TypeVariant::Hello => Ok(Self::Hello(Box::new(Hello::read_xdr(r)?))),
            TypeVariant::Auth => Ok(Self::Auth(Box::new(Auth::read_xdr(r)?))),
            TypeVariant::IpAddrType => Ok(Self::IpAddrType(Box::new(IpAddrType::read_xdr(r)?))),
            TypeVariant::PeerAddress => Ok(Self::PeerAddress(Box::new(PeerAddress::read_xdr(r)?))),
            TypeVariant::PeerAddressIp => {
                Ok(Self::PeerAddressIp(Box::new(PeerAddressIp::read_xdr(r)?)))
            }
            TypeVariant::MessageType => Ok(Self::MessageType(Box::new(MessageType::read_xdr(r)?))),
            TypeVariant::DontHave => Ok(Self::DontHave(Box::new(DontHave::read_xdr(r)?))),
            TypeVariant::SurveyMessageCommandType => Ok(Self::SurveyMessageCommandType(Box::new(
                SurveyMessageCommandType::read_xdr(r)?,
            ))),
            TypeVariant::SurveyRequestMessage => Ok(Self::SurveyRequestMessage(Box::new(
                SurveyRequestMessage::read_xdr(r)?,
            ))),
            TypeVariant::SignedSurveyRequestMessage => Ok(Self::SignedSurveyRequestMessage(
                Box::new(SignedSurveyRequestMessage::read_xdr(r)?),
            )),
            TypeVariant::EncryptedBody => {
                Ok(Self::EncryptedBody(Box::new(EncryptedBody::read_xdr(r)?)))
            }
            TypeVariant::SurveyResponseMessage => Ok(Self::SurveyResponseMessage(Box::new(
                SurveyResponseMessage::read_xdr(r)?,
            ))),
            TypeVariant::SignedSurveyResponseMessage => Ok(Self::SignedSurveyResponseMessage(
                Box::new(SignedSurveyResponseMessage::read_xdr(r)?),
            )),
            TypeVariant::PeerStats => Ok(Self::PeerStats(Box::new(PeerStats::read_xdr(r)?))),
            TypeVariant::PeerStatList => {
                Ok(Self::PeerStatList(Box::new(PeerStatList::read_xdr(r)?)))
            }
            TypeVariant::TopologyResponseBody => Ok(Self::TopologyResponseBody(Box::new(
                TopologyResponseBody::read_xdr(r)?,
            ))),
            TypeVariant::SurveyResponseBody => Ok(Self::SurveyResponseBody(Box::new(
                SurveyResponseBody::read_xdr(r)?,
            ))),
            TypeVariant::TxAdvertVector => {
                Ok(Self::TxAdvertVector(Box::new(TxAdvertVector::read_xdr(r)?)))
            }
            TypeVariant::FloodAdvert => Ok(Self::FloodAdvert(Box::new(FloodAdvert::read_xdr(r)?))),
            TypeVariant::TxDemandVector => {
                Ok(Self::TxDemandVector(Box::new(TxDemandVector::read_xdr(r)?)))
            }
            TypeVariant::FloodDemand => Ok(Self::FloodDemand(Box::new(FloodDemand::read_xdr(r)?))),
            TypeVariant::StellarMessage => {
                Ok(Self::StellarMessage(Box::new(StellarMessage::read_xdr(r)?)))
            }
            TypeVariant::AuthenticatedMessage => Ok(Self::AuthenticatedMessage(Box::new(
                AuthenticatedMessage::read_xdr(r)?,
            ))),
            TypeVariant::AuthenticatedMessageV0 => Ok(Self::AuthenticatedMessageV0(Box::new(
                AuthenticatedMessageV0::read_xdr(r)?,
            ))),
            TypeVariant::LiquidityPoolParameters => Ok(Self::LiquidityPoolParameters(Box::new(
                LiquidityPoolParameters::read_xdr(r)?,
            ))),
            TypeVariant::MuxedAccount => {
                Ok(Self::MuxedAccount(Box::new(MuxedAccount::read_xdr(r)?)))
            }
            TypeVariant::MuxedAccountMed25519 => Ok(Self::MuxedAccountMed25519(Box::new(
                MuxedAccountMed25519::read_xdr(r)?,
            ))),
            TypeVariant::DecoratedSignature => Ok(Self::DecoratedSignature(Box::new(
                DecoratedSignature::read_xdr(r)?,
            ))),
            TypeVariant::LedgerFootprint => Ok(Self::LedgerFootprint(Box::new(
                LedgerFootprint::read_xdr(r)?,
            ))),
            TypeVariant::OperationType => {
                Ok(Self::OperationType(Box::new(OperationType::read_xdr(r)?)))
            }
            TypeVariant::CreateAccountOp => Ok(Self::CreateAccountOp(Box::new(
                CreateAccountOp::read_xdr(r)?,
            ))),
            TypeVariant::PaymentOp => Ok(Self::PaymentOp(Box::new(PaymentOp::read_xdr(r)?))),
            TypeVariant::PathPaymentStrictReceiveOp => Ok(Self::PathPaymentStrictReceiveOp(
                Box::new(PathPaymentStrictReceiveOp::read_xdr(r)?),
            )),
            TypeVariant::PathPaymentStrictSendOp => Ok(Self::PathPaymentStrictSendOp(Box::new(
                PathPaymentStrictSendOp::read_xdr(r)?,
            ))),
            TypeVariant::ManageSellOfferOp => Ok(Self::ManageSellOfferOp(Box::new(
                ManageSellOfferOp::read_xdr(r)?,
            ))),
            TypeVariant::ManageBuyOfferOp => Ok(Self::ManageBuyOfferOp(Box::new(
                ManageBuyOfferOp::read_xdr(r)?,
            ))),
            TypeVariant::CreatePassiveSellOfferOp => Ok(Self::CreatePassiveSellOfferOp(Box::new(
                CreatePassiveSellOfferOp::read_xdr(r)?,
            ))),
            TypeVariant::SetOptionsOp => {
                Ok(Self::SetOptionsOp(Box::new(SetOptionsOp::read_xdr(r)?)))
            }
            TypeVariant::ChangeTrustAsset => Ok(Self::ChangeTrustAsset(Box::new(
                ChangeTrustAsset::read_xdr(r)?,
            ))),
            TypeVariant::ChangeTrustOp => {
                Ok(Self::ChangeTrustOp(Box::new(ChangeTrustOp::read_xdr(r)?)))
            }
            TypeVariant::AllowTrustOp => {
                Ok(Self::AllowTrustOp(Box::new(AllowTrustOp::read_xdr(r)?)))
            }
            TypeVariant::ManageDataOp => {
                Ok(Self::ManageDataOp(Box::new(ManageDataOp::read_xdr(r)?)))
            }
            TypeVariant::BumpSequenceOp => {
                Ok(Self::BumpSequenceOp(Box::new(BumpSequenceOp::read_xdr(r)?)))
            }
            TypeVariant::CreateClaimableBalanceOp => Ok(Self::CreateClaimableBalanceOp(Box::new(
                CreateClaimableBalanceOp::read_xdr(r)?,
            ))),
            TypeVariant::ClaimClaimableBalanceOp => Ok(Self::ClaimClaimableBalanceOp(Box::new(
                ClaimClaimableBalanceOp::read_xdr(r)?,
            ))),
            TypeVariant::BeginSponsoringFutureReservesOp => {
                Ok(Self::BeginSponsoringFutureReservesOp(Box::new(
                    BeginSponsoringFutureReservesOp::read_xdr(r)?,
                )))
            }
            TypeVariant::RevokeSponsorshipType => Ok(Self::RevokeSponsorshipType(Box::new(
                RevokeSponsorshipType::read_xdr(r)?,
            ))),
            TypeVariant::RevokeSponsorshipOp => Ok(Self::RevokeSponsorshipOp(Box::new(
                RevokeSponsorshipOp::read_xdr(r)?,
            ))),
            TypeVariant::RevokeSponsorshipOpSigner => Ok(Self::RevokeSponsorshipOpSigner(
                Box::new(RevokeSponsorshipOpSigner::read_xdr(r)?),
            )),
            TypeVariant::ClawbackOp => Ok(Self::ClawbackOp(Box::new(ClawbackOp::read_xdr(r)?))),
            TypeVariant::ClawbackClaimableBalanceOp => Ok(Self::ClawbackClaimableBalanceOp(
                Box::new(ClawbackClaimableBalanceOp::read_xdr(r)?),
            )),
            TypeVariant::SetTrustLineFlagsOp => Ok(Self::SetTrustLineFlagsOp(Box::new(
                SetTrustLineFlagsOp::read_xdr(r)?,
            ))),
            TypeVariant::LiquidityPoolDepositOp => Ok(Self::LiquidityPoolDepositOp(Box::new(
                LiquidityPoolDepositOp::read_xdr(r)?,
            ))),
            TypeVariant::LiquidityPoolWithdrawOp => Ok(Self::LiquidityPoolWithdrawOp(Box::new(
                LiquidityPoolWithdrawOp::read_xdr(r)?,
            ))),
            TypeVariant::HostFunctionType => Ok(Self::HostFunctionType(Box::new(
                HostFunctionType::read_xdr(r)?,
            ))),
            TypeVariant::ContractIdType => {
                Ok(Self::ContractIdType(Box::new(ContractIdType::read_xdr(r)?)))
            }
            TypeVariant::ContractIdPublicKeyType => Ok(Self::ContractIdPublicKeyType(Box::new(
                ContractIdPublicKeyType::read_xdr(r)?,
            ))),
            TypeVariant::InstallContractCodeArgs => Ok(Self::InstallContractCodeArgs(Box::new(
                InstallContractCodeArgs::read_xdr(r)?,
            ))),
            TypeVariant::ContractId => Ok(Self::ContractId(Box::new(ContractId::read_xdr(r)?))),
            TypeVariant::ContractIdFromEd25519PublicKey => {
                Ok(Self::ContractIdFromEd25519PublicKey(Box::new(
                    ContractIdFromEd25519PublicKey::read_xdr(r)?,
                )))
            }
            TypeVariant::CreateContractArgs => Ok(Self::CreateContractArgs(Box::new(
                CreateContractArgs::read_xdr(r)?,
            ))),
            TypeVariant::HostFunction => {
                Ok(Self::HostFunction(Box::new(HostFunction::read_xdr(r)?)))
            }
            TypeVariant::InvokeHostFunctionOp => Ok(Self::InvokeHostFunctionOp(Box::new(
                InvokeHostFunctionOp::read_xdr(r)?,
            ))),
            TypeVariant::Operation => Ok(Self::Operation(Box::new(Operation::read_xdr(r)?))),
            TypeVariant::OperationBody => {
                Ok(Self::OperationBody(Box::new(OperationBody::read_xdr(r)?)))
            }
            TypeVariant::HashIdPreimage => {
                Ok(Self::HashIdPreimage(Box::new(HashIdPreimage::read_xdr(r)?)))
            }
            TypeVariant::HashIdPreimageOperationId => Ok(Self::HashIdPreimageOperationId(
                Box::new(HashIdPreimageOperationId::read_xdr(r)?),
            )),
            TypeVariant::HashIdPreimageRevokeId => Ok(Self::HashIdPreimageRevokeId(Box::new(
                HashIdPreimageRevokeId::read_xdr(r)?,
            ))),
            TypeVariant::HashIdPreimageEd25519ContractId => {
                Ok(Self::HashIdPreimageEd25519ContractId(Box::new(
                    HashIdPreimageEd25519ContractId::read_xdr(r)?,
                )))
            }
            TypeVariant::HashIdPreimageContractId => Ok(Self::HashIdPreimageContractId(Box::new(
                HashIdPreimageContractId::read_xdr(r)?,
            ))),
            TypeVariant::HashIdPreimageFromAsset => Ok(Self::HashIdPreimageFromAsset(Box::new(
                HashIdPreimageFromAsset::read_xdr(r)?,
            ))),
            TypeVariant::HashIdPreimageSourceAccountContractId => {
                Ok(Self::HashIdPreimageSourceAccountContractId(Box::new(
                    HashIdPreimageSourceAccountContractId::read_xdr(r)?,
                )))
            }
            TypeVariant::HashIdPreimageCreateContractArgs => {
                Ok(Self::HashIdPreimageCreateContractArgs(Box::new(
                    HashIdPreimageCreateContractArgs::read_xdr(r)?,
                )))
            }
            TypeVariant::MemoType => Ok(Self::MemoType(Box::new(MemoType::read_xdr(r)?))),
            TypeVariant::Memo => Ok(Self::Memo(Box::new(Memo::read_xdr(r)?))),
            TypeVariant::TimeBounds => Ok(Self::TimeBounds(Box::new(TimeBounds::read_xdr(r)?))),
            TypeVariant::LedgerBounds => {
                Ok(Self::LedgerBounds(Box::new(LedgerBounds::read_xdr(r)?)))
            }
            TypeVariant::PreconditionsV2 => Ok(Self::PreconditionsV2(Box::new(
                PreconditionsV2::read_xdr(r)?,
            ))),
            TypeVariant::PreconditionType => Ok(Self::PreconditionType(Box::new(
                PreconditionType::read_xdr(r)?,
            ))),
            TypeVariant::Preconditions => {
                Ok(Self::Preconditions(Box::new(Preconditions::read_xdr(r)?)))
            }
            TypeVariant::TransactionV0 => {
                Ok(Self::TransactionV0(Box::new(TransactionV0::read_xdr(r)?)))
            }
            TypeVariant::TransactionV0Ext => Ok(Self::TransactionV0Ext(Box::new(
                TransactionV0Ext::read_xdr(r)?,
            ))),
            TypeVariant::TransactionV0Envelope => Ok(Self::TransactionV0Envelope(Box::new(
                TransactionV0Envelope::read_xdr(r)?,
            ))),
            TypeVariant::Transaction => Ok(Self::Transaction(Box::new(Transaction::read_xdr(r)?))),
            TypeVariant::TransactionExt => {
                Ok(Self::TransactionExt(Box::new(TransactionExt::read_xdr(r)?)))
            }
            TypeVariant::TransactionV1Envelope => Ok(Self::TransactionV1Envelope(Box::new(
                TransactionV1Envelope::read_xdr(r)?,
            ))),
            TypeVariant::FeeBumpTransaction => Ok(Self::FeeBumpTransaction(Box::new(
                FeeBumpTransaction::read_xdr(r)?,
            ))),
            TypeVariant::FeeBumpTransactionInnerTx => Ok(Self::FeeBumpTransactionInnerTx(
                Box::new(FeeBumpTransactionInnerTx::read_xdr(r)?),
            )),
            TypeVariant::FeeBumpTransactionExt => Ok(Self::FeeBumpTransactionExt(Box::new(
                FeeBumpTransactionExt::read_xdr(r)?,
            ))),
            TypeVariant::FeeBumpTransactionEnvelope => Ok(Self::FeeBumpTransactionEnvelope(
                Box::new(FeeBumpTransactionEnvelope::read_xdr(r)?),
            )),
            TypeVariant::TransactionEnvelope => Ok(Self::TransactionEnvelope(Box::new(
                TransactionEnvelope::read_xdr(r)?,
            ))),
            TypeVariant::TransactionSignaturePayload => Ok(Self::TransactionSignaturePayload(
                Box::new(TransactionSignaturePayload::read_xdr(r)?),
            )),
            TypeVariant::TransactionSignaturePayloadTaggedTransaction => {
                Ok(Self::TransactionSignaturePayloadTaggedTransaction(
                    Box::new(TransactionSignaturePayloadTaggedTransaction::read_xdr(r)?),
                ))
            }
            TypeVariant::ClaimAtomType => {
                Ok(Self::ClaimAtomType(Box::new(ClaimAtomType::read_xdr(r)?)))
            }
            TypeVariant::ClaimOfferAtomV0 => Ok(Self::ClaimOfferAtomV0(Box::new(
                ClaimOfferAtomV0::read_xdr(r)?,
            ))),
            TypeVariant::ClaimOfferAtom => {
                Ok(Self::ClaimOfferAtom(Box::new(ClaimOfferAtom::read_xdr(r)?)))
            }
            TypeVariant::ClaimLiquidityAtom => Ok(Self::ClaimLiquidityAtom(Box::new(
                ClaimLiquidityAtom::read_xdr(r)?,
            ))),
            TypeVariant::ClaimAtom => Ok(Self::ClaimAtom(Box::new(ClaimAtom::read_xdr(r)?))),
            TypeVariant::CreateAccountResultCode => Ok(Self::CreateAccountResultCode(Box::new(
                CreateAccountResultCode::read_xdr(r)?,
            ))),
            TypeVariant::CreateAccountResult => Ok(Self::CreateAccountResult(Box::new(
                CreateAccountResult::read_xdr(r)?,
            ))),
            TypeVariant::PaymentResultCode => Ok(Self::PaymentResultCode(Box::new(
                PaymentResultCode::read_xdr(r)?,
            ))),
            TypeVariant::PaymentResult => {
                Ok(Self::PaymentResult(Box::new(PaymentResult::read_xdr(r)?)))
            }
            TypeVariant::PathPaymentStrictReceiveResultCode => {
                Ok(Self::PathPaymentStrictReceiveResultCode(Box::new(
                    PathPaymentStrictReceiveResultCode::read_xdr(r)?,
                )))
            }
            TypeVariant::SimplePaymentResult => Ok(Self::SimplePaymentResult(Box::new(
                SimplePaymentResult::read_xdr(r)?,
            ))),
            TypeVariant::PathPaymentStrictReceiveResult => {
                Ok(Self::PathPaymentStrictReceiveResult(Box::new(
                    PathPaymentStrictReceiveResult::read_xdr(r)?,
                )))
            }
            TypeVariant::PathPaymentStrictReceiveResultSuccess => {
                Ok(Self::PathPaymentStrictReceiveResultSuccess(Box::new(
                    PathPaymentStrictReceiveResultSuccess::read_xdr(r)?,
                )))
            }
            TypeVariant::PathPaymentStrictSendResultCode => {
                Ok(Self::PathPaymentStrictSendResultCode(Box::new(
                    PathPaymentStrictSendResultCode::read_xdr(r)?,
                )))
            }
            TypeVariant::PathPaymentStrictSendResult => Ok(Self::PathPaymentStrictSendResult(
                Box::new(PathPaymentStrictSendResult::read_xdr(r)?),
            )),
            TypeVariant::PathPaymentStrictSendResultSuccess => {
                Ok(Self::PathPaymentStrictSendResultSuccess(Box::new(
                    PathPaymentStrictSendResultSuccess::read_xdr(r)?,
                )))
            }
            TypeVariant::ManageSellOfferResultCode => Ok(Self::ManageSellOfferResultCode(
                Box::new(ManageSellOfferResultCode::read_xdr(r)?),
            )),
            TypeVariant::ManageOfferEffect => Ok(Self::ManageOfferEffect(Box::new(
                ManageOfferEffect::read_xdr(r)?,
            ))),
            TypeVariant::ManageOfferSuccessResult => Ok(Self::ManageOfferSuccessResult(Box::new(
                ManageOfferSuccessResult::read_xdr(r)?,
            ))),
            TypeVariant::ManageOfferSuccessResultOffer => Ok(Self::ManageOfferSuccessResultOffer(
                Box::new(ManageOfferSuccessResultOffer::read_xdr(r)?),
            )),
            TypeVariant::ManageSellOfferResult => Ok(Self::ManageSellOfferResult(Box::new(
                ManageSellOfferResult::read_xdr(r)?,
            ))),
            TypeVariant::ManageBuyOfferResultCode => Ok(Self::ManageBuyOfferResultCode(Box::new(
                ManageBuyOfferResultCode::read_xdr(r)?,
            ))),
            TypeVariant::ManageBuyOfferResult => Ok(Self::ManageBuyOfferResult(Box::new(
                ManageBuyOfferResult::read_xdr(r)?,
            ))),
            TypeVariant::SetOptionsResultCode => Ok(Self::SetOptionsResultCode(Box::new(
                SetOptionsResultCode::read_xdr(r)?,
            ))),
            TypeVariant::SetOptionsResult => Ok(Self::SetOptionsResult(Box::new(
                SetOptionsResult::read_xdr(r)?,
            ))),
            TypeVariant::ChangeTrustResultCode => Ok(Self::ChangeTrustResultCode(Box::new(
                ChangeTrustResultCode::read_xdr(r)?,
            ))),
            TypeVariant::ChangeTrustResult => Ok(Self::ChangeTrustResult(Box::new(
                ChangeTrustResult::read_xdr(r)?,
            ))),
            TypeVariant::AllowTrustResultCode => Ok(Self::AllowTrustResultCode(Box::new(
                AllowTrustResultCode::read_xdr(r)?,
            ))),
            TypeVariant::AllowTrustResult => Ok(Self::AllowTrustResult(Box::new(
                AllowTrustResult::read_xdr(r)?,
            ))),
            TypeVariant::AccountMergeResultCode => Ok(Self::AccountMergeResultCode(Box::new(
                AccountMergeResultCode::read_xdr(r)?,
            ))),
            TypeVariant::AccountMergeResult => Ok(Self::AccountMergeResult(Box::new(
                AccountMergeResult::read_xdr(r)?,
            ))),
            TypeVariant::InflationResultCode => Ok(Self::InflationResultCode(Box::new(
                InflationResultCode::read_xdr(r)?,
            ))),
            TypeVariant::InflationPayout => Ok(Self::InflationPayout(Box::new(
                InflationPayout::read_xdr(r)?,
            ))),
            TypeVariant::InflationResult => Ok(Self::InflationResult(Box::new(
                InflationResult::read_xdr(r)?,
            ))),
            TypeVariant::ManageDataResultCode => Ok(Self::ManageDataResultCode(Box::new(
                ManageDataResultCode::read_xdr(r)?,
            ))),
            TypeVariant::ManageDataResult => Ok(Self::ManageDataResult(Box::new(
                ManageDataResult::read_xdr(r)?,
            ))),
            TypeVariant::BumpSequenceResultCode => Ok(Self::BumpSequenceResultCode(Box::new(
                BumpSequenceResultCode::read_xdr(r)?,
            ))),
            TypeVariant::BumpSequenceResult => Ok(Self::BumpSequenceResult(Box::new(
                BumpSequenceResult::read_xdr(r)?,
            ))),
            TypeVariant::CreateClaimableBalanceResultCode => {
                Ok(Self::CreateClaimableBalanceResultCode(Box::new(
                    CreateClaimableBalanceResultCode::read_xdr(r)?,
                )))
            }
            TypeVariant::CreateClaimableBalanceResult => Ok(Self::CreateClaimableBalanceResult(
                Box::new(CreateClaimableBalanceResult::read_xdr(r)?),
            )),
            TypeVariant::ClaimClaimableBalanceResultCode => {
                Ok(Self::ClaimClaimableBalanceResultCode(Box::new(
                    ClaimClaimableBalanceResultCode::read_xdr(r)?,
                )))
            }
            TypeVariant::ClaimClaimableBalanceResult => Ok(Self::ClaimClaimableBalanceResult(
                Box::new(ClaimClaimableBalanceResult::read_xdr(r)?),
            )),
            TypeVariant::BeginSponsoringFutureReservesResultCode => {
                Ok(Self::BeginSponsoringFutureReservesResultCode(Box::new(
                    BeginSponsoringFutureReservesResultCode::read_xdr(r)?,
                )))
            }
            TypeVariant::BeginSponsoringFutureReservesResult => {
                Ok(Self::BeginSponsoringFutureReservesResult(Box::new(
                    BeginSponsoringFutureReservesResult::read_xdr(r)?,
                )))
            }
            TypeVariant::EndSponsoringFutureReservesResultCode => {
                Ok(Self::EndSponsoringFutureReservesResultCode(Box::new(
                    EndSponsoringFutureReservesResultCode::read_xdr(r)?,
                )))
            }
            TypeVariant::EndSponsoringFutureReservesResult => {
                Ok(Self::EndSponsoringFutureReservesResult(Box::new(
                    EndSponsoringFutureReservesResult::read_xdr(r)?,
                )))
            }
            TypeVariant::RevokeSponsorshipResultCode => Ok(Self::RevokeSponsorshipResultCode(
                Box::new(RevokeSponsorshipResultCode::read_xdr(r)?),
            )),
            TypeVariant::RevokeSponsorshipResult => Ok(Self::RevokeSponsorshipResult(Box::new(
                RevokeSponsorshipResult::read_xdr(r)?,
            ))),
            TypeVariant::ClawbackResultCode => Ok(Self::ClawbackResultCode(Box::new(
                ClawbackResultCode::read_xdr(r)?,
            ))),
            TypeVariant::ClawbackResult => {
                Ok(Self::ClawbackResult(Box::new(ClawbackResult::read_xdr(r)?)))
            }
            TypeVariant::ClawbackClaimableBalanceResultCode => {
                Ok(Self::ClawbackClaimableBalanceResultCode(Box::new(
                    ClawbackClaimableBalanceResultCode::read_xdr(r)?,
                )))
            }
            TypeVariant::ClawbackClaimableBalanceResult => {
                Ok(Self::ClawbackClaimableBalanceResult(Box::new(
                    ClawbackClaimableBalanceResult::read_xdr(r)?,
                )))
            }
            TypeVariant::SetTrustLineFlagsResultCode => Ok(Self::SetTrustLineFlagsResultCode(
                Box::new(SetTrustLineFlagsResultCode::read_xdr(r)?),
            )),
            TypeVariant::SetTrustLineFlagsResult => Ok(Self::SetTrustLineFlagsResult(Box::new(
                SetTrustLineFlagsResult::read_xdr(r)?,
            ))),
            TypeVariant::LiquidityPoolDepositResultCode => {
                Ok(Self::LiquidityPoolDepositResultCode(Box::new(
                    LiquidityPoolDepositResultCode::read_xdr(r)?,
                )))
            }
            TypeVariant::LiquidityPoolDepositResult => Ok(Self::LiquidityPoolDepositResult(
                Box::new(LiquidityPoolDepositResult::read_xdr(r)?),
            )),
            TypeVariant::LiquidityPoolWithdrawResultCode => {
                Ok(Self::LiquidityPoolWithdrawResultCode(Box::new(
                    LiquidityPoolWithdrawResultCode::read_xdr(r)?,
                )))
            }
            TypeVariant::LiquidityPoolWithdrawResult => Ok(Self::LiquidityPoolWithdrawResult(
                Box::new(LiquidityPoolWithdrawResult::read_xdr(r)?),
            )),
            TypeVariant::InvokeHostFunctionResultCode => Ok(Self::InvokeHostFunctionResultCode(
                Box::new(InvokeHostFunctionResultCode::read_xdr(r)?),
            )),
            TypeVariant::InvokeHostFunctionResult => Ok(Self::InvokeHostFunctionResult(Box::new(
                InvokeHostFunctionResult::read_xdr(r)?,
            ))),
            TypeVariant::OperationResultCode => Ok(Self::OperationResultCode(Box::new(
                OperationResultCode::read_xdr(r)?,
            ))),
            TypeVariant::OperationResult => Ok(Self::OperationResult(Box::new(
                OperationResult::read_xdr(r)?,
            ))),
            TypeVariant::OperationResultTr => Ok(Self::OperationResultTr(Box::new(
                OperationResultTr::read_xdr(r)?,
            ))),
            TypeVariant::TransactionResultCode => Ok(Self::TransactionResultCode(Box::new(
                TransactionResultCode::read_xdr(r)?,
            ))),
            TypeVariant::InnerTransactionResult => Ok(Self::InnerTransactionResult(Box::new(
                InnerTransactionResult::read_xdr(r)?,
            ))),
            TypeVariant::InnerTransactionResultResult => Ok(Self::InnerTransactionResultResult(
                Box::new(InnerTransactionResultResult::read_xdr(r)?),
            )),
            TypeVariant::InnerTransactionResultExt => Ok(Self::InnerTransactionResultExt(
                Box::new(InnerTransactionResultExt::read_xdr(r)?),
            )),
            TypeVariant::InnerTransactionResultPair => Ok(Self::InnerTransactionResultPair(
                Box::new(InnerTransactionResultPair::read_xdr(r)?),
            )),
            TypeVariant::TransactionResult => Ok(Self::TransactionResult(Box::new(
                TransactionResult::read_xdr(r)?,
            ))),
            TypeVariant::TransactionResultResult => Ok(Self::TransactionResultResult(Box::new(
                TransactionResultResult::read_xdr(r)?,
            ))),
            TypeVariant::TransactionResultExt => Ok(Self::TransactionResultExt(Box::new(
                TransactionResultExt::read_xdr(r)?,
            ))),
            TypeVariant::Hash => Ok(Self::Hash(Box::new(Hash::read_xdr(r)?))),
            TypeVariant::Uint256 => Ok(Self::Uint256(Box::new(Uint256::read_xdr(r)?))),
            TypeVariant::Uint32 => Ok(Self::Uint32(Box::new(Uint32::read_xdr(r)?))),
            TypeVariant::Int32 => Ok(Self::Int32(Box::new(Int32::read_xdr(r)?))),
            TypeVariant::Uint64 => Ok(Self::Uint64(Box::new(Uint64::read_xdr(r)?))),
            TypeVariant::Int64 => Ok(Self::Int64(Box::new(Int64::read_xdr(r)?))),
            TypeVariant::ExtensionPoint => {
                Ok(Self::ExtensionPoint(Box::new(ExtensionPoint::read_xdr(r)?)))
            }
            TypeVariant::CryptoKeyType => {
                Ok(Self::CryptoKeyType(Box::new(CryptoKeyType::read_xdr(r)?)))
            }
            TypeVariant::PublicKeyType => {
                Ok(Self::PublicKeyType(Box::new(PublicKeyType::read_xdr(r)?)))
            }
            TypeVariant::SignerKeyType => {
                Ok(Self::SignerKeyType(Box::new(SignerKeyType::read_xdr(r)?)))
            }
            TypeVariant::PublicKey => Ok(Self::PublicKey(Box::new(PublicKey::read_xdr(r)?))),
            TypeVariant::SignerKey => Ok(Self::SignerKey(Box::new(SignerKey::read_xdr(r)?))),
            TypeVariant::SignerKeyEd25519SignedPayload => Ok(Self::SignerKeyEd25519SignedPayload(
                Box::new(SignerKeyEd25519SignedPayload::read_xdr(r)?),
            )),
            TypeVariant::Signature => Ok(Self::Signature(Box::new(Signature::read_xdr(r)?))),
            TypeVariant::SignatureHint => {
                Ok(Self::SignatureHint(Box::new(SignatureHint::read_xdr(r)?)))
            }
            TypeVariant::NodeId => Ok(Self::NodeId(Box::new(NodeId::read_xdr(r)?))),
            TypeVariant::AccountId => Ok(Self::AccountId(Box::new(AccountId::read_xdr(r)?))),
            TypeVariant::Curve25519Secret => Ok(Self::Curve25519Secret(Box::new(
                Curve25519Secret::read_xdr(r)?,
            ))),
            TypeVariant::Curve25519Public => Ok(Self::Curve25519Public(Box::new(
                Curve25519Public::read_xdr(r)?,
            ))),
            TypeVariant::HmacSha256Key => {
                Ok(Self::HmacSha256Key(Box::new(HmacSha256Key::read_xdr(r)?)))
            }
            TypeVariant::HmacSha256Mac => {
                Ok(Self::HmacSha256Mac(Box::new(HmacSha256Mac::read_xdr(r)?)))
            }
        }
    }

    #[cfg(feature = "base64")]
    pub fn read_xdr_base64(v: TypeVariant, r: &mut impl Read) -> Result<Self> {
        let mut dec = base64::read::DecoderReader::new(r, base64::STANDARD);
        let t = Self::read_xdr(v, &mut dec)?;
        Ok(t)
    }

    #[cfg(feature = "std")]
    pub fn read_xdr_to_end(v: TypeVariant, r: &mut impl Read) -> Result<Self> {
        let s = Self::read_xdr(v, r)?;
        // Check that any further reads, such as this read of one byte, read no
        // data, indicating EOF. If a byte is read the data is invalid.
        if r.read(&mut [0u8; 1])? == 0 {
            Ok(s)
        } else {
            Err(Error::Invalid)
        }
    }

    #[cfg(feature = "base64")]
    pub fn read_xdr_base64_to_end(v: TypeVariant, r: &mut impl Read) -> Result<Self> {
        let mut dec = base64::read::DecoderReader::new(r, base64::STANDARD);
        let t = Self::read_xdr_to_end(v, &mut dec)?;
        Ok(t)
    }

    #[cfg(feature = "std")]
    #[allow(clippy::too_many_lines)]
    pub fn read_xdr_iter<R: Read>(
        v: TypeVariant,
        r: &mut R,
    ) -> Box<dyn Iterator<Item = Result<Self>> + '_> {
        match v {
            TypeVariant::Value => Box::new(
                ReadXdrIter::<_, Value>::new(r).map(|r| r.map(|t| Self::Value(Box::new(t)))),
            ),
            TypeVariant::ScpBallot => Box::new(
                ReadXdrIter::<_, ScpBallot>::new(r)
                    .map(|r| r.map(|t| Self::ScpBallot(Box::new(t)))),
            ),
            TypeVariant::ScpStatementType => Box::new(
                ReadXdrIter::<_, ScpStatementType>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementType(Box::new(t)))),
            ),
            TypeVariant::ScpNomination => Box::new(
                ReadXdrIter::<_, ScpNomination>::new(r)
                    .map(|r| r.map(|t| Self::ScpNomination(Box::new(t)))),
            ),
            TypeVariant::ScpStatement => Box::new(
                ReadXdrIter::<_, ScpStatement>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatement(Box::new(t)))),
            ),
            TypeVariant::ScpStatementPledges => Box::new(
                ReadXdrIter::<_, ScpStatementPledges>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementPledges(Box::new(t)))),
            ),
            TypeVariant::ScpStatementPrepare => Box::new(
                ReadXdrIter::<_, ScpStatementPrepare>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementPrepare(Box::new(t)))),
            ),
            TypeVariant::ScpStatementConfirm => Box::new(
                ReadXdrIter::<_, ScpStatementConfirm>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementConfirm(Box::new(t)))),
            ),
            TypeVariant::ScpStatementExternalize => Box::new(
                ReadXdrIter::<_, ScpStatementExternalize>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementExternalize(Box::new(t)))),
            ),
            TypeVariant::ScpEnvelope => Box::new(
                ReadXdrIter::<_, ScpEnvelope>::new(r)
                    .map(|r| r.map(|t| Self::ScpEnvelope(Box::new(t)))),
            ),
            TypeVariant::ScpQuorumSet => Box::new(
                ReadXdrIter::<_, ScpQuorumSet>::new(r)
                    .map(|r| r.map(|t| Self::ScpQuorumSet(Box::new(t)))),
            ),
            TypeVariant::ScEnvMetaKind => Box::new(
                ReadXdrIter::<_, ScEnvMetaKind>::new(r)
                    .map(|r| r.map(|t| Self::ScEnvMetaKind(Box::new(t)))),
            ),
            TypeVariant::ScEnvMetaEntry => Box::new(
                ReadXdrIter::<_, ScEnvMetaEntry>::new(r)
                    .map(|r| r.map(|t| Self::ScEnvMetaEntry(Box::new(t)))),
            ),
            TypeVariant::ScSpecType => Box::new(
                ReadXdrIter::<_, ScSpecType>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecType(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeOption => Box::new(
                ReadXdrIter::<_, ScSpecTypeOption>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeOption(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeResult => Box::new(
                ReadXdrIter::<_, ScSpecTypeResult>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeResult(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeVec => Box::new(
                ReadXdrIter::<_, ScSpecTypeVec>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeVec(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeMap => Box::new(
                ReadXdrIter::<_, ScSpecTypeMap>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeMap(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeSet => Box::new(
                ReadXdrIter::<_, ScSpecTypeSet>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeSet(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeTuple => Box::new(
                ReadXdrIter::<_, ScSpecTypeTuple>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeTuple(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeBytesN => Box::new(
                ReadXdrIter::<_, ScSpecTypeBytesN>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeBytesN(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeUdt => Box::new(
                ReadXdrIter::<_, ScSpecTypeUdt>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeUdt(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeDef => Box::new(
                ReadXdrIter::<_, ScSpecTypeDef>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeDef(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtStructFieldV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtStructFieldV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtStructFieldV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtStructV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtStructV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtStructV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtUnionCaseV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtUnionCaseV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtUnionCaseV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtUnionV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtUnionV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtUnionV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtEnumCaseV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtEnumCaseV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtEnumCaseV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtEnumV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtEnumV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtEnumV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtErrorEnumCaseV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtErrorEnumCaseV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtErrorEnumCaseV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtErrorEnumV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtErrorEnumV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtErrorEnumV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecFunctionInputV0 => Box::new(
                ReadXdrIter::<_, ScSpecFunctionInputV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecFunctionInputV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecFunctionV0 => Box::new(
                ReadXdrIter::<_, ScSpecFunctionV0>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecFunctionV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecEntryKind => Box::new(
                ReadXdrIter::<_, ScSpecEntryKind>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecEntryKind(Box::new(t)))),
            ),
            TypeVariant::ScSpecEntry => Box::new(
                ReadXdrIter::<_, ScSpecEntry>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecEntry(Box::new(t)))),
            ),
            TypeVariant::ScSymbol => Box::new(
                ReadXdrIter::<_, ScSymbol>::new(r).map(|r| r.map(|t| Self::ScSymbol(Box::new(t)))),
            ),
            TypeVariant::ScValType => Box::new(
                ReadXdrIter::<_, ScValType>::new(r)
                    .map(|r| r.map(|t| Self::ScValType(Box::new(t)))),
            ),
            TypeVariant::ScStatic => Box::new(
                ReadXdrIter::<_, ScStatic>::new(r).map(|r| r.map(|t| Self::ScStatic(Box::new(t)))),
            ),
            TypeVariant::ScStatusType => Box::new(
                ReadXdrIter::<_, ScStatusType>::new(r)
                    .map(|r| r.map(|t| Self::ScStatusType(Box::new(t)))),
            ),
            TypeVariant::ScHostValErrorCode => Box::new(
                ReadXdrIter::<_, ScHostValErrorCode>::new(r)
                    .map(|r| r.map(|t| Self::ScHostValErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScHostObjErrorCode => Box::new(
                ReadXdrIter::<_, ScHostObjErrorCode>::new(r)
                    .map(|r| r.map(|t| Self::ScHostObjErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScHostFnErrorCode => Box::new(
                ReadXdrIter::<_, ScHostFnErrorCode>::new(r)
                    .map(|r| r.map(|t| Self::ScHostFnErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScHostStorageErrorCode => Box::new(
                ReadXdrIter::<_, ScHostStorageErrorCode>::new(r)
                    .map(|r| r.map(|t| Self::ScHostStorageErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScHostContextErrorCode => Box::new(
                ReadXdrIter::<_, ScHostContextErrorCode>::new(r)
                    .map(|r| r.map(|t| Self::ScHostContextErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScVmErrorCode => Box::new(
                ReadXdrIter::<_, ScVmErrorCode>::new(r)
                    .map(|r| r.map(|t| Self::ScVmErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScUnknownErrorCode => Box::new(
                ReadXdrIter::<_, ScUnknownErrorCode>::new(r)
                    .map(|r| r.map(|t| Self::ScUnknownErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScStatus => Box::new(
                ReadXdrIter::<_, ScStatus>::new(r).map(|r| r.map(|t| Self::ScStatus(Box::new(t)))),
            ),
            TypeVariant::ScVal => Box::new(
                ReadXdrIter::<_, ScVal>::new(r).map(|r| r.map(|t| Self::ScVal(Box::new(t)))),
            ),
            TypeVariant::ScObjectType => Box::new(
                ReadXdrIter::<_, ScObjectType>::new(r)
                    .map(|r| r.map(|t| Self::ScObjectType(Box::new(t)))),
            ),
            TypeVariant::ScMapEntry => Box::new(
                ReadXdrIter::<_, ScMapEntry>::new(r)
                    .map(|r| r.map(|t| Self::ScMapEntry(Box::new(t)))),
            ),
            TypeVariant::ScVec => Box::new(
                ReadXdrIter::<_, ScVec>::new(r).map(|r| r.map(|t| Self::ScVec(Box::new(t)))),
            ),
            TypeVariant::ScMap => Box::new(
                ReadXdrIter::<_, ScMap>::new(r).map(|r| r.map(|t| Self::ScMap(Box::new(t)))),
            ),
            TypeVariant::ScContractCodeType => Box::new(
                ReadXdrIter::<_, ScContractCodeType>::new(r)
                    .map(|r| r.map(|t| Self::ScContractCodeType(Box::new(t)))),
            ),
            TypeVariant::ScContractCode => Box::new(
                ReadXdrIter::<_, ScContractCode>::new(r)
                    .map(|r| r.map(|t| Self::ScContractCode(Box::new(t)))),
            ),
            TypeVariant::Int128Parts => Box::new(
                ReadXdrIter::<_, Int128Parts>::new(r)
                    .map(|r| r.map(|t| Self::Int128Parts(Box::new(t)))),
            ),
            TypeVariant::ScObject => Box::new(
                ReadXdrIter::<_, ScObject>::new(r).map(|r| r.map(|t| Self::ScObject(Box::new(t)))),
            ),
            TypeVariant::StoredTransactionSet => Box::new(
                ReadXdrIter::<_, StoredTransactionSet>::new(r)
                    .map(|r| r.map(|t| Self::StoredTransactionSet(Box::new(t)))),
            ),
            TypeVariant::PersistedScpStateV0 => Box::new(
                ReadXdrIter::<_, PersistedScpStateV0>::new(r)
                    .map(|r| r.map(|t| Self::PersistedScpStateV0(Box::new(t)))),
            ),
            TypeVariant::PersistedScpStateV1 => Box::new(
                ReadXdrIter::<_, PersistedScpStateV1>::new(r)
                    .map(|r| r.map(|t| Self::PersistedScpStateV1(Box::new(t)))),
            ),
            TypeVariant::PersistedScpState => Box::new(
                ReadXdrIter::<_, PersistedScpState>::new(r)
                    .map(|r| r.map(|t| Self::PersistedScpState(Box::new(t)))),
            ),
            TypeVariant::Thresholds => Box::new(
                ReadXdrIter::<_, Thresholds>::new(r)
                    .map(|r| r.map(|t| Self::Thresholds(Box::new(t)))),
            ),
            TypeVariant::String32 => Box::new(
                ReadXdrIter::<_, String32>::new(r).map(|r| r.map(|t| Self::String32(Box::new(t)))),
            ),
            TypeVariant::String64 => Box::new(
                ReadXdrIter::<_, String64>::new(r).map(|r| r.map(|t| Self::String64(Box::new(t)))),
            ),
            TypeVariant::SequenceNumber => Box::new(
                ReadXdrIter::<_, SequenceNumber>::new(r)
                    .map(|r| r.map(|t| Self::SequenceNumber(Box::new(t)))),
            ),
            TypeVariant::TimePoint => Box::new(
                ReadXdrIter::<_, TimePoint>::new(r)
                    .map(|r| r.map(|t| Self::TimePoint(Box::new(t)))),
            ),
            TypeVariant::Duration => Box::new(
                ReadXdrIter::<_, Duration>::new(r).map(|r| r.map(|t| Self::Duration(Box::new(t)))),
            ),
            TypeVariant::DataValue => Box::new(
                ReadXdrIter::<_, DataValue>::new(r)
                    .map(|r| r.map(|t| Self::DataValue(Box::new(t)))),
            ),
            TypeVariant::PoolId => Box::new(
                ReadXdrIter::<_, PoolId>::new(r).map(|r| r.map(|t| Self::PoolId(Box::new(t)))),
            ),
            TypeVariant::AssetCode4 => Box::new(
                ReadXdrIter::<_, AssetCode4>::new(r)
                    .map(|r| r.map(|t| Self::AssetCode4(Box::new(t)))),
            ),
            TypeVariant::AssetCode12 => Box::new(
                ReadXdrIter::<_, AssetCode12>::new(r)
                    .map(|r| r.map(|t| Self::AssetCode12(Box::new(t)))),
            ),
            TypeVariant::AssetType => Box::new(
                ReadXdrIter::<_, AssetType>::new(r)
                    .map(|r| r.map(|t| Self::AssetType(Box::new(t)))),
            ),
            TypeVariant::AssetCode => Box::new(
                ReadXdrIter::<_, AssetCode>::new(r)
                    .map(|r| r.map(|t| Self::AssetCode(Box::new(t)))),
            ),
            TypeVariant::AlphaNum4 => Box::new(
                ReadXdrIter::<_, AlphaNum4>::new(r)
                    .map(|r| r.map(|t| Self::AlphaNum4(Box::new(t)))),
            ),
            TypeVariant::AlphaNum12 => Box::new(
                ReadXdrIter::<_, AlphaNum12>::new(r)
                    .map(|r| r.map(|t| Self::AlphaNum12(Box::new(t)))),
            ),
            TypeVariant::Asset => Box::new(
                ReadXdrIter::<_, Asset>::new(r).map(|r| r.map(|t| Self::Asset(Box::new(t)))),
            ),
            TypeVariant::Price => Box::new(
                ReadXdrIter::<_, Price>::new(r).map(|r| r.map(|t| Self::Price(Box::new(t)))),
            ),
            TypeVariant::Liabilities => Box::new(
                ReadXdrIter::<_, Liabilities>::new(r)
                    .map(|r| r.map(|t| Self::Liabilities(Box::new(t)))),
            ),
            TypeVariant::ThresholdIndexes => Box::new(
                ReadXdrIter::<_, ThresholdIndexes>::new(r)
                    .map(|r| r.map(|t| Self::ThresholdIndexes(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryType => Box::new(
                ReadXdrIter::<_, LedgerEntryType>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryType(Box::new(t)))),
            ),
            TypeVariant::Signer => Box::new(
                ReadXdrIter::<_, Signer>::new(r).map(|r| r.map(|t| Self::Signer(Box::new(t)))),
            ),
            TypeVariant::AccountFlags => Box::new(
                ReadXdrIter::<_, AccountFlags>::new(r)
                    .map(|r| r.map(|t| Self::AccountFlags(Box::new(t)))),
            ),
            TypeVariant::SponsorshipDescriptor => Box::new(
                ReadXdrIter::<_, SponsorshipDescriptor>::new(r)
                    .map(|r| r.map(|t| Self::SponsorshipDescriptor(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV3 => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV3>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV3(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV2 => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV2>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV2(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV2Ext => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV2Ext>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV2Ext(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV1 => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV1>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV1(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV1Ext => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV1Ext>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV1Ext(Box::new(t)))),
            ),
            TypeVariant::AccountEntry => Box::new(
                ReadXdrIter::<_, AccountEntry>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntry(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExt => Box::new(
                ReadXdrIter::<_, AccountEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExt(Box::new(t)))),
            ),
            TypeVariant::TrustLineFlags => Box::new(
                ReadXdrIter::<_, TrustLineFlags>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineFlags(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolType => Box::new(
                ReadXdrIter::<_, LiquidityPoolType>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolType(Box::new(t)))),
            ),
            TypeVariant::TrustLineAsset => Box::new(
                ReadXdrIter::<_, TrustLineAsset>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineAsset(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryExtensionV2 => Box::new(
                ReadXdrIter::<_, TrustLineEntryExtensionV2>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryExtensionV2(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryExtensionV2Ext => Box::new(
                ReadXdrIter::<_, TrustLineEntryExtensionV2Ext>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryExtensionV2Ext(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntry => Box::new(
                ReadXdrIter::<_, TrustLineEntry>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntry(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryExt => Box::new(
                ReadXdrIter::<_, TrustLineEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryExt(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryV1 => Box::new(
                ReadXdrIter::<_, TrustLineEntryV1>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryV1(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryV1Ext => Box::new(
                ReadXdrIter::<_, TrustLineEntryV1Ext>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryV1Ext(Box::new(t)))),
            ),
            TypeVariant::OfferEntryFlags => Box::new(
                ReadXdrIter::<_, OfferEntryFlags>::new(r)
                    .map(|r| r.map(|t| Self::OfferEntryFlags(Box::new(t)))),
            ),
            TypeVariant::OfferEntry => Box::new(
                ReadXdrIter::<_, OfferEntry>::new(r)
                    .map(|r| r.map(|t| Self::OfferEntry(Box::new(t)))),
            ),
            TypeVariant::OfferEntryExt => Box::new(
                ReadXdrIter::<_, OfferEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::OfferEntryExt(Box::new(t)))),
            ),
            TypeVariant::DataEntry => Box::new(
                ReadXdrIter::<_, DataEntry>::new(r)
                    .map(|r| r.map(|t| Self::DataEntry(Box::new(t)))),
            ),
            TypeVariant::DataEntryExt => Box::new(
                ReadXdrIter::<_, DataEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::DataEntryExt(Box::new(t)))),
            ),
            TypeVariant::ClaimPredicateType => Box::new(
                ReadXdrIter::<_, ClaimPredicateType>::new(r)
                    .map(|r| r.map(|t| Self::ClaimPredicateType(Box::new(t)))),
            ),
            TypeVariant::ClaimPredicate => Box::new(
                ReadXdrIter::<_, ClaimPredicate>::new(r)
                    .map(|r| r.map(|t| Self::ClaimPredicate(Box::new(t)))),
            ),
            TypeVariant::ClaimantType => Box::new(
                ReadXdrIter::<_, ClaimantType>::new(r)
                    .map(|r| r.map(|t| Self::ClaimantType(Box::new(t)))),
            ),
            TypeVariant::Claimant => Box::new(
                ReadXdrIter::<_, Claimant>::new(r).map(|r| r.map(|t| Self::Claimant(Box::new(t)))),
            ),
            TypeVariant::ClaimantV0 => Box::new(
                ReadXdrIter::<_, ClaimantV0>::new(r)
                    .map(|r| r.map(|t| Self::ClaimantV0(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceIdType => Box::new(
                ReadXdrIter::<_, ClaimableBalanceIdType>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceIdType(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceId => Box::new(
                ReadXdrIter::<_, ClaimableBalanceId>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceId(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceFlags => Box::new(
                ReadXdrIter::<_, ClaimableBalanceFlags>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceFlags(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceEntryExtensionV1 => Box::new(
                ReadXdrIter::<_, ClaimableBalanceEntryExtensionV1>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntryExtensionV1(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceEntryExtensionV1Ext => Box::new(
                ReadXdrIter::<_, ClaimableBalanceEntryExtensionV1Ext>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntryExtensionV1Ext(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceEntry => Box::new(
                ReadXdrIter::<_, ClaimableBalanceEntry>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntry(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceEntryExt => Box::new(
                ReadXdrIter::<_, ClaimableBalanceEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntryExt(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolConstantProductParameters => Box::new(
                ReadXdrIter::<_, LiquidityPoolConstantProductParameters>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolConstantProductParameters(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolEntry => Box::new(
                ReadXdrIter::<_, LiquidityPoolEntry>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolEntry(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolEntryBody => Box::new(
                ReadXdrIter::<_, LiquidityPoolEntryBody>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolEntryBody(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolEntryConstantProduct => Box::new(
                ReadXdrIter::<_, LiquidityPoolEntryConstantProduct>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolEntryConstantProduct(Box::new(t)))),
            ),
            TypeVariant::ContractDataEntry => Box::new(
                ReadXdrIter::<_, ContractDataEntry>::new(r)
                    .map(|r| r.map(|t| Self::ContractDataEntry(Box::new(t)))),
            ),
            TypeVariant::ContractCodeEntry => Box::new(
                ReadXdrIter::<_, ContractCodeEntry>::new(r)
                    .map(|r| r.map(|t| Self::ContractCodeEntry(Box::new(t)))),
            ),
            TypeVariant::ConfigSettingType => Box::new(
                ReadXdrIter::<_, ConfigSettingType>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSettingType(Box::new(t)))),
            ),
            TypeVariant::ConfigSetting => Box::new(
                ReadXdrIter::<_, ConfigSetting>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSetting(Box::new(t)))),
            ),
            TypeVariant::ConfigSettingId => Box::new(
                ReadXdrIter::<_, ConfigSettingId>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSettingId(Box::new(t)))),
            ),
            TypeVariant::ConfigSettingEntry => Box::new(
                ReadXdrIter::<_, ConfigSettingEntry>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSettingEntry(Box::new(t)))),
            ),
            TypeVariant::ConfigSettingEntryExt => Box::new(
                ReadXdrIter::<_, ConfigSettingEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSettingEntryExt(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryExtensionV1 => Box::new(
                ReadXdrIter::<_, LedgerEntryExtensionV1>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryExtensionV1(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryExtensionV1Ext => Box::new(
                ReadXdrIter::<_, LedgerEntryExtensionV1Ext>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryExtensionV1Ext(Box::new(t)))),
            ),
            TypeVariant::LedgerEntry => Box::new(
                ReadXdrIter::<_, LedgerEntry>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntry(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryData => Box::new(
                ReadXdrIter::<_, LedgerEntryData>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryData(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryExt => Box::new(
                ReadXdrIter::<_, LedgerEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryExt(Box::new(t)))),
            ),
            TypeVariant::LedgerKey => Box::new(
                ReadXdrIter::<_, LedgerKey>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKey(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyAccount => Box::new(
                ReadXdrIter::<_, LedgerKeyAccount>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyAccount(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyTrustLine => Box::new(
                ReadXdrIter::<_, LedgerKeyTrustLine>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyTrustLine(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyOffer => Box::new(
                ReadXdrIter::<_, LedgerKeyOffer>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyOffer(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyData => Box::new(
                ReadXdrIter::<_, LedgerKeyData>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyData(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyClaimableBalance => Box::new(
                ReadXdrIter::<_, LedgerKeyClaimableBalance>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyClaimableBalance(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyLiquidityPool => Box::new(
                ReadXdrIter::<_, LedgerKeyLiquidityPool>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyLiquidityPool(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyContractData => Box::new(
                ReadXdrIter::<_, LedgerKeyContractData>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyContractData(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyContractCode => Box::new(
                ReadXdrIter::<_, LedgerKeyContractCode>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyContractCode(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyConfigSetting => Box::new(
                ReadXdrIter::<_, LedgerKeyConfigSetting>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyConfigSetting(Box::new(t)))),
            ),
            TypeVariant::EnvelopeType => Box::new(
                ReadXdrIter::<_, EnvelopeType>::new(r)
                    .map(|r| r.map(|t| Self::EnvelopeType(Box::new(t)))),
            ),
            TypeVariant::UpgradeType => Box::new(
                ReadXdrIter::<_, UpgradeType>::new(r)
                    .map(|r| r.map(|t| Self::UpgradeType(Box::new(t)))),
            ),
            TypeVariant::StellarValueType => Box::new(
                ReadXdrIter::<_, StellarValueType>::new(r)
                    .map(|r| r.map(|t| Self::StellarValueType(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseValueSignature => Box::new(
                ReadXdrIter::<_, LedgerCloseValueSignature>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseValueSignature(Box::new(t)))),
            ),
            TypeVariant::StellarValue => Box::new(
                ReadXdrIter::<_, StellarValue>::new(r)
                    .map(|r| r.map(|t| Self::StellarValue(Box::new(t)))),
            ),
            TypeVariant::StellarValueExt => Box::new(
                ReadXdrIter::<_, StellarValueExt>::new(r)
                    .map(|r| r.map(|t| Self::StellarValueExt(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderFlags => Box::new(
                ReadXdrIter::<_, LedgerHeaderFlags>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderFlags(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderExtensionV1 => Box::new(
                ReadXdrIter::<_, LedgerHeaderExtensionV1>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderExtensionV1(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderExtensionV1Ext => Box::new(
                ReadXdrIter::<_, LedgerHeaderExtensionV1Ext>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderExtensionV1Ext(Box::new(t)))),
            ),
            TypeVariant::LedgerHeader => Box::new(
                ReadXdrIter::<_, LedgerHeader>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeader(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderExt => Box::new(
                ReadXdrIter::<_, LedgerHeaderExt>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderExt(Box::new(t)))),
            ),
            TypeVariant::LedgerUpgradeType => Box::new(
                ReadXdrIter::<_, LedgerUpgradeType>::new(r)
                    .map(|r| r.map(|t| Self::LedgerUpgradeType(Box::new(t)))),
            ),
            TypeVariant::LedgerUpgrade => Box::new(
                ReadXdrIter::<_, LedgerUpgrade>::new(r)
                    .map(|r| r.map(|t| Self::LedgerUpgrade(Box::new(t)))),
            ),
            TypeVariant::LedgerUpgradeConfigSetting => Box::new(
                ReadXdrIter::<_, LedgerUpgradeConfigSetting>::new(r)
                    .map(|r| r.map(|t| Self::LedgerUpgradeConfigSetting(Box::new(t)))),
            ),
            TypeVariant::BucketEntryType => Box::new(
                ReadXdrIter::<_, BucketEntryType>::new(r)
                    .map(|r| r.map(|t| Self::BucketEntryType(Box::new(t)))),
            ),
            TypeVariant::BucketMetadata => Box::new(
                ReadXdrIter::<_, BucketMetadata>::new(r)
                    .map(|r| r.map(|t| Self::BucketMetadata(Box::new(t)))),
            ),
            TypeVariant::BucketMetadataExt => Box::new(
                ReadXdrIter::<_, BucketMetadataExt>::new(r)
                    .map(|r| r.map(|t| Self::BucketMetadataExt(Box::new(t)))),
            ),
            TypeVariant::BucketEntry => Box::new(
                ReadXdrIter::<_, BucketEntry>::new(r)
                    .map(|r| r.map(|t| Self::BucketEntry(Box::new(t)))),
            ),
            TypeVariant::TxSetComponentType => Box::new(
                ReadXdrIter::<_, TxSetComponentType>::new(r)
                    .map(|r| r.map(|t| Self::TxSetComponentType(Box::new(t)))),
            ),
            TypeVariant::TxSetComponent => Box::new(
                ReadXdrIter::<_, TxSetComponent>::new(r)
                    .map(|r| r.map(|t| Self::TxSetComponent(Box::new(t)))),
            ),
            TypeVariant::TxSetComponentTxsMaybeDiscountedFee => Box::new(
                ReadXdrIter::<_, TxSetComponentTxsMaybeDiscountedFee>::new(r)
                    .map(|r| r.map(|t| Self::TxSetComponentTxsMaybeDiscountedFee(Box::new(t)))),
            ),
            TypeVariant::TransactionPhase => Box::new(
                ReadXdrIter::<_, TransactionPhase>::new(r)
                    .map(|r| r.map(|t| Self::TransactionPhase(Box::new(t)))),
            ),
            TypeVariant::TransactionSet => Box::new(
                ReadXdrIter::<_, TransactionSet>::new(r)
                    .map(|r| r.map(|t| Self::TransactionSet(Box::new(t)))),
            ),
            TypeVariant::TransactionSetV1 => Box::new(
                ReadXdrIter::<_, TransactionSetV1>::new(r)
                    .map(|r| r.map(|t| Self::TransactionSetV1(Box::new(t)))),
            ),
            TypeVariant::GeneralizedTransactionSet => Box::new(
                ReadXdrIter::<_, GeneralizedTransactionSet>::new(r)
                    .map(|r| r.map(|t| Self::GeneralizedTransactionSet(Box::new(t)))),
            ),
            TypeVariant::TransactionResultPair => Box::new(
                ReadXdrIter::<_, TransactionResultPair>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultPair(Box::new(t)))),
            ),
            TypeVariant::TransactionResultSet => Box::new(
                ReadXdrIter::<_, TransactionResultSet>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultSet(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryEntry => Box::new(
                ReadXdrIter::<_, TransactionHistoryEntry>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryEntry(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryEntryExt => Box::new(
                ReadXdrIter::<_, TransactionHistoryEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryEntryExt(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryResultEntry => Box::new(
                ReadXdrIter::<_, TransactionHistoryResultEntry>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntry(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryResultEntryExt => Box::new(
                ReadXdrIter::<_, TransactionHistoryResultEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntryExt(Box::new(t)))),
            ),
            TypeVariant::TransactionResultPairV2 => Box::new(
                ReadXdrIter::<_, TransactionResultPairV2>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultPairV2(Box::new(t)))),
            ),
            TypeVariant::TransactionResultSetV2 => Box::new(
                ReadXdrIter::<_, TransactionResultSetV2>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultSetV2(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryResultEntryV2 => Box::new(
                ReadXdrIter::<_, TransactionHistoryResultEntryV2>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntryV2(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryResultEntryV2Ext => Box::new(
                ReadXdrIter::<_, TransactionHistoryResultEntryV2Ext>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntryV2Ext(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderHistoryEntry => Box::new(
                ReadXdrIter::<_, LedgerHeaderHistoryEntry>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderHistoryEntry(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderHistoryEntryExt => Box::new(
                ReadXdrIter::<_, LedgerHeaderHistoryEntryExt>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderHistoryEntryExt(Box::new(t)))),
            ),
            TypeVariant::LedgerScpMessages => Box::new(
                ReadXdrIter::<_, LedgerScpMessages>::new(r)
                    .map(|r| r.map(|t| Self::LedgerScpMessages(Box::new(t)))),
            ),
            TypeVariant::ScpHistoryEntryV0 => Box::new(
                ReadXdrIter::<_, ScpHistoryEntryV0>::new(r)
                    .map(|r| r.map(|t| Self::ScpHistoryEntryV0(Box::new(t)))),
            ),
            TypeVariant::ScpHistoryEntry => Box::new(
                ReadXdrIter::<_, ScpHistoryEntry>::new(r)
                    .map(|r| r.map(|t| Self::ScpHistoryEntry(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryChangeType => Box::new(
                ReadXdrIter::<_, LedgerEntryChangeType>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryChangeType(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryChange => Box::new(
                ReadXdrIter::<_, LedgerEntryChange>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryChange(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryChanges => Box::new(
                ReadXdrIter::<_, LedgerEntryChanges>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryChanges(Box::new(t)))),
            ),
            TypeVariant::OperationMeta => Box::new(
                ReadXdrIter::<_, OperationMeta>::new(r)
                    .map(|r| r.map(|t| Self::OperationMeta(Box::new(t)))),
            ),
            TypeVariant::TransactionMetaV1 => Box::new(
                ReadXdrIter::<_, TransactionMetaV1>::new(r)
                    .map(|r| r.map(|t| Self::TransactionMetaV1(Box::new(t)))),
            ),
            TypeVariant::TransactionMetaV2 => Box::new(
                ReadXdrIter::<_, TransactionMetaV2>::new(r)
                    .map(|r| r.map(|t| Self::TransactionMetaV2(Box::new(t)))),
            ),
            TypeVariant::ContractEventType => Box::new(
                ReadXdrIter::<_, ContractEventType>::new(r)
                    .map(|r| r.map(|t| Self::ContractEventType(Box::new(t)))),
            ),
            TypeVariant::ContractEvent => Box::new(
                ReadXdrIter::<_, ContractEvent>::new(r)
                    .map(|r| r.map(|t| Self::ContractEvent(Box::new(t)))),
            ),
            TypeVariant::ContractEventBody => Box::new(
                ReadXdrIter::<_, ContractEventBody>::new(r)
                    .map(|r| r.map(|t| Self::ContractEventBody(Box::new(t)))),
            ),
            TypeVariant::ContractEventV0 => Box::new(
                ReadXdrIter::<_, ContractEventV0>::new(r)
                    .map(|r| r.map(|t| Self::ContractEventV0(Box::new(t)))),
            ),
            TypeVariant::OperationEvents => Box::new(
                ReadXdrIter::<_, OperationEvents>::new(r)
                    .map(|r| r.map(|t| Self::OperationEvents(Box::new(t)))),
            ),
            TypeVariant::TransactionMetaV3 => Box::new(
                ReadXdrIter::<_, TransactionMetaV3>::new(r)
                    .map(|r| r.map(|t| Self::TransactionMetaV3(Box::new(t)))),
            ),
            TypeVariant::TransactionMeta => Box::new(
                ReadXdrIter::<_, TransactionMeta>::new(r)
                    .map(|r| r.map(|t| Self::TransactionMeta(Box::new(t)))),
            ),
            TypeVariant::TransactionResultMeta => Box::new(
                ReadXdrIter::<_, TransactionResultMeta>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultMeta(Box::new(t)))),
            ),
            TypeVariant::TransactionResultMetaV2 => Box::new(
                ReadXdrIter::<_, TransactionResultMetaV2>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultMetaV2(Box::new(t)))),
            ),
            TypeVariant::UpgradeEntryMeta => Box::new(
                ReadXdrIter::<_, UpgradeEntryMeta>::new(r)
                    .map(|r| r.map(|t| Self::UpgradeEntryMeta(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseMetaV0 => Box::new(
                ReadXdrIter::<_, LedgerCloseMetaV0>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseMetaV0(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseMetaV1 => Box::new(
                ReadXdrIter::<_, LedgerCloseMetaV1>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseMetaV1(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseMetaV2 => Box::new(
                ReadXdrIter::<_, LedgerCloseMetaV2>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseMetaV2(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseMeta => Box::new(
                ReadXdrIter::<_, LedgerCloseMeta>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseMeta(Box::new(t)))),
            ),
            TypeVariant::ErrorCode => Box::new(
                ReadXdrIter::<_, ErrorCode>::new(r)
                    .map(|r| r.map(|t| Self::ErrorCode(Box::new(t)))),
            ),
            TypeVariant::SError => Box::new(
                ReadXdrIter::<_, SError>::new(r).map(|r| r.map(|t| Self::SError(Box::new(t)))),
            ),
            TypeVariant::SendMore => Box::new(
                ReadXdrIter::<_, SendMore>::new(r).map(|r| r.map(|t| Self::SendMore(Box::new(t)))),
            ),
            TypeVariant::AuthCert => Box::new(
                ReadXdrIter::<_, AuthCert>::new(r).map(|r| r.map(|t| Self::AuthCert(Box::new(t)))),
            ),
            TypeVariant::Hello => Box::new(
                ReadXdrIter::<_, Hello>::new(r).map(|r| r.map(|t| Self::Hello(Box::new(t)))),
            ),
            TypeVariant::Auth => {
                Box::new(ReadXdrIter::<_, Auth>::new(r).map(|r| r.map(|t| Self::Auth(Box::new(t)))))
            }
            TypeVariant::IpAddrType => Box::new(
                ReadXdrIter::<_, IpAddrType>::new(r)
                    .map(|r| r.map(|t| Self::IpAddrType(Box::new(t)))),
            ),
            TypeVariant::PeerAddress => Box::new(
                ReadXdrIter::<_, PeerAddress>::new(r)
                    .map(|r| r.map(|t| Self::PeerAddress(Box::new(t)))),
            ),
            TypeVariant::PeerAddressIp => Box::new(
                ReadXdrIter::<_, PeerAddressIp>::new(r)
                    .map(|r| r.map(|t| Self::PeerAddressIp(Box::new(t)))),
            ),
            TypeVariant::MessageType => Box::new(
                ReadXdrIter::<_, MessageType>::new(r)
                    .map(|r| r.map(|t| Self::MessageType(Box::new(t)))),
            ),
            TypeVariant::DontHave => Box::new(
                ReadXdrIter::<_, DontHave>::new(r).map(|r| r.map(|t| Self::DontHave(Box::new(t)))),
            ),
            TypeVariant::SurveyMessageCommandType => Box::new(
                ReadXdrIter::<_, SurveyMessageCommandType>::new(r)
                    .map(|r| r.map(|t| Self::SurveyMessageCommandType(Box::new(t)))),
            ),
            TypeVariant::SurveyRequestMessage => Box::new(
                ReadXdrIter::<_, SurveyRequestMessage>::new(r)
                    .map(|r| r.map(|t| Self::SurveyRequestMessage(Box::new(t)))),
            ),
            TypeVariant::SignedSurveyRequestMessage => Box::new(
                ReadXdrIter::<_, SignedSurveyRequestMessage>::new(r)
                    .map(|r| r.map(|t| Self::SignedSurveyRequestMessage(Box::new(t)))),
            ),
            TypeVariant::EncryptedBody => Box::new(
                ReadXdrIter::<_, EncryptedBody>::new(r)
                    .map(|r| r.map(|t| Self::EncryptedBody(Box::new(t)))),
            ),
            TypeVariant::SurveyResponseMessage => Box::new(
                ReadXdrIter::<_, SurveyResponseMessage>::new(r)
                    .map(|r| r.map(|t| Self::SurveyResponseMessage(Box::new(t)))),
            ),
            TypeVariant::SignedSurveyResponseMessage => Box::new(
                ReadXdrIter::<_, SignedSurveyResponseMessage>::new(r)
                    .map(|r| r.map(|t| Self::SignedSurveyResponseMessage(Box::new(t)))),
            ),
            TypeVariant::PeerStats => Box::new(
                ReadXdrIter::<_, PeerStats>::new(r)
                    .map(|r| r.map(|t| Self::PeerStats(Box::new(t)))),
            ),
            TypeVariant::PeerStatList => Box::new(
                ReadXdrIter::<_, PeerStatList>::new(r)
                    .map(|r| r.map(|t| Self::PeerStatList(Box::new(t)))),
            ),
            TypeVariant::TopologyResponseBody => Box::new(
                ReadXdrIter::<_, TopologyResponseBody>::new(r)
                    .map(|r| r.map(|t| Self::TopologyResponseBody(Box::new(t)))),
            ),
            TypeVariant::SurveyResponseBody => Box::new(
                ReadXdrIter::<_, SurveyResponseBody>::new(r)
                    .map(|r| r.map(|t| Self::SurveyResponseBody(Box::new(t)))),
            ),
            TypeVariant::TxAdvertVector => Box::new(
                ReadXdrIter::<_, TxAdvertVector>::new(r)
                    .map(|r| r.map(|t| Self::TxAdvertVector(Box::new(t)))),
            ),
            TypeVariant::FloodAdvert => Box::new(
                ReadXdrIter::<_, FloodAdvert>::new(r)
                    .map(|r| r.map(|t| Self::FloodAdvert(Box::new(t)))),
            ),
            TypeVariant::TxDemandVector => Box::new(
                ReadXdrIter::<_, TxDemandVector>::new(r)
                    .map(|r| r.map(|t| Self::TxDemandVector(Box::new(t)))),
            ),
            TypeVariant::FloodDemand => Box::new(
                ReadXdrIter::<_, FloodDemand>::new(r)
                    .map(|r| r.map(|t| Self::FloodDemand(Box::new(t)))),
            ),
            TypeVariant::StellarMessage => Box::new(
                ReadXdrIter::<_, StellarMessage>::new(r)
                    .map(|r| r.map(|t| Self::StellarMessage(Box::new(t)))),
            ),
            TypeVariant::AuthenticatedMessage => Box::new(
                ReadXdrIter::<_, AuthenticatedMessage>::new(r)
                    .map(|r| r.map(|t| Self::AuthenticatedMessage(Box::new(t)))),
            ),
            TypeVariant::AuthenticatedMessageV0 => Box::new(
                ReadXdrIter::<_, AuthenticatedMessageV0>::new(r)
                    .map(|r| r.map(|t| Self::AuthenticatedMessageV0(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolParameters => Box::new(
                ReadXdrIter::<_, LiquidityPoolParameters>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolParameters(Box::new(t)))),
            ),
            TypeVariant::MuxedAccount => Box::new(
                ReadXdrIter::<_, MuxedAccount>::new(r)
                    .map(|r| r.map(|t| Self::MuxedAccount(Box::new(t)))),
            ),
            TypeVariant::MuxedAccountMed25519 => Box::new(
                ReadXdrIter::<_, MuxedAccountMed25519>::new(r)
                    .map(|r| r.map(|t| Self::MuxedAccountMed25519(Box::new(t)))),
            ),
            TypeVariant::DecoratedSignature => Box::new(
                ReadXdrIter::<_, DecoratedSignature>::new(r)
                    .map(|r| r.map(|t| Self::DecoratedSignature(Box::new(t)))),
            ),
            TypeVariant::LedgerFootprint => Box::new(
                ReadXdrIter::<_, LedgerFootprint>::new(r)
                    .map(|r| r.map(|t| Self::LedgerFootprint(Box::new(t)))),
            ),
            TypeVariant::OperationType => Box::new(
                ReadXdrIter::<_, OperationType>::new(r)
                    .map(|r| r.map(|t| Self::OperationType(Box::new(t)))),
            ),
            TypeVariant::CreateAccountOp => Box::new(
                ReadXdrIter::<_, CreateAccountOp>::new(r)
                    .map(|r| r.map(|t| Self::CreateAccountOp(Box::new(t)))),
            ),
            TypeVariant::PaymentOp => Box::new(
                ReadXdrIter::<_, PaymentOp>::new(r)
                    .map(|r| r.map(|t| Self::PaymentOp(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictReceiveOp => Box::new(
                ReadXdrIter::<_, PathPaymentStrictReceiveOp>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveOp(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictSendOp => Box::new(
                ReadXdrIter::<_, PathPaymentStrictSendOp>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendOp(Box::new(t)))),
            ),
            TypeVariant::ManageSellOfferOp => Box::new(
                ReadXdrIter::<_, ManageSellOfferOp>::new(r)
                    .map(|r| r.map(|t| Self::ManageSellOfferOp(Box::new(t)))),
            ),
            TypeVariant::ManageBuyOfferOp => Box::new(
                ReadXdrIter::<_, ManageBuyOfferOp>::new(r)
                    .map(|r| r.map(|t| Self::ManageBuyOfferOp(Box::new(t)))),
            ),
            TypeVariant::CreatePassiveSellOfferOp => Box::new(
                ReadXdrIter::<_, CreatePassiveSellOfferOp>::new(r)
                    .map(|r| r.map(|t| Self::CreatePassiveSellOfferOp(Box::new(t)))),
            ),
            TypeVariant::SetOptionsOp => Box::new(
                ReadXdrIter::<_, SetOptionsOp>::new(r)
                    .map(|r| r.map(|t| Self::SetOptionsOp(Box::new(t)))),
            ),
            TypeVariant::ChangeTrustAsset => Box::new(
                ReadXdrIter::<_, ChangeTrustAsset>::new(r)
                    .map(|r| r.map(|t| Self::ChangeTrustAsset(Box::new(t)))),
            ),
            TypeVariant::ChangeTrustOp => Box::new(
                ReadXdrIter::<_, ChangeTrustOp>::new(r)
                    .map(|r| r.map(|t| Self::ChangeTrustOp(Box::new(t)))),
            ),
            TypeVariant::AllowTrustOp => Box::new(
                ReadXdrIter::<_, AllowTrustOp>::new(r)
                    .map(|r| r.map(|t| Self::AllowTrustOp(Box::new(t)))),
            ),
            TypeVariant::ManageDataOp => Box::new(
                ReadXdrIter::<_, ManageDataOp>::new(r)
                    .map(|r| r.map(|t| Self::ManageDataOp(Box::new(t)))),
            ),
            TypeVariant::BumpSequenceOp => Box::new(
                ReadXdrIter::<_, BumpSequenceOp>::new(r)
                    .map(|r| r.map(|t| Self::BumpSequenceOp(Box::new(t)))),
            ),
            TypeVariant::CreateClaimableBalanceOp => Box::new(
                ReadXdrIter::<_, CreateClaimableBalanceOp>::new(r)
                    .map(|r| r.map(|t| Self::CreateClaimableBalanceOp(Box::new(t)))),
            ),
            TypeVariant::ClaimClaimableBalanceOp => Box::new(
                ReadXdrIter::<_, ClaimClaimableBalanceOp>::new(r)
                    .map(|r| r.map(|t| Self::ClaimClaimableBalanceOp(Box::new(t)))),
            ),
            TypeVariant::BeginSponsoringFutureReservesOp => Box::new(
                ReadXdrIter::<_, BeginSponsoringFutureReservesOp>::new(r)
                    .map(|r| r.map(|t| Self::BeginSponsoringFutureReservesOp(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipType => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipType>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipType(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipOp => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipOp>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipOp(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipOpSigner => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipOpSigner>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipOpSigner(Box::new(t)))),
            ),
            TypeVariant::ClawbackOp => Box::new(
                ReadXdrIter::<_, ClawbackOp>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackOp(Box::new(t)))),
            ),
            TypeVariant::ClawbackClaimableBalanceOp => Box::new(
                ReadXdrIter::<_, ClawbackClaimableBalanceOp>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackClaimableBalanceOp(Box::new(t)))),
            ),
            TypeVariant::SetTrustLineFlagsOp => Box::new(
                ReadXdrIter::<_, SetTrustLineFlagsOp>::new(r)
                    .map(|r| r.map(|t| Self::SetTrustLineFlagsOp(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolDepositOp => Box::new(
                ReadXdrIter::<_, LiquidityPoolDepositOp>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolDepositOp(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolWithdrawOp => Box::new(
                ReadXdrIter::<_, LiquidityPoolWithdrawOp>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolWithdrawOp(Box::new(t)))),
            ),
            TypeVariant::HostFunctionType => Box::new(
                ReadXdrIter::<_, HostFunctionType>::new(r)
                    .map(|r| r.map(|t| Self::HostFunctionType(Box::new(t)))),
            ),
            TypeVariant::ContractIdType => Box::new(
                ReadXdrIter::<_, ContractIdType>::new(r)
                    .map(|r| r.map(|t| Self::ContractIdType(Box::new(t)))),
            ),
            TypeVariant::ContractIdPublicKeyType => Box::new(
                ReadXdrIter::<_, ContractIdPublicKeyType>::new(r)
                    .map(|r| r.map(|t| Self::ContractIdPublicKeyType(Box::new(t)))),
            ),
            TypeVariant::InstallContractCodeArgs => Box::new(
                ReadXdrIter::<_, InstallContractCodeArgs>::new(r)
                    .map(|r| r.map(|t| Self::InstallContractCodeArgs(Box::new(t)))),
            ),
            TypeVariant::ContractId => Box::new(
                ReadXdrIter::<_, ContractId>::new(r)
                    .map(|r| r.map(|t| Self::ContractId(Box::new(t)))),
            ),
            TypeVariant::ContractIdFromEd25519PublicKey => Box::new(
                ReadXdrIter::<_, ContractIdFromEd25519PublicKey>::new(r)
                    .map(|r| r.map(|t| Self::ContractIdFromEd25519PublicKey(Box::new(t)))),
            ),
            TypeVariant::CreateContractArgs => Box::new(
                ReadXdrIter::<_, CreateContractArgs>::new(r)
                    .map(|r| r.map(|t| Self::CreateContractArgs(Box::new(t)))),
            ),
            TypeVariant::HostFunction => Box::new(
                ReadXdrIter::<_, HostFunction>::new(r)
                    .map(|r| r.map(|t| Self::HostFunction(Box::new(t)))),
            ),
            TypeVariant::InvokeHostFunctionOp => Box::new(
                ReadXdrIter::<_, InvokeHostFunctionOp>::new(r)
                    .map(|r| r.map(|t| Self::InvokeHostFunctionOp(Box::new(t)))),
            ),
            TypeVariant::Operation => Box::new(
                ReadXdrIter::<_, Operation>::new(r)
                    .map(|r| r.map(|t| Self::Operation(Box::new(t)))),
            ),
            TypeVariant::OperationBody => Box::new(
                ReadXdrIter::<_, OperationBody>::new(r)
                    .map(|r| r.map(|t| Self::OperationBody(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimage => Box::new(
                ReadXdrIter::<_, HashIdPreimage>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimage(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageOperationId => Box::new(
                ReadXdrIter::<_, HashIdPreimageOperationId>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageOperationId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageRevokeId => Box::new(
                ReadXdrIter::<_, HashIdPreimageRevokeId>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageRevokeId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageEd25519ContractId => Box::new(
                ReadXdrIter::<_, HashIdPreimageEd25519ContractId>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageEd25519ContractId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageContractId => Box::new(
                ReadXdrIter::<_, HashIdPreimageContractId>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageContractId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageFromAsset => Box::new(
                ReadXdrIter::<_, HashIdPreimageFromAsset>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageFromAsset(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageSourceAccountContractId => Box::new(
                ReadXdrIter::<_, HashIdPreimageSourceAccountContractId>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageSourceAccountContractId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageCreateContractArgs => Box::new(
                ReadXdrIter::<_, HashIdPreimageCreateContractArgs>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageCreateContractArgs(Box::new(t)))),
            ),
            TypeVariant::MemoType => Box::new(
                ReadXdrIter::<_, MemoType>::new(r).map(|r| r.map(|t| Self::MemoType(Box::new(t)))),
            ),
            TypeVariant::Memo => {
                Box::new(ReadXdrIter::<_, Memo>::new(r).map(|r| r.map(|t| Self::Memo(Box::new(t)))))
            }
            TypeVariant::TimeBounds => Box::new(
                ReadXdrIter::<_, TimeBounds>::new(r)
                    .map(|r| r.map(|t| Self::TimeBounds(Box::new(t)))),
            ),
            TypeVariant::LedgerBounds => Box::new(
                ReadXdrIter::<_, LedgerBounds>::new(r)
                    .map(|r| r.map(|t| Self::LedgerBounds(Box::new(t)))),
            ),
            TypeVariant::PreconditionsV2 => Box::new(
                ReadXdrIter::<_, PreconditionsV2>::new(r)
                    .map(|r| r.map(|t| Self::PreconditionsV2(Box::new(t)))),
            ),
            TypeVariant::PreconditionType => Box::new(
                ReadXdrIter::<_, PreconditionType>::new(r)
                    .map(|r| r.map(|t| Self::PreconditionType(Box::new(t)))),
            ),
            TypeVariant::Preconditions => Box::new(
                ReadXdrIter::<_, Preconditions>::new(r)
                    .map(|r| r.map(|t| Self::Preconditions(Box::new(t)))),
            ),
            TypeVariant::TransactionV0 => Box::new(
                ReadXdrIter::<_, TransactionV0>::new(r)
                    .map(|r| r.map(|t| Self::TransactionV0(Box::new(t)))),
            ),
            TypeVariant::TransactionV0Ext => Box::new(
                ReadXdrIter::<_, TransactionV0Ext>::new(r)
                    .map(|r| r.map(|t| Self::TransactionV0Ext(Box::new(t)))),
            ),
            TypeVariant::TransactionV0Envelope => Box::new(
                ReadXdrIter::<_, TransactionV0Envelope>::new(r)
                    .map(|r| r.map(|t| Self::TransactionV0Envelope(Box::new(t)))),
            ),
            TypeVariant::Transaction => Box::new(
                ReadXdrIter::<_, Transaction>::new(r)
                    .map(|r| r.map(|t| Self::Transaction(Box::new(t)))),
            ),
            TypeVariant::TransactionExt => Box::new(
                ReadXdrIter::<_, TransactionExt>::new(r)
                    .map(|r| r.map(|t| Self::TransactionExt(Box::new(t)))),
            ),
            TypeVariant::TransactionV1Envelope => Box::new(
                ReadXdrIter::<_, TransactionV1Envelope>::new(r)
                    .map(|r| r.map(|t| Self::TransactionV1Envelope(Box::new(t)))),
            ),
            TypeVariant::FeeBumpTransaction => Box::new(
                ReadXdrIter::<_, FeeBumpTransaction>::new(r)
                    .map(|r| r.map(|t| Self::FeeBumpTransaction(Box::new(t)))),
            ),
            TypeVariant::FeeBumpTransactionInnerTx => Box::new(
                ReadXdrIter::<_, FeeBumpTransactionInnerTx>::new(r)
                    .map(|r| r.map(|t| Self::FeeBumpTransactionInnerTx(Box::new(t)))),
            ),
            TypeVariant::FeeBumpTransactionExt => Box::new(
                ReadXdrIter::<_, FeeBumpTransactionExt>::new(r)
                    .map(|r| r.map(|t| Self::FeeBumpTransactionExt(Box::new(t)))),
            ),
            TypeVariant::FeeBumpTransactionEnvelope => Box::new(
                ReadXdrIter::<_, FeeBumpTransactionEnvelope>::new(r)
                    .map(|r| r.map(|t| Self::FeeBumpTransactionEnvelope(Box::new(t)))),
            ),
            TypeVariant::TransactionEnvelope => Box::new(
                ReadXdrIter::<_, TransactionEnvelope>::new(r)
                    .map(|r| r.map(|t| Self::TransactionEnvelope(Box::new(t)))),
            ),
            TypeVariant::TransactionSignaturePayload => Box::new(
                ReadXdrIter::<_, TransactionSignaturePayload>::new(r)
                    .map(|r| r.map(|t| Self::TransactionSignaturePayload(Box::new(t)))),
            ),
            TypeVariant::TransactionSignaturePayloadTaggedTransaction => Box::new(
                ReadXdrIter::<_, TransactionSignaturePayloadTaggedTransaction>::new(r).map(|r| {
                    r.map(|t| Self::TransactionSignaturePayloadTaggedTransaction(Box::new(t)))
                }),
            ),
            TypeVariant::ClaimAtomType => Box::new(
                ReadXdrIter::<_, ClaimAtomType>::new(r)
                    .map(|r| r.map(|t| Self::ClaimAtomType(Box::new(t)))),
            ),
            TypeVariant::ClaimOfferAtomV0 => Box::new(
                ReadXdrIter::<_, ClaimOfferAtomV0>::new(r)
                    .map(|r| r.map(|t| Self::ClaimOfferAtomV0(Box::new(t)))),
            ),
            TypeVariant::ClaimOfferAtom => Box::new(
                ReadXdrIter::<_, ClaimOfferAtom>::new(r)
                    .map(|r| r.map(|t| Self::ClaimOfferAtom(Box::new(t)))),
            ),
            TypeVariant::ClaimLiquidityAtom => Box::new(
                ReadXdrIter::<_, ClaimLiquidityAtom>::new(r)
                    .map(|r| r.map(|t| Self::ClaimLiquidityAtom(Box::new(t)))),
            ),
            TypeVariant::ClaimAtom => Box::new(
                ReadXdrIter::<_, ClaimAtom>::new(r)
                    .map(|r| r.map(|t| Self::ClaimAtom(Box::new(t)))),
            ),
            TypeVariant::CreateAccountResultCode => Box::new(
                ReadXdrIter::<_, CreateAccountResultCode>::new(r)
                    .map(|r| r.map(|t| Self::CreateAccountResultCode(Box::new(t)))),
            ),
            TypeVariant::CreateAccountResult => Box::new(
                ReadXdrIter::<_, CreateAccountResult>::new(r)
                    .map(|r| r.map(|t| Self::CreateAccountResult(Box::new(t)))),
            ),
            TypeVariant::PaymentResultCode => Box::new(
                ReadXdrIter::<_, PaymentResultCode>::new(r)
                    .map(|r| r.map(|t| Self::PaymentResultCode(Box::new(t)))),
            ),
            TypeVariant::PaymentResult => Box::new(
                ReadXdrIter::<_, PaymentResult>::new(r)
                    .map(|r| r.map(|t| Self::PaymentResult(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictReceiveResultCode => Box::new(
                ReadXdrIter::<_, PathPaymentStrictReceiveResultCode>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveResultCode(Box::new(t)))),
            ),
            TypeVariant::SimplePaymentResult => Box::new(
                ReadXdrIter::<_, SimplePaymentResult>::new(r)
                    .map(|r| r.map(|t| Self::SimplePaymentResult(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictReceiveResult => Box::new(
                ReadXdrIter::<_, PathPaymentStrictReceiveResult>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveResult(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictReceiveResultSuccess => Box::new(
                ReadXdrIter::<_, PathPaymentStrictReceiveResultSuccess>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveResultSuccess(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictSendResultCode => Box::new(
                ReadXdrIter::<_, PathPaymentStrictSendResultCode>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendResultCode(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictSendResult => Box::new(
                ReadXdrIter::<_, PathPaymentStrictSendResult>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendResult(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictSendResultSuccess => Box::new(
                ReadXdrIter::<_, PathPaymentStrictSendResultSuccess>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendResultSuccess(Box::new(t)))),
            ),
            TypeVariant::ManageSellOfferResultCode => Box::new(
                ReadXdrIter::<_, ManageSellOfferResultCode>::new(r)
                    .map(|r| r.map(|t| Self::ManageSellOfferResultCode(Box::new(t)))),
            ),
            TypeVariant::ManageOfferEffect => Box::new(
                ReadXdrIter::<_, ManageOfferEffect>::new(r)
                    .map(|r| r.map(|t| Self::ManageOfferEffect(Box::new(t)))),
            ),
            TypeVariant::ManageOfferSuccessResult => Box::new(
                ReadXdrIter::<_, ManageOfferSuccessResult>::new(r)
                    .map(|r| r.map(|t| Self::ManageOfferSuccessResult(Box::new(t)))),
            ),
            TypeVariant::ManageOfferSuccessResultOffer => Box::new(
                ReadXdrIter::<_, ManageOfferSuccessResultOffer>::new(r)
                    .map(|r| r.map(|t| Self::ManageOfferSuccessResultOffer(Box::new(t)))),
            ),
            TypeVariant::ManageSellOfferResult => Box::new(
                ReadXdrIter::<_, ManageSellOfferResult>::new(r)
                    .map(|r| r.map(|t| Self::ManageSellOfferResult(Box::new(t)))),
            ),
            TypeVariant::ManageBuyOfferResultCode => Box::new(
                ReadXdrIter::<_, ManageBuyOfferResultCode>::new(r)
                    .map(|r| r.map(|t| Self::ManageBuyOfferResultCode(Box::new(t)))),
            ),
            TypeVariant::ManageBuyOfferResult => Box::new(
                ReadXdrIter::<_, ManageBuyOfferResult>::new(r)
                    .map(|r| r.map(|t| Self::ManageBuyOfferResult(Box::new(t)))),
            ),
            TypeVariant::SetOptionsResultCode => Box::new(
                ReadXdrIter::<_, SetOptionsResultCode>::new(r)
                    .map(|r| r.map(|t| Self::SetOptionsResultCode(Box::new(t)))),
            ),
            TypeVariant::SetOptionsResult => Box::new(
                ReadXdrIter::<_, SetOptionsResult>::new(r)
                    .map(|r| r.map(|t| Self::SetOptionsResult(Box::new(t)))),
            ),
            TypeVariant::ChangeTrustResultCode => Box::new(
                ReadXdrIter::<_, ChangeTrustResultCode>::new(r)
                    .map(|r| r.map(|t| Self::ChangeTrustResultCode(Box::new(t)))),
            ),
            TypeVariant::ChangeTrustResult => Box::new(
                ReadXdrIter::<_, ChangeTrustResult>::new(r)
                    .map(|r| r.map(|t| Self::ChangeTrustResult(Box::new(t)))),
            ),
            TypeVariant::AllowTrustResultCode => Box::new(
                ReadXdrIter::<_, AllowTrustResultCode>::new(r)
                    .map(|r| r.map(|t| Self::AllowTrustResultCode(Box::new(t)))),
            ),
            TypeVariant::AllowTrustResult => Box::new(
                ReadXdrIter::<_, AllowTrustResult>::new(r)
                    .map(|r| r.map(|t| Self::AllowTrustResult(Box::new(t)))),
            ),
            TypeVariant::AccountMergeResultCode => Box::new(
                ReadXdrIter::<_, AccountMergeResultCode>::new(r)
                    .map(|r| r.map(|t| Self::AccountMergeResultCode(Box::new(t)))),
            ),
            TypeVariant::AccountMergeResult => Box::new(
                ReadXdrIter::<_, AccountMergeResult>::new(r)
                    .map(|r| r.map(|t| Self::AccountMergeResult(Box::new(t)))),
            ),
            TypeVariant::InflationResultCode => Box::new(
                ReadXdrIter::<_, InflationResultCode>::new(r)
                    .map(|r| r.map(|t| Self::InflationResultCode(Box::new(t)))),
            ),
            TypeVariant::InflationPayout => Box::new(
                ReadXdrIter::<_, InflationPayout>::new(r)
                    .map(|r| r.map(|t| Self::InflationPayout(Box::new(t)))),
            ),
            TypeVariant::InflationResult => Box::new(
                ReadXdrIter::<_, InflationResult>::new(r)
                    .map(|r| r.map(|t| Self::InflationResult(Box::new(t)))),
            ),
            TypeVariant::ManageDataResultCode => Box::new(
                ReadXdrIter::<_, ManageDataResultCode>::new(r)
                    .map(|r| r.map(|t| Self::ManageDataResultCode(Box::new(t)))),
            ),
            TypeVariant::ManageDataResult => Box::new(
                ReadXdrIter::<_, ManageDataResult>::new(r)
                    .map(|r| r.map(|t| Self::ManageDataResult(Box::new(t)))),
            ),
            TypeVariant::BumpSequenceResultCode => Box::new(
                ReadXdrIter::<_, BumpSequenceResultCode>::new(r)
                    .map(|r| r.map(|t| Self::BumpSequenceResultCode(Box::new(t)))),
            ),
            TypeVariant::BumpSequenceResult => Box::new(
                ReadXdrIter::<_, BumpSequenceResult>::new(r)
                    .map(|r| r.map(|t| Self::BumpSequenceResult(Box::new(t)))),
            ),
            TypeVariant::CreateClaimableBalanceResultCode => Box::new(
                ReadXdrIter::<_, CreateClaimableBalanceResultCode>::new(r)
                    .map(|r| r.map(|t| Self::CreateClaimableBalanceResultCode(Box::new(t)))),
            ),
            TypeVariant::CreateClaimableBalanceResult => Box::new(
                ReadXdrIter::<_, CreateClaimableBalanceResult>::new(r)
                    .map(|r| r.map(|t| Self::CreateClaimableBalanceResult(Box::new(t)))),
            ),
            TypeVariant::ClaimClaimableBalanceResultCode => Box::new(
                ReadXdrIter::<_, ClaimClaimableBalanceResultCode>::new(r)
                    .map(|r| r.map(|t| Self::ClaimClaimableBalanceResultCode(Box::new(t)))),
            ),
            TypeVariant::ClaimClaimableBalanceResult => Box::new(
                ReadXdrIter::<_, ClaimClaimableBalanceResult>::new(r)
                    .map(|r| r.map(|t| Self::ClaimClaimableBalanceResult(Box::new(t)))),
            ),
            TypeVariant::BeginSponsoringFutureReservesResultCode => Box::new(
                ReadXdrIter::<_, BeginSponsoringFutureReservesResultCode>::new(r)
                    .map(|r| r.map(|t| Self::BeginSponsoringFutureReservesResultCode(Box::new(t)))),
            ),
            TypeVariant::BeginSponsoringFutureReservesResult => Box::new(
                ReadXdrIter::<_, BeginSponsoringFutureReservesResult>::new(r)
                    .map(|r| r.map(|t| Self::BeginSponsoringFutureReservesResult(Box::new(t)))),
            ),
            TypeVariant::EndSponsoringFutureReservesResultCode => Box::new(
                ReadXdrIter::<_, EndSponsoringFutureReservesResultCode>::new(r)
                    .map(|r| r.map(|t| Self::EndSponsoringFutureReservesResultCode(Box::new(t)))),
            ),
            TypeVariant::EndSponsoringFutureReservesResult => Box::new(
                ReadXdrIter::<_, EndSponsoringFutureReservesResult>::new(r)
                    .map(|r| r.map(|t| Self::EndSponsoringFutureReservesResult(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipResultCode => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipResultCode>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipResultCode(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipResult => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipResult>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipResult(Box::new(t)))),
            ),
            TypeVariant::ClawbackResultCode => Box::new(
                ReadXdrIter::<_, ClawbackResultCode>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackResultCode(Box::new(t)))),
            ),
            TypeVariant::ClawbackResult => Box::new(
                ReadXdrIter::<_, ClawbackResult>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackResult(Box::new(t)))),
            ),
            TypeVariant::ClawbackClaimableBalanceResultCode => Box::new(
                ReadXdrIter::<_, ClawbackClaimableBalanceResultCode>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackClaimableBalanceResultCode(Box::new(t)))),
            ),
            TypeVariant::ClawbackClaimableBalanceResult => Box::new(
                ReadXdrIter::<_, ClawbackClaimableBalanceResult>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackClaimableBalanceResult(Box::new(t)))),
            ),
            TypeVariant::SetTrustLineFlagsResultCode => Box::new(
                ReadXdrIter::<_, SetTrustLineFlagsResultCode>::new(r)
                    .map(|r| r.map(|t| Self::SetTrustLineFlagsResultCode(Box::new(t)))),
            ),
            TypeVariant::SetTrustLineFlagsResult => Box::new(
                ReadXdrIter::<_, SetTrustLineFlagsResult>::new(r)
                    .map(|r| r.map(|t| Self::SetTrustLineFlagsResult(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolDepositResultCode => Box::new(
                ReadXdrIter::<_, LiquidityPoolDepositResultCode>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolDepositResultCode(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolDepositResult => Box::new(
                ReadXdrIter::<_, LiquidityPoolDepositResult>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolDepositResult(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolWithdrawResultCode => Box::new(
                ReadXdrIter::<_, LiquidityPoolWithdrawResultCode>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolWithdrawResultCode(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolWithdrawResult => Box::new(
                ReadXdrIter::<_, LiquidityPoolWithdrawResult>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolWithdrawResult(Box::new(t)))),
            ),
            TypeVariant::InvokeHostFunctionResultCode => Box::new(
                ReadXdrIter::<_, InvokeHostFunctionResultCode>::new(r)
                    .map(|r| r.map(|t| Self::InvokeHostFunctionResultCode(Box::new(t)))),
            ),
            TypeVariant::InvokeHostFunctionResult => Box::new(
                ReadXdrIter::<_, InvokeHostFunctionResult>::new(r)
                    .map(|r| r.map(|t| Self::InvokeHostFunctionResult(Box::new(t)))),
            ),
            TypeVariant::OperationResultCode => Box::new(
                ReadXdrIter::<_, OperationResultCode>::new(r)
                    .map(|r| r.map(|t| Self::OperationResultCode(Box::new(t)))),
            ),
            TypeVariant::OperationResult => Box::new(
                ReadXdrIter::<_, OperationResult>::new(r)
                    .map(|r| r.map(|t| Self::OperationResult(Box::new(t)))),
            ),
            TypeVariant::OperationResultTr => Box::new(
                ReadXdrIter::<_, OperationResultTr>::new(r)
                    .map(|r| r.map(|t| Self::OperationResultTr(Box::new(t)))),
            ),
            TypeVariant::TransactionResultCode => Box::new(
                ReadXdrIter::<_, TransactionResultCode>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultCode(Box::new(t)))),
            ),
            TypeVariant::InnerTransactionResult => Box::new(
                ReadXdrIter::<_, InnerTransactionResult>::new(r)
                    .map(|r| r.map(|t| Self::InnerTransactionResult(Box::new(t)))),
            ),
            TypeVariant::InnerTransactionResultResult => Box::new(
                ReadXdrIter::<_, InnerTransactionResultResult>::new(r)
                    .map(|r| r.map(|t| Self::InnerTransactionResultResult(Box::new(t)))),
            ),
            TypeVariant::InnerTransactionResultExt => Box::new(
                ReadXdrIter::<_, InnerTransactionResultExt>::new(r)
                    .map(|r| r.map(|t| Self::InnerTransactionResultExt(Box::new(t)))),
            ),
            TypeVariant::InnerTransactionResultPair => Box::new(
                ReadXdrIter::<_, InnerTransactionResultPair>::new(r)
                    .map(|r| r.map(|t| Self::InnerTransactionResultPair(Box::new(t)))),
            ),
            TypeVariant::TransactionResult => Box::new(
                ReadXdrIter::<_, TransactionResult>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResult(Box::new(t)))),
            ),
            TypeVariant::TransactionResultResult => Box::new(
                ReadXdrIter::<_, TransactionResultResult>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultResult(Box::new(t)))),
            ),
            TypeVariant::TransactionResultExt => Box::new(
                ReadXdrIter::<_, TransactionResultExt>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultExt(Box::new(t)))),
            ),
            TypeVariant::Hash => {
                Box::new(ReadXdrIter::<_, Hash>::new(r).map(|r| r.map(|t| Self::Hash(Box::new(t)))))
            }
            TypeVariant::Uint256 => Box::new(
                ReadXdrIter::<_, Uint256>::new(r).map(|r| r.map(|t| Self::Uint256(Box::new(t)))),
            ),
            TypeVariant::Uint32 => Box::new(
                ReadXdrIter::<_, Uint32>::new(r).map(|r| r.map(|t| Self::Uint32(Box::new(t)))),
            ),
            TypeVariant::Int32 => Box::new(
                ReadXdrIter::<_, Int32>::new(r).map(|r| r.map(|t| Self::Int32(Box::new(t)))),
            ),
            TypeVariant::Uint64 => Box::new(
                ReadXdrIter::<_, Uint64>::new(r).map(|r| r.map(|t| Self::Uint64(Box::new(t)))),
            ),
            TypeVariant::Int64 => Box::new(
                ReadXdrIter::<_, Int64>::new(r).map(|r| r.map(|t| Self::Int64(Box::new(t)))),
            ),
            TypeVariant::ExtensionPoint => Box::new(
                ReadXdrIter::<_, ExtensionPoint>::new(r)
                    .map(|r| r.map(|t| Self::ExtensionPoint(Box::new(t)))),
            ),
            TypeVariant::CryptoKeyType => Box::new(
                ReadXdrIter::<_, CryptoKeyType>::new(r)
                    .map(|r| r.map(|t| Self::CryptoKeyType(Box::new(t)))),
            ),
            TypeVariant::PublicKeyType => Box::new(
                ReadXdrIter::<_, PublicKeyType>::new(r)
                    .map(|r| r.map(|t| Self::PublicKeyType(Box::new(t)))),
            ),
            TypeVariant::SignerKeyType => Box::new(
                ReadXdrIter::<_, SignerKeyType>::new(r)
                    .map(|r| r.map(|t| Self::SignerKeyType(Box::new(t)))),
            ),
            TypeVariant::PublicKey => Box::new(
                ReadXdrIter::<_, PublicKey>::new(r)
                    .map(|r| r.map(|t| Self::PublicKey(Box::new(t)))),
            ),
            TypeVariant::SignerKey => Box::new(
                ReadXdrIter::<_, SignerKey>::new(r)
                    .map(|r| r.map(|t| Self::SignerKey(Box::new(t)))),
            ),
            TypeVariant::SignerKeyEd25519SignedPayload => Box::new(
                ReadXdrIter::<_, SignerKeyEd25519SignedPayload>::new(r)
                    .map(|r| r.map(|t| Self::SignerKeyEd25519SignedPayload(Box::new(t)))),
            ),
            TypeVariant::Signature => Box::new(
                ReadXdrIter::<_, Signature>::new(r)
                    .map(|r| r.map(|t| Self::Signature(Box::new(t)))),
            ),
            TypeVariant::SignatureHint => Box::new(
                ReadXdrIter::<_, SignatureHint>::new(r)
                    .map(|r| r.map(|t| Self::SignatureHint(Box::new(t)))),
            ),
            TypeVariant::NodeId => Box::new(
                ReadXdrIter::<_, NodeId>::new(r).map(|r| r.map(|t| Self::NodeId(Box::new(t)))),
            ),
            TypeVariant::AccountId => Box::new(
                ReadXdrIter::<_, AccountId>::new(r)
                    .map(|r| r.map(|t| Self::AccountId(Box::new(t)))),
            ),
            TypeVariant::Curve25519Secret => Box::new(
                ReadXdrIter::<_, Curve25519Secret>::new(r)
                    .map(|r| r.map(|t| Self::Curve25519Secret(Box::new(t)))),
            ),
            TypeVariant::Curve25519Public => Box::new(
                ReadXdrIter::<_, Curve25519Public>::new(r)
                    .map(|r| r.map(|t| Self::Curve25519Public(Box::new(t)))),
            ),
            TypeVariant::HmacSha256Key => Box::new(
                ReadXdrIter::<_, HmacSha256Key>::new(r)
                    .map(|r| r.map(|t| Self::HmacSha256Key(Box::new(t)))),
            ),
            TypeVariant::HmacSha256Mac => Box::new(
                ReadXdrIter::<_, HmacSha256Mac>::new(r)
                    .map(|r| r.map(|t| Self::HmacSha256Mac(Box::new(t)))),
            ),
        }
    }

    #[cfg(feature = "std")]
    #[allow(clippy::too_many_lines)]
    pub fn read_xdr_framed_iter<R: Read>(
        v: TypeVariant,
        r: &mut R,
    ) -> Box<dyn Iterator<Item = Result<Self>> + '_> {
        match v {
            TypeVariant::Value => Box::new(
                ReadXdrIter::<_, Frame<Value>>::new(r)
                    .map(|r| r.map(|t| Self::Value(Box::new(t.0)))),
            ),
            TypeVariant::ScpBallot => Box::new(
                ReadXdrIter::<_, Frame<ScpBallot>>::new(r)
                    .map(|r| r.map(|t| Self::ScpBallot(Box::new(t.0)))),
            ),
            TypeVariant::ScpStatementType => Box::new(
                ReadXdrIter::<_, Frame<ScpStatementType>>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementType(Box::new(t.0)))),
            ),
            TypeVariant::ScpNomination => Box::new(
                ReadXdrIter::<_, Frame<ScpNomination>>::new(r)
                    .map(|r| r.map(|t| Self::ScpNomination(Box::new(t.0)))),
            ),
            TypeVariant::ScpStatement => Box::new(
                ReadXdrIter::<_, Frame<ScpStatement>>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatement(Box::new(t.0)))),
            ),
            TypeVariant::ScpStatementPledges => Box::new(
                ReadXdrIter::<_, Frame<ScpStatementPledges>>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementPledges(Box::new(t.0)))),
            ),
            TypeVariant::ScpStatementPrepare => Box::new(
                ReadXdrIter::<_, Frame<ScpStatementPrepare>>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementPrepare(Box::new(t.0)))),
            ),
            TypeVariant::ScpStatementConfirm => Box::new(
                ReadXdrIter::<_, Frame<ScpStatementConfirm>>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementConfirm(Box::new(t.0)))),
            ),
            TypeVariant::ScpStatementExternalize => Box::new(
                ReadXdrIter::<_, Frame<ScpStatementExternalize>>::new(r)
                    .map(|r| r.map(|t| Self::ScpStatementExternalize(Box::new(t.0)))),
            ),
            TypeVariant::ScpEnvelope => Box::new(
                ReadXdrIter::<_, Frame<ScpEnvelope>>::new(r)
                    .map(|r| r.map(|t| Self::ScpEnvelope(Box::new(t.0)))),
            ),
            TypeVariant::ScpQuorumSet => Box::new(
                ReadXdrIter::<_, Frame<ScpQuorumSet>>::new(r)
                    .map(|r| r.map(|t| Self::ScpQuorumSet(Box::new(t.0)))),
            ),
            TypeVariant::ScEnvMetaKind => Box::new(
                ReadXdrIter::<_, Frame<ScEnvMetaKind>>::new(r)
                    .map(|r| r.map(|t| Self::ScEnvMetaKind(Box::new(t.0)))),
            ),
            TypeVariant::ScEnvMetaEntry => Box::new(
                ReadXdrIter::<_, Frame<ScEnvMetaEntry>>::new(r)
                    .map(|r| r.map(|t| Self::ScEnvMetaEntry(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecType => Box::new(
                ReadXdrIter::<_, Frame<ScSpecType>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecType(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecTypeOption => Box::new(
                ReadXdrIter::<_, Frame<ScSpecTypeOption>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeOption(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecTypeResult => Box::new(
                ReadXdrIter::<_, Frame<ScSpecTypeResult>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeResult(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecTypeVec => Box::new(
                ReadXdrIter::<_, Frame<ScSpecTypeVec>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeVec(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecTypeMap => Box::new(
                ReadXdrIter::<_, Frame<ScSpecTypeMap>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeMap(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecTypeSet => Box::new(
                ReadXdrIter::<_, Frame<ScSpecTypeSet>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeSet(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecTypeTuple => Box::new(
                ReadXdrIter::<_, Frame<ScSpecTypeTuple>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeTuple(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecTypeBytesN => Box::new(
                ReadXdrIter::<_, Frame<ScSpecTypeBytesN>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeBytesN(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecTypeUdt => Box::new(
                ReadXdrIter::<_, Frame<ScSpecTypeUdt>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeUdt(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecTypeDef => Box::new(
                ReadXdrIter::<_, Frame<ScSpecTypeDef>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecTypeDef(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecUdtStructFieldV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecUdtStructFieldV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtStructFieldV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecUdtStructV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecUdtStructV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtStructV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecUdtUnionCaseV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecUdtUnionCaseV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtUnionCaseV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecUdtUnionV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecUdtUnionV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtUnionV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecUdtEnumCaseV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecUdtEnumCaseV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtEnumCaseV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecUdtEnumV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecUdtEnumV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtEnumV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecUdtErrorEnumCaseV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecUdtErrorEnumCaseV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtErrorEnumCaseV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecUdtErrorEnumV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecUdtErrorEnumV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecUdtErrorEnumV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecFunctionInputV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecFunctionInputV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecFunctionInputV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecFunctionV0 => Box::new(
                ReadXdrIter::<_, Frame<ScSpecFunctionV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecFunctionV0(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecEntryKind => Box::new(
                ReadXdrIter::<_, Frame<ScSpecEntryKind>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecEntryKind(Box::new(t.0)))),
            ),
            TypeVariant::ScSpecEntry => Box::new(
                ReadXdrIter::<_, Frame<ScSpecEntry>>::new(r)
                    .map(|r| r.map(|t| Self::ScSpecEntry(Box::new(t.0)))),
            ),
            TypeVariant::ScSymbol => Box::new(
                ReadXdrIter::<_, Frame<ScSymbol>>::new(r)
                    .map(|r| r.map(|t| Self::ScSymbol(Box::new(t.0)))),
            ),
            TypeVariant::ScValType => Box::new(
                ReadXdrIter::<_, Frame<ScValType>>::new(r)
                    .map(|r| r.map(|t| Self::ScValType(Box::new(t.0)))),
            ),
            TypeVariant::ScStatic => Box::new(
                ReadXdrIter::<_, Frame<ScStatic>>::new(r)
                    .map(|r| r.map(|t| Self::ScStatic(Box::new(t.0)))),
            ),
            TypeVariant::ScStatusType => Box::new(
                ReadXdrIter::<_, Frame<ScStatusType>>::new(r)
                    .map(|r| r.map(|t| Self::ScStatusType(Box::new(t.0)))),
            ),
            TypeVariant::ScHostValErrorCode => Box::new(
                ReadXdrIter::<_, Frame<ScHostValErrorCode>>::new(r)
                    .map(|r| r.map(|t| Self::ScHostValErrorCode(Box::new(t.0)))),
            ),
            TypeVariant::ScHostObjErrorCode => Box::new(
                ReadXdrIter::<_, Frame<ScHostObjErrorCode>>::new(r)
                    .map(|r| r.map(|t| Self::ScHostObjErrorCode(Box::new(t.0)))),
            ),
            TypeVariant::ScHostFnErrorCode => Box::new(
                ReadXdrIter::<_, Frame<ScHostFnErrorCode>>::new(r)
                    .map(|r| r.map(|t| Self::ScHostFnErrorCode(Box::new(t.0)))),
            ),
            TypeVariant::ScHostStorageErrorCode => Box::new(
                ReadXdrIter::<_, Frame<ScHostStorageErrorCode>>::new(r)
                    .map(|r| r.map(|t| Self::ScHostStorageErrorCode(Box::new(t.0)))),
            ),
            TypeVariant::ScHostContextErrorCode => Box::new(
                ReadXdrIter::<_, Frame<ScHostContextErrorCode>>::new(r)
                    .map(|r| r.map(|t| Self::ScHostContextErrorCode(Box::new(t.0)))),
            ),
            TypeVariant::ScVmErrorCode => Box::new(
                ReadXdrIter::<_, Frame<ScVmErrorCode>>::new(r)
                    .map(|r| r.map(|t| Self::ScVmErrorCode(Box::new(t.0)))),
            ),
            TypeVariant::ScUnknownErrorCode => Box::new(
                ReadXdrIter::<_, Frame<ScUnknownErrorCode>>::new(r)
                    .map(|r| r.map(|t| Self::ScUnknownErrorCode(Box::new(t.0)))),
            ),
            TypeVariant::ScStatus => Box::new(
                ReadXdrIter::<_, Frame<ScStatus>>::new(r)
                    .map(|r| r.map(|t| Self::ScStatus(Box::new(t.0)))),
            ),
            TypeVariant::ScVal => Box::new(
                ReadXdrIter::<_, Frame<ScVal>>::new(r)
                    .map(|r| r.map(|t| Self::ScVal(Box::new(t.0)))),
            ),
            TypeVariant::ScObjectType => Box::new(
                ReadXdrIter::<_, Frame<ScObjectType>>::new(r)
                    .map(|r| r.map(|t| Self::ScObjectType(Box::new(t.0)))),
            ),
            TypeVariant::ScMapEntry => Box::new(
                ReadXdrIter::<_, Frame<ScMapEntry>>::new(r)
                    .map(|r| r.map(|t| Self::ScMapEntry(Box::new(t.0)))),
            ),
            TypeVariant::ScVec => Box::new(
                ReadXdrIter::<_, Frame<ScVec>>::new(r)
                    .map(|r| r.map(|t| Self::ScVec(Box::new(t.0)))),
            ),
            TypeVariant::ScMap => Box::new(
                ReadXdrIter::<_, Frame<ScMap>>::new(r)
                    .map(|r| r.map(|t| Self::ScMap(Box::new(t.0)))),
            ),
            TypeVariant::ScContractCodeType => Box::new(
                ReadXdrIter::<_, Frame<ScContractCodeType>>::new(r)
                    .map(|r| r.map(|t| Self::ScContractCodeType(Box::new(t.0)))),
            ),
            TypeVariant::ScContractCode => Box::new(
                ReadXdrIter::<_, Frame<ScContractCode>>::new(r)
                    .map(|r| r.map(|t| Self::ScContractCode(Box::new(t.0)))),
            ),
            TypeVariant::Int128Parts => Box::new(
                ReadXdrIter::<_, Frame<Int128Parts>>::new(r)
                    .map(|r| r.map(|t| Self::Int128Parts(Box::new(t.0)))),
            ),
            TypeVariant::ScObject => Box::new(
                ReadXdrIter::<_, Frame<ScObject>>::new(r)
                    .map(|r| r.map(|t| Self::ScObject(Box::new(t.0)))),
            ),
            TypeVariant::StoredTransactionSet => Box::new(
                ReadXdrIter::<_, Frame<StoredTransactionSet>>::new(r)
                    .map(|r| r.map(|t| Self::StoredTransactionSet(Box::new(t.0)))),
            ),
            TypeVariant::PersistedScpStateV0 => Box::new(
                ReadXdrIter::<_, Frame<PersistedScpStateV0>>::new(r)
                    .map(|r| r.map(|t| Self::PersistedScpStateV0(Box::new(t.0)))),
            ),
            TypeVariant::PersistedScpStateV1 => Box::new(
                ReadXdrIter::<_, Frame<PersistedScpStateV1>>::new(r)
                    .map(|r| r.map(|t| Self::PersistedScpStateV1(Box::new(t.0)))),
            ),
            TypeVariant::PersistedScpState => Box::new(
                ReadXdrIter::<_, Frame<PersistedScpState>>::new(r)
                    .map(|r| r.map(|t| Self::PersistedScpState(Box::new(t.0)))),
            ),
            TypeVariant::Thresholds => Box::new(
                ReadXdrIter::<_, Frame<Thresholds>>::new(r)
                    .map(|r| r.map(|t| Self::Thresholds(Box::new(t.0)))),
            ),
            TypeVariant::String32 => Box::new(
                ReadXdrIter::<_, Frame<String32>>::new(r)
                    .map(|r| r.map(|t| Self::String32(Box::new(t.0)))),
            ),
            TypeVariant::String64 => Box::new(
                ReadXdrIter::<_, Frame<String64>>::new(r)
                    .map(|r| r.map(|t| Self::String64(Box::new(t.0)))),
            ),
            TypeVariant::SequenceNumber => Box::new(
                ReadXdrIter::<_, Frame<SequenceNumber>>::new(r)
                    .map(|r| r.map(|t| Self::SequenceNumber(Box::new(t.0)))),
            ),
            TypeVariant::TimePoint => Box::new(
                ReadXdrIter::<_, Frame<TimePoint>>::new(r)
                    .map(|r| r.map(|t| Self::TimePoint(Box::new(t.0)))),
            ),
            TypeVariant::Duration => Box::new(
                ReadXdrIter::<_, Frame<Duration>>::new(r)
                    .map(|r| r.map(|t| Self::Duration(Box::new(t.0)))),
            ),
            TypeVariant::DataValue => Box::new(
                ReadXdrIter::<_, Frame<DataValue>>::new(r)
                    .map(|r| r.map(|t| Self::DataValue(Box::new(t.0)))),
            ),
            TypeVariant::PoolId => Box::new(
                ReadXdrIter::<_, Frame<PoolId>>::new(r)
                    .map(|r| r.map(|t| Self::PoolId(Box::new(t.0)))),
            ),
            TypeVariant::AssetCode4 => Box::new(
                ReadXdrIter::<_, Frame<AssetCode4>>::new(r)
                    .map(|r| r.map(|t| Self::AssetCode4(Box::new(t.0)))),
            ),
            TypeVariant::AssetCode12 => Box::new(
                ReadXdrIter::<_, Frame<AssetCode12>>::new(r)
                    .map(|r| r.map(|t| Self::AssetCode12(Box::new(t.0)))),
            ),
            TypeVariant::AssetType => Box::new(
                ReadXdrIter::<_, Frame<AssetType>>::new(r)
                    .map(|r| r.map(|t| Self::AssetType(Box::new(t.0)))),
            ),
            TypeVariant::AssetCode => Box::new(
                ReadXdrIter::<_, Frame<AssetCode>>::new(r)
                    .map(|r| r.map(|t| Self::AssetCode(Box::new(t.0)))),
            ),
            TypeVariant::AlphaNum4 => Box::new(
                ReadXdrIter::<_, Frame<AlphaNum4>>::new(r)
                    .map(|r| r.map(|t| Self::AlphaNum4(Box::new(t.0)))),
            ),
            TypeVariant::AlphaNum12 => Box::new(
                ReadXdrIter::<_, Frame<AlphaNum12>>::new(r)
                    .map(|r| r.map(|t| Self::AlphaNum12(Box::new(t.0)))),
            ),
            TypeVariant::Asset => Box::new(
                ReadXdrIter::<_, Frame<Asset>>::new(r)
                    .map(|r| r.map(|t| Self::Asset(Box::new(t.0)))),
            ),
            TypeVariant::Price => Box::new(
                ReadXdrIter::<_, Frame<Price>>::new(r)
                    .map(|r| r.map(|t| Self::Price(Box::new(t.0)))),
            ),
            TypeVariant::Liabilities => Box::new(
                ReadXdrIter::<_, Frame<Liabilities>>::new(r)
                    .map(|r| r.map(|t| Self::Liabilities(Box::new(t.0)))),
            ),
            TypeVariant::ThresholdIndexes => Box::new(
                ReadXdrIter::<_, Frame<ThresholdIndexes>>::new(r)
                    .map(|r| r.map(|t| Self::ThresholdIndexes(Box::new(t.0)))),
            ),
            TypeVariant::LedgerEntryType => Box::new(
                ReadXdrIter::<_, Frame<LedgerEntryType>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryType(Box::new(t.0)))),
            ),
            TypeVariant::Signer => Box::new(
                ReadXdrIter::<_, Frame<Signer>>::new(r)
                    .map(|r| r.map(|t| Self::Signer(Box::new(t.0)))),
            ),
            TypeVariant::AccountFlags => Box::new(
                ReadXdrIter::<_, Frame<AccountFlags>>::new(r)
                    .map(|r| r.map(|t| Self::AccountFlags(Box::new(t.0)))),
            ),
            TypeVariant::SponsorshipDescriptor => Box::new(
                ReadXdrIter::<_, Frame<SponsorshipDescriptor>>::new(r)
                    .map(|r| r.map(|t| Self::SponsorshipDescriptor(Box::new(t.0)))),
            ),
            TypeVariant::AccountEntryExtensionV3 => Box::new(
                ReadXdrIter::<_, Frame<AccountEntryExtensionV3>>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV3(Box::new(t.0)))),
            ),
            TypeVariant::AccountEntryExtensionV2 => Box::new(
                ReadXdrIter::<_, Frame<AccountEntryExtensionV2>>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV2(Box::new(t.0)))),
            ),
            TypeVariant::AccountEntryExtensionV2Ext => Box::new(
                ReadXdrIter::<_, Frame<AccountEntryExtensionV2Ext>>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV2Ext(Box::new(t.0)))),
            ),
            TypeVariant::AccountEntryExtensionV1 => Box::new(
                ReadXdrIter::<_, Frame<AccountEntryExtensionV1>>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV1(Box::new(t.0)))),
            ),
            TypeVariant::AccountEntryExtensionV1Ext => Box::new(
                ReadXdrIter::<_, Frame<AccountEntryExtensionV1Ext>>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV1Ext(Box::new(t.0)))),
            ),
            TypeVariant::AccountEntry => Box::new(
                ReadXdrIter::<_, Frame<AccountEntry>>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntry(Box::new(t.0)))),
            ),
            TypeVariant::AccountEntryExt => Box::new(
                ReadXdrIter::<_, Frame<AccountEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::AccountEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::TrustLineFlags => Box::new(
                ReadXdrIter::<_, Frame<TrustLineFlags>>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineFlags(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolType => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolType>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolType(Box::new(t.0)))),
            ),
            TypeVariant::TrustLineAsset => Box::new(
                ReadXdrIter::<_, Frame<TrustLineAsset>>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineAsset(Box::new(t.0)))),
            ),
            TypeVariant::TrustLineEntryExtensionV2 => Box::new(
                ReadXdrIter::<_, Frame<TrustLineEntryExtensionV2>>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryExtensionV2(Box::new(t.0)))),
            ),
            TypeVariant::TrustLineEntryExtensionV2Ext => Box::new(
                ReadXdrIter::<_, Frame<TrustLineEntryExtensionV2Ext>>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryExtensionV2Ext(Box::new(t.0)))),
            ),
            TypeVariant::TrustLineEntry => Box::new(
                ReadXdrIter::<_, Frame<TrustLineEntry>>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntry(Box::new(t.0)))),
            ),
            TypeVariant::TrustLineEntryExt => Box::new(
                ReadXdrIter::<_, Frame<TrustLineEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::TrustLineEntryV1 => Box::new(
                ReadXdrIter::<_, Frame<TrustLineEntryV1>>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryV1(Box::new(t.0)))),
            ),
            TypeVariant::TrustLineEntryV1Ext => Box::new(
                ReadXdrIter::<_, Frame<TrustLineEntryV1Ext>>::new(r)
                    .map(|r| r.map(|t| Self::TrustLineEntryV1Ext(Box::new(t.0)))),
            ),
            TypeVariant::OfferEntryFlags => Box::new(
                ReadXdrIter::<_, Frame<OfferEntryFlags>>::new(r)
                    .map(|r| r.map(|t| Self::OfferEntryFlags(Box::new(t.0)))),
            ),
            TypeVariant::OfferEntry => Box::new(
                ReadXdrIter::<_, Frame<OfferEntry>>::new(r)
                    .map(|r| r.map(|t| Self::OfferEntry(Box::new(t.0)))),
            ),
            TypeVariant::OfferEntryExt => Box::new(
                ReadXdrIter::<_, Frame<OfferEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::OfferEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::DataEntry => Box::new(
                ReadXdrIter::<_, Frame<DataEntry>>::new(r)
                    .map(|r| r.map(|t| Self::DataEntry(Box::new(t.0)))),
            ),
            TypeVariant::DataEntryExt => Box::new(
                ReadXdrIter::<_, Frame<DataEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::DataEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::ClaimPredicateType => Box::new(
                ReadXdrIter::<_, Frame<ClaimPredicateType>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimPredicateType(Box::new(t.0)))),
            ),
            TypeVariant::ClaimPredicate => Box::new(
                ReadXdrIter::<_, Frame<ClaimPredicate>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimPredicate(Box::new(t.0)))),
            ),
            TypeVariant::ClaimantType => Box::new(
                ReadXdrIter::<_, Frame<ClaimantType>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimantType(Box::new(t.0)))),
            ),
            TypeVariant::Claimant => Box::new(
                ReadXdrIter::<_, Frame<Claimant>>::new(r)
                    .map(|r| r.map(|t| Self::Claimant(Box::new(t.0)))),
            ),
            TypeVariant::ClaimantV0 => Box::new(
                ReadXdrIter::<_, Frame<ClaimantV0>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimantV0(Box::new(t.0)))),
            ),
            TypeVariant::ClaimableBalanceIdType => Box::new(
                ReadXdrIter::<_, Frame<ClaimableBalanceIdType>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceIdType(Box::new(t.0)))),
            ),
            TypeVariant::ClaimableBalanceId => Box::new(
                ReadXdrIter::<_, Frame<ClaimableBalanceId>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceId(Box::new(t.0)))),
            ),
            TypeVariant::ClaimableBalanceFlags => Box::new(
                ReadXdrIter::<_, Frame<ClaimableBalanceFlags>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceFlags(Box::new(t.0)))),
            ),
            TypeVariant::ClaimableBalanceEntryExtensionV1 => Box::new(
                ReadXdrIter::<_, Frame<ClaimableBalanceEntryExtensionV1>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntryExtensionV1(Box::new(t.0)))),
            ),
            TypeVariant::ClaimableBalanceEntryExtensionV1Ext => Box::new(
                ReadXdrIter::<_, Frame<ClaimableBalanceEntryExtensionV1Ext>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntryExtensionV1Ext(Box::new(t.0)))),
            ),
            TypeVariant::ClaimableBalanceEntry => Box::new(
                ReadXdrIter::<_, Frame<ClaimableBalanceEntry>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntry(Box::new(t.0)))),
            ),
            TypeVariant::ClaimableBalanceEntryExt => Box::new(
                ReadXdrIter::<_, Frame<ClaimableBalanceEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolConstantProductParameters => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolConstantProductParameters>>::new(r).map(|r| {
                    r.map(|t| Self::LiquidityPoolConstantProductParameters(Box::new(t.0)))
                }),
            ),
            TypeVariant::LiquidityPoolEntry => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolEntry>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolEntry(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolEntryBody => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolEntryBody>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolEntryBody(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolEntryConstantProduct => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolEntryConstantProduct>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolEntryConstantProduct(Box::new(t.0)))),
            ),
            TypeVariant::ContractDataEntry => Box::new(
                ReadXdrIter::<_, Frame<ContractDataEntry>>::new(r)
                    .map(|r| r.map(|t| Self::ContractDataEntry(Box::new(t.0)))),
            ),
            TypeVariant::ContractCodeEntry => Box::new(
                ReadXdrIter::<_, Frame<ContractCodeEntry>>::new(r)
                    .map(|r| r.map(|t| Self::ContractCodeEntry(Box::new(t.0)))),
            ),
            TypeVariant::ConfigSettingType => Box::new(
                ReadXdrIter::<_, Frame<ConfigSettingType>>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSettingType(Box::new(t.0)))),
            ),
            TypeVariant::ConfigSetting => Box::new(
                ReadXdrIter::<_, Frame<ConfigSetting>>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSetting(Box::new(t.0)))),
            ),
            TypeVariant::ConfigSettingId => Box::new(
                ReadXdrIter::<_, Frame<ConfigSettingId>>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSettingId(Box::new(t.0)))),
            ),
            TypeVariant::ConfigSettingEntry => Box::new(
                ReadXdrIter::<_, Frame<ConfigSettingEntry>>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSettingEntry(Box::new(t.0)))),
            ),
            TypeVariant::ConfigSettingEntryExt => Box::new(
                ReadXdrIter::<_, Frame<ConfigSettingEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::ConfigSettingEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::LedgerEntryExtensionV1 => Box::new(
                ReadXdrIter::<_, Frame<LedgerEntryExtensionV1>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryExtensionV1(Box::new(t.0)))),
            ),
            TypeVariant::LedgerEntryExtensionV1Ext => Box::new(
                ReadXdrIter::<_, Frame<LedgerEntryExtensionV1Ext>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryExtensionV1Ext(Box::new(t.0)))),
            ),
            TypeVariant::LedgerEntry => Box::new(
                ReadXdrIter::<_, Frame<LedgerEntry>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntry(Box::new(t.0)))),
            ),
            TypeVariant::LedgerEntryData => Box::new(
                ReadXdrIter::<_, Frame<LedgerEntryData>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryData(Box::new(t.0)))),
            ),
            TypeVariant::LedgerEntryExt => Box::new(
                ReadXdrIter::<_, Frame<LedgerEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKey => Box::new(
                ReadXdrIter::<_, Frame<LedgerKey>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKey(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKeyAccount => Box::new(
                ReadXdrIter::<_, Frame<LedgerKeyAccount>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyAccount(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKeyTrustLine => Box::new(
                ReadXdrIter::<_, Frame<LedgerKeyTrustLine>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyTrustLine(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKeyOffer => Box::new(
                ReadXdrIter::<_, Frame<LedgerKeyOffer>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyOffer(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKeyData => Box::new(
                ReadXdrIter::<_, Frame<LedgerKeyData>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyData(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKeyClaimableBalance => Box::new(
                ReadXdrIter::<_, Frame<LedgerKeyClaimableBalance>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyClaimableBalance(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKeyLiquidityPool => Box::new(
                ReadXdrIter::<_, Frame<LedgerKeyLiquidityPool>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyLiquidityPool(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKeyContractData => Box::new(
                ReadXdrIter::<_, Frame<LedgerKeyContractData>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyContractData(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKeyContractCode => Box::new(
                ReadXdrIter::<_, Frame<LedgerKeyContractCode>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyContractCode(Box::new(t.0)))),
            ),
            TypeVariant::LedgerKeyConfigSetting => Box::new(
                ReadXdrIter::<_, Frame<LedgerKeyConfigSetting>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerKeyConfigSetting(Box::new(t.0)))),
            ),
            TypeVariant::EnvelopeType => Box::new(
                ReadXdrIter::<_, Frame<EnvelopeType>>::new(r)
                    .map(|r| r.map(|t| Self::EnvelopeType(Box::new(t.0)))),
            ),
            TypeVariant::UpgradeType => Box::new(
                ReadXdrIter::<_, Frame<UpgradeType>>::new(r)
                    .map(|r| r.map(|t| Self::UpgradeType(Box::new(t.0)))),
            ),
            TypeVariant::StellarValueType => Box::new(
                ReadXdrIter::<_, Frame<StellarValueType>>::new(r)
                    .map(|r| r.map(|t| Self::StellarValueType(Box::new(t.0)))),
            ),
            TypeVariant::LedgerCloseValueSignature => Box::new(
                ReadXdrIter::<_, Frame<LedgerCloseValueSignature>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseValueSignature(Box::new(t.0)))),
            ),
            TypeVariant::StellarValue => Box::new(
                ReadXdrIter::<_, Frame<StellarValue>>::new(r)
                    .map(|r| r.map(|t| Self::StellarValue(Box::new(t.0)))),
            ),
            TypeVariant::StellarValueExt => Box::new(
                ReadXdrIter::<_, Frame<StellarValueExt>>::new(r)
                    .map(|r| r.map(|t| Self::StellarValueExt(Box::new(t.0)))),
            ),
            TypeVariant::LedgerHeaderFlags => Box::new(
                ReadXdrIter::<_, Frame<LedgerHeaderFlags>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderFlags(Box::new(t.0)))),
            ),
            TypeVariant::LedgerHeaderExtensionV1 => Box::new(
                ReadXdrIter::<_, Frame<LedgerHeaderExtensionV1>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderExtensionV1(Box::new(t.0)))),
            ),
            TypeVariant::LedgerHeaderExtensionV1Ext => Box::new(
                ReadXdrIter::<_, Frame<LedgerHeaderExtensionV1Ext>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderExtensionV1Ext(Box::new(t.0)))),
            ),
            TypeVariant::LedgerHeader => Box::new(
                ReadXdrIter::<_, Frame<LedgerHeader>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeader(Box::new(t.0)))),
            ),
            TypeVariant::LedgerHeaderExt => Box::new(
                ReadXdrIter::<_, Frame<LedgerHeaderExt>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderExt(Box::new(t.0)))),
            ),
            TypeVariant::LedgerUpgradeType => Box::new(
                ReadXdrIter::<_, Frame<LedgerUpgradeType>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerUpgradeType(Box::new(t.0)))),
            ),
            TypeVariant::LedgerUpgrade => Box::new(
                ReadXdrIter::<_, Frame<LedgerUpgrade>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerUpgrade(Box::new(t.0)))),
            ),
            TypeVariant::LedgerUpgradeConfigSetting => Box::new(
                ReadXdrIter::<_, Frame<LedgerUpgradeConfigSetting>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerUpgradeConfigSetting(Box::new(t.0)))),
            ),
            TypeVariant::BucketEntryType => Box::new(
                ReadXdrIter::<_, Frame<BucketEntryType>>::new(r)
                    .map(|r| r.map(|t| Self::BucketEntryType(Box::new(t.0)))),
            ),
            TypeVariant::BucketMetadata => Box::new(
                ReadXdrIter::<_, Frame<BucketMetadata>>::new(r)
                    .map(|r| r.map(|t| Self::BucketMetadata(Box::new(t.0)))),
            ),
            TypeVariant::BucketMetadataExt => Box::new(
                ReadXdrIter::<_, Frame<BucketMetadataExt>>::new(r)
                    .map(|r| r.map(|t| Self::BucketMetadataExt(Box::new(t.0)))),
            ),
            TypeVariant::BucketEntry => Box::new(
                ReadXdrIter::<_, Frame<BucketEntry>>::new(r)
                    .map(|r| r.map(|t| Self::BucketEntry(Box::new(t.0)))),
            ),
            TypeVariant::TxSetComponentType => Box::new(
                ReadXdrIter::<_, Frame<TxSetComponentType>>::new(r)
                    .map(|r| r.map(|t| Self::TxSetComponentType(Box::new(t.0)))),
            ),
            TypeVariant::TxSetComponent => Box::new(
                ReadXdrIter::<_, Frame<TxSetComponent>>::new(r)
                    .map(|r| r.map(|t| Self::TxSetComponent(Box::new(t.0)))),
            ),
            TypeVariant::TxSetComponentTxsMaybeDiscountedFee => Box::new(
                ReadXdrIter::<_, Frame<TxSetComponentTxsMaybeDiscountedFee>>::new(r)
                    .map(|r| r.map(|t| Self::TxSetComponentTxsMaybeDiscountedFee(Box::new(t.0)))),
            ),
            TypeVariant::TransactionPhase => Box::new(
                ReadXdrIter::<_, Frame<TransactionPhase>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionPhase(Box::new(t.0)))),
            ),
            TypeVariant::TransactionSet => Box::new(
                ReadXdrIter::<_, Frame<TransactionSet>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionSet(Box::new(t.0)))),
            ),
            TypeVariant::TransactionSetV1 => Box::new(
                ReadXdrIter::<_, Frame<TransactionSetV1>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionSetV1(Box::new(t.0)))),
            ),
            TypeVariant::GeneralizedTransactionSet => Box::new(
                ReadXdrIter::<_, Frame<GeneralizedTransactionSet>>::new(r)
                    .map(|r| r.map(|t| Self::GeneralizedTransactionSet(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResultPair => Box::new(
                ReadXdrIter::<_, Frame<TransactionResultPair>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultPair(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResultSet => Box::new(
                ReadXdrIter::<_, Frame<TransactionResultSet>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultSet(Box::new(t.0)))),
            ),
            TypeVariant::TransactionHistoryEntry => Box::new(
                ReadXdrIter::<_, Frame<TransactionHistoryEntry>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryEntry(Box::new(t.0)))),
            ),
            TypeVariant::TransactionHistoryEntryExt => Box::new(
                ReadXdrIter::<_, Frame<TransactionHistoryEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::TransactionHistoryResultEntry => Box::new(
                ReadXdrIter::<_, Frame<TransactionHistoryResultEntry>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntry(Box::new(t.0)))),
            ),
            TypeVariant::TransactionHistoryResultEntryExt => Box::new(
                ReadXdrIter::<_, Frame<TransactionHistoryResultEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResultPairV2 => Box::new(
                ReadXdrIter::<_, Frame<TransactionResultPairV2>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultPairV2(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResultSetV2 => Box::new(
                ReadXdrIter::<_, Frame<TransactionResultSetV2>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultSetV2(Box::new(t.0)))),
            ),
            TypeVariant::TransactionHistoryResultEntryV2 => Box::new(
                ReadXdrIter::<_, Frame<TransactionHistoryResultEntryV2>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntryV2(Box::new(t.0)))),
            ),
            TypeVariant::TransactionHistoryResultEntryV2Ext => Box::new(
                ReadXdrIter::<_, Frame<TransactionHistoryResultEntryV2Ext>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntryV2Ext(Box::new(t.0)))),
            ),
            TypeVariant::LedgerHeaderHistoryEntry => Box::new(
                ReadXdrIter::<_, Frame<LedgerHeaderHistoryEntry>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderHistoryEntry(Box::new(t.0)))),
            ),
            TypeVariant::LedgerHeaderHistoryEntryExt => Box::new(
                ReadXdrIter::<_, Frame<LedgerHeaderHistoryEntryExt>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerHeaderHistoryEntryExt(Box::new(t.0)))),
            ),
            TypeVariant::LedgerScpMessages => Box::new(
                ReadXdrIter::<_, Frame<LedgerScpMessages>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerScpMessages(Box::new(t.0)))),
            ),
            TypeVariant::ScpHistoryEntryV0 => Box::new(
                ReadXdrIter::<_, Frame<ScpHistoryEntryV0>>::new(r)
                    .map(|r| r.map(|t| Self::ScpHistoryEntryV0(Box::new(t.0)))),
            ),
            TypeVariant::ScpHistoryEntry => Box::new(
                ReadXdrIter::<_, Frame<ScpHistoryEntry>>::new(r)
                    .map(|r| r.map(|t| Self::ScpHistoryEntry(Box::new(t.0)))),
            ),
            TypeVariant::LedgerEntryChangeType => Box::new(
                ReadXdrIter::<_, Frame<LedgerEntryChangeType>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryChangeType(Box::new(t.0)))),
            ),
            TypeVariant::LedgerEntryChange => Box::new(
                ReadXdrIter::<_, Frame<LedgerEntryChange>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryChange(Box::new(t.0)))),
            ),
            TypeVariant::LedgerEntryChanges => Box::new(
                ReadXdrIter::<_, Frame<LedgerEntryChanges>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerEntryChanges(Box::new(t.0)))),
            ),
            TypeVariant::OperationMeta => Box::new(
                ReadXdrIter::<_, Frame<OperationMeta>>::new(r)
                    .map(|r| r.map(|t| Self::OperationMeta(Box::new(t.0)))),
            ),
            TypeVariant::TransactionMetaV1 => Box::new(
                ReadXdrIter::<_, Frame<TransactionMetaV1>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionMetaV1(Box::new(t.0)))),
            ),
            TypeVariant::TransactionMetaV2 => Box::new(
                ReadXdrIter::<_, Frame<TransactionMetaV2>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionMetaV2(Box::new(t.0)))),
            ),
            TypeVariant::ContractEventType => Box::new(
                ReadXdrIter::<_, Frame<ContractEventType>>::new(r)
                    .map(|r| r.map(|t| Self::ContractEventType(Box::new(t.0)))),
            ),
            TypeVariant::ContractEvent => Box::new(
                ReadXdrIter::<_, Frame<ContractEvent>>::new(r)
                    .map(|r| r.map(|t| Self::ContractEvent(Box::new(t.0)))),
            ),
            TypeVariant::ContractEventBody => Box::new(
                ReadXdrIter::<_, Frame<ContractEventBody>>::new(r)
                    .map(|r| r.map(|t| Self::ContractEventBody(Box::new(t.0)))),
            ),
            TypeVariant::ContractEventV0 => Box::new(
                ReadXdrIter::<_, Frame<ContractEventV0>>::new(r)
                    .map(|r| r.map(|t| Self::ContractEventV0(Box::new(t.0)))),
            ),
            TypeVariant::OperationEvents => Box::new(
                ReadXdrIter::<_, Frame<OperationEvents>>::new(r)
                    .map(|r| r.map(|t| Self::OperationEvents(Box::new(t.0)))),
            ),
            TypeVariant::TransactionMetaV3 => Box::new(
                ReadXdrIter::<_, Frame<TransactionMetaV3>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionMetaV3(Box::new(t.0)))),
            ),
            TypeVariant::TransactionMeta => Box::new(
                ReadXdrIter::<_, Frame<TransactionMeta>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionMeta(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResultMeta => Box::new(
                ReadXdrIter::<_, Frame<TransactionResultMeta>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultMeta(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResultMetaV2 => Box::new(
                ReadXdrIter::<_, Frame<TransactionResultMetaV2>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultMetaV2(Box::new(t.0)))),
            ),
            TypeVariant::UpgradeEntryMeta => Box::new(
                ReadXdrIter::<_, Frame<UpgradeEntryMeta>>::new(r)
                    .map(|r| r.map(|t| Self::UpgradeEntryMeta(Box::new(t.0)))),
            ),
            TypeVariant::LedgerCloseMetaV0 => Box::new(
                ReadXdrIter::<_, Frame<LedgerCloseMetaV0>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseMetaV0(Box::new(t.0)))),
            ),
            TypeVariant::LedgerCloseMetaV1 => Box::new(
                ReadXdrIter::<_, Frame<LedgerCloseMetaV1>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseMetaV1(Box::new(t.0)))),
            ),
            TypeVariant::LedgerCloseMetaV2 => Box::new(
                ReadXdrIter::<_, Frame<LedgerCloseMetaV2>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseMetaV2(Box::new(t.0)))),
            ),
            TypeVariant::LedgerCloseMeta => Box::new(
                ReadXdrIter::<_, Frame<LedgerCloseMeta>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerCloseMeta(Box::new(t.0)))),
            ),
            TypeVariant::ErrorCode => Box::new(
                ReadXdrIter::<_, Frame<ErrorCode>>::new(r)
                    .map(|r| r.map(|t| Self::ErrorCode(Box::new(t.0)))),
            ),
            TypeVariant::SError => Box::new(
                ReadXdrIter::<_, Frame<SError>>::new(r)
                    .map(|r| r.map(|t| Self::SError(Box::new(t.0)))),
            ),
            TypeVariant::SendMore => Box::new(
                ReadXdrIter::<_, Frame<SendMore>>::new(r)
                    .map(|r| r.map(|t| Self::SendMore(Box::new(t.0)))),
            ),
            TypeVariant::AuthCert => Box::new(
                ReadXdrIter::<_, Frame<AuthCert>>::new(r)
                    .map(|r| r.map(|t| Self::AuthCert(Box::new(t.0)))),
            ),
            TypeVariant::Hello => Box::new(
                ReadXdrIter::<_, Frame<Hello>>::new(r)
                    .map(|r| r.map(|t| Self::Hello(Box::new(t.0)))),
            ),
            TypeVariant::Auth => Box::new(
                ReadXdrIter::<_, Frame<Auth>>::new(r).map(|r| r.map(|t| Self::Auth(Box::new(t.0)))),
            ),
            TypeVariant::IpAddrType => Box::new(
                ReadXdrIter::<_, Frame<IpAddrType>>::new(r)
                    .map(|r| r.map(|t| Self::IpAddrType(Box::new(t.0)))),
            ),
            TypeVariant::PeerAddress => Box::new(
                ReadXdrIter::<_, Frame<PeerAddress>>::new(r)
                    .map(|r| r.map(|t| Self::PeerAddress(Box::new(t.0)))),
            ),
            TypeVariant::PeerAddressIp => Box::new(
                ReadXdrIter::<_, Frame<PeerAddressIp>>::new(r)
                    .map(|r| r.map(|t| Self::PeerAddressIp(Box::new(t.0)))),
            ),
            TypeVariant::MessageType => Box::new(
                ReadXdrIter::<_, Frame<MessageType>>::new(r)
                    .map(|r| r.map(|t| Self::MessageType(Box::new(t.0)))),
            ),
            TypeVariant::DontHave => Box::new(
                ReadXdrIter::<_, Frame<DontHave>>::new(r)
                    .map(|r| r.map(|t| Self::DontHave(Box::new(t.0)))),
            ),
            TypeVariant::SurveyMessageCommandType => Box::new(
                ReadXdrIter::<_, Frame<SurveyMessageCommandType>>::new(r)
                    .map(|r| r.map(|t| Self::SurveyMessageCommandType(Box::new(t.0)))),
            ),
            TypeVariant::SurveyRequestMessage => Box::new(
                ReadXdrIter::<_, Frame<SurveyRequestMessage>>::new(r)
                    .map(|r| r.map(|t| Self::SurveyRequestMessage(Box::new(t.0)))),
            ),
            TypeVariant::SignedSurveyRequestMessage => Box::new(
                ReadXdrIter::<_, Frame<SignedSurveyRequestMessage>>::new(r)
                    .map(|r| r.map(|t| Self::SignedSurveyRequestMessage(Box::new(t.0)))),
            ),
            TypeVariant::EncryptedBody => Box::new(
                ReadXdrIter::<_, Frame<EncryptedBody>>::new(r)
                    .map(|r| r.map(|t| Self::EncryptedBody(Box::new(t.0)))),
            ),
            TypeVariant::SurveyResponseMessage => Box::new(
                ReadXdrIter::<_, Frame<SurveyResponseMessage>>::new(r)
                    .map(|r| r.map(|t| Self::SurveyResponseMessage(Box::new(t.0)))),
            ),
            TypeVariant::SignedSurveyResponseMessage => Box::new(
                ReadXdrIter::<_, Frame<SignedSurveyResponseMessage>>::new(r)
                    .map(|r| r.map(|t| Self::SignedSurveyResponseMessage(Box::new(t.0)))),
            ),
            TypeVariant::PeerStats => Box::new(
                ReadXdrIter::<_, Frame<PeerStats>>::new(r)
                    .map(|r| r.map(|t| Self::PeerStats(Box::new(t.0)))),
            ),
            TypeVariant::PeerStatList => Box::new(
                ReadXdrIter::<_, Frame<PeerStatList>>::new(r)
                    .map(|r| r.map(|t| Self::PeerStatList(Box::new(t.0)))),
            ),
            TypeVariant::TopologyResponseBody => Box::new(
                ReadXdrIter::<_, Frame<TopologyResponseBody>>::new(r)
                    .map(|r| r.map(|t| Self::TopologyResponseBody(Box::new(t.0)))),
            ),
            TypeVariant::SurveyResponseBody => Box::new(
                ReadXdrIter::<_, Frame<SurveyResponseBody>>::new(r)
                    .map(|r| r.map(|t| Self::SurveyResponseBody(Box::new(t.0)))),
            ),
            TypeVariant::TxAdvertVector => Box::new(
                ReadXdrIter::<_, Frame<TxAdvertVector>>::new(r)
                    .map(|r| r.map(|t| Self::TxAdvertVector(Box::new(t.0)))),
            ),
            TypeVariant::FloodAdvert => Box::new(
                ReadXdrIter::<_, Frame<FloodAdvert>>::new(r)
                    .map(|r| r.map(|t| Self::FloodAdvert(Box::new(t.0)))),
            ),
            TypeVariant::TxDemandVector => Box::new(
                ReadXdrIter::<_, Frame<TxDemandVector>>::new(r)
                    .map(|r| r.map(|t| Self::TxDemandVector(Box::new(t.0)))),
            ),
            TypeVariant::FloodDemand => Box::new(
                ReadXdrIter::<_, Frame<FloodDemand>>::new(r)
                    .map(|r| r.map(|t| Self::FloodDemand(Box::new(t.0)))),
            ),
            TypeVariant::StellarMessage => Box::new(
                ReadXdrIter::<_, Frame<StellarMessage>>::new(r)
                    .map(|r| r.map(|t| Self::StellarMessage(Box::new(t.0)))),
            ),
            TypeVariant::AuthenticatedMessage => Box::new(
                ReadXdrIter::<_, Frame<AuthenticatedMessage>>::new(r)
                    .map(|r| r.map(|t| Self::AuthenticatedMessage(Box::new(t.0)))),
            ),
            TypeVariant::AuthenticatedMessageV0 => Box::new(
                ReadXdrIter::<_, Frame<AuthenticatedMessageV0>>::new(r)
                    .map(|r| r.map(|t| Self::AuthenticatedMessageV0(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolParameters => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolParameters>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolParameters(Box::new(t.0)))),
            ),
            TypeVariant::MuxedAccount => Box::new(
                ReadXdrIter::<_, Frame<MuxedAccount>>::new(r)
                    .map(|r| r.map(|t| Self::MuxedAccount(Box::new(t.0)))),
            ),
            TypeVariant::MuxedAccountMed25519 => Box::new(
                ReadXdrIter::<_, Frame<MuxedAccountMed25519>>::new(r)
                    .map(|r| r.map(|t| Self::MuxedAccountMed25519(Box::new(t.0)))),
            ),
            TypeVariant::DecoratedSignature => Box::new(
                ReadXdrIter::<_, Frame<DecoratedSignature>>::new(r)
                    .map(|r| r.map(|t| Self::DecoratedSignature(Box::new(t.0)))),
            ),
            TypeVariant::LedgerFootprint => Box::new(
                ReadXdrIter::<_, Frame<LedgerFootprint>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerFootprint(Box::new(t.0)))),
            ),
            TypeVariant::OperationType => Box::new(
                ReadXdrIter::<_, Frame<OperationType>>::new(r)
                    .map(|r| r.map(|t| Self::OperationType(Box::new(t.0)))),
            ),
            TypeVariant::CreateAccountOp => Box::new(
                ReadXdrIter::<_, Frame<CreateAccountOp>>::new(r)
                    .map(|r| r.map(|t| Self::CreateAccountOp(Box::new(t.0)))),
            ),
            TypeVariant::PaymentOp => Box::new(
                ReadXdrIter::<_, Frame<PaymentOp>>::new(r)
                    .map(|r| r.map(|t| Self::PaymentOp(Box::new(t.0)))),
            ),
            TypeVariant::PathPaymentStrictReceiveOp => Box::new(
                ReadXdrIter::<_, Frame<PathPaymentStrictReceiveOp>>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveOp(Box::new(t.0)))),
            ),
            TypeVariant::PathPaymentStrictSendOp => Box::new(
                ReadXdrIter::<_, Frame<PathPaymentStrictSendOp>>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendOp(Box::new(t.0)))),
            ),
            TypeVariant::ManageSellOfferOp => Box::new(
                ReadXdrIter::<_, Frame<ManageSellOfferOp>>::new(r)
                    .map(|r| r.map(|t| Self::ManageSellOfferOp(Box::new(t.0)))),
            ),
            TypeVariant::ManageBuyOfferOp => Box::new(
                ReadXdrIter::<_, Frame<ManageBuyOfferOp>>::new(r)
                    .map(|r| r.map(|t| Self::ManageBuyOfferOp(Box::new(t.0)))),
            ),
            TypeVariant::CreatePassiveSellOfferOp => Box::new(
                ReadXdrIter::<_, Frame<CreatePassiveSellOfferOp>>::new(r)
                    .map(|r| r.map(|t| Self::CreatePassiveSellOfferOp(Box::new(t.0)))),
            ),
            TypeVariant::SetOptionsOp => Box::new(
                ReadXdrIter::<_, Frame<SetOptionsOp>>::new(r)
                    .map(|r| r.map(|t| Self::SetOptionsOp(Box::new(t.0)))),
            ),
            TypeVariant::ChangeTrustAsset => Box::new(
                ReadXdrIter::<_, Frame<ChangeTrustAsset>>::new(r)
                    .map(|r| r.map(|t| Self::ChangeTrustAsset(Box::new(t.0)))),
            ),
            TypeVariant::ChangeTrustOp => Box::new(
                ReadXdrIter::<_, Frame<ChangeTrustOp>>::new(r)
                    .map(|r| r.map(|t| Self::ChangeTrustOp(Box::new(t.0)))),
            ),
            TypeVariant::AllowTrustOp => Box::new(
                ReadXdrIter::<_, Frame<AllowTrustOp>>::new(r)
                    .map(|r| r.map(|t| Self::AllowTrustOp(Box::new(t.0)))),
            ),
            TypeVariant::ManageDataOp => Box::new(
                ReadXdrIter::<_, Frame<ManageDataOp>>::new(r)
                    .map(|r| r.map(|t| Self::ManageDataOp(Box::new(t.0)))),
            ),
            TypeVariant::BumpSequenceOp => Box::new(
                ReadXdrIter::<_, Frame<BumpSequenceOp>>::new(r)
                    .map(|r| r.map(|t| Self::BumpSequenceOp(Box::new(t.0)))),
            ),
            TypeVariant::CreateClaimableBalanceOp => Box::new(
                ReadXdrIter::<_, Frame<CreateClaimableBalanceOp>>::new(r)
                    .map(|r| r.map(|t| Self::CreateClaimableBalanceOp(Box::new(t.0)))),
            ),
            TypeVariant::ClaimClaimableBalanceOp => Box::new(
                ReadXdrIter::<_, Frame<ClaimClaimableBalanceOp>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimClaimableBalanceOp(Box::new(t.0)))),
            ),
            TypeVariant::BeginSponsoringFutureReservesOp => Box::new(
                ReadXdrIter::<_, Frame<BeginSponsoringFutureReservesOp>>::new(r)
                    .map(|r| r.map(|t| Self::BeginSponsoringFutureReservesOp(Box::new(t.0)))),
            ),
            TypeVariant::RevokeSponsorshipType => Box::new(
                ReadXdrIter::<_, Frame<RevokeSponsorshipType>>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipType(Box::new(t.0)))),
            ),
            TypeVariant::RevokeSponsorshipOp => Box::new(
                ReadXdrIter::<_, Frame<RevokeSponsorshipOp>>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipOp(Box::new(t.0)))),
            ),
            TypeVariant::RevokeSponsorshipOpSigner => Box::new(
                ReadXdrIter::<_, Frame<RevokeSponsorshipOpSigner>>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipOpSigner(Box::new(t.0)))),
            ),
            TypeVariant::ClawbackOp => Box::new(
                ReadXdrIter::<_, Frame<ClawbackOp>>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackOp(Box::new(t.0)))),
            ),
            TypeVariant::ClawbackClaimableBalanceOp => Box::new(
                ReadXdrIter::<_, Frame<ClawbackClaimableBalanceOp>>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackClaimableBalanceOp(Box::new(t.0)))),
            ),
            TypeVariant::SetTrustLineFlagsOp => Box::new(
                ReadXdrIter::<_, Frame<SetTrustLineFlagsOp>>::new(r)
                    .map(|r| r.map(|t| Self::SetTrustLineFlagsOp(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolDepositOp => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolDepositOp>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolDepositOp(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolWithdrawOp => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolWithdrawOp>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolWithdrawOp(Box::new(t.0)))),
            ),
            TypeVariant::HostFunctionType => Box::new(
                ReadXdrIter::<_, Frame<HostFunctionType>>::new(r)
                    .map(|r| r.map(|t| Self::HostFunctionType(Box::new(t.0)))),
            ),
            TypeVariant::ContractIdType => Box::new(
                ReadXdrIter::<_, Frame<ContractIdType>>::new(r)
                    .map(|r| r.map(|t| Self::ContractIdType(Box::new(t.0)))),
            ),
            TypeVariant::ContractIdPublicKeyType => Box::new(
                ReadXdrIter::<_, Frame<ContractIdPublicKeyType>>::new(r)
                    .map(|r| r.map(|t| Self::ContractIdPublicKeyType(Box::new(t.0)))),
            ),
            TypeVariant::InstallContractCodeArgs => Box::new(
                ReadXdrIter::<_, Frame<InstallContractCodeArgs>>::new(r)
                    .map(|r| r.map(|t| Self::InstallContractCodeArgs(Box::new(t.0)))),
            ),
            TypeVariant::ContractId => Box::new(
                ReadXdrIter::<_, Frame<ContractId>>::new(r)
                    .map(|r| r.map(|t| Self::ContractId(Box::new(t.0)))),
            ),
            TypeVariant::ContractIdFromEd25519PublicKey => Box::new(
                ReadXdrIter::<_, Frame<ContractIdFromEd25519PublicKey>>::new(r)
                    .map(|r| r.map(|t| Self::ContractIdFromEd25519PublicKey(Box::new(t.0)))),
            ),
            TypeVariant::CreateContractArgs => Box::new(
                ReadXdrIter::<_, Frame<CreateContractArgs>>::new(r)
                    .map(|r| r.map(|t| Self::CreateContractArgs(Box::new(t.0)))),
            ),
            TypeVariant::HostFunction => Box::new(
                ReadXdrIter::<_, Frame<HostFunction>>::new(r)
                    .map(|r| r.map(|t| Self::HostFunction(Box::new(t.0)))),
            ),
            TypeVariant::InvokeHostFunctionOp => Box::new(
                ReadXdrIter::<_, Frame<InvokeHostFunctionOp>>::new(r)
                    .map(|r| r.map(|t| Self::InvokeHostFunctionOp(Box::new(t.0)))),
            ),
            TypeVariant::Operation => Box::new(
                ReadXdrIter::<_, Frame<Operation>>::new(r)
                    .map(|r| r.map(|t| Self::Operation(Box::new(t.0)))),
            ),
            TypeVariant::OperationBody => Box::new(
                ReadXdrIter::<_, Frame<OperationBody>>::new(r)
                    .map(|r| r.map(|t| Self::OperationBody(Box::new(t.0)))),
            ),
            TypeVariant::HashIdPreimage => Box::new(
                ReadXdrIter::<_, Frame<HashIdPreimage>>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimage(Box::new(t.0)))),
            ),
            TypeVariant::HashIdPreimageOperationId => Box::new(
                ReadXdrIter::<_, Frame<HashIdPreimageOperationId>>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageOperationId(Box::new(t.0)))),
            ),
            TypeVariant::HashIdPreimageRevokeId => Box::new(
                ReadXdrIter::<_, Frame<HashIdPreimageRevokeId>>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageRevokeId(Box::new(t.0)))),
            ),
            TypeVariant::HashIdPreimageEd25519ContractId => Box::new(
                ReadXdrIter::<_, Frame<HashIdPreimageEd25519ContractId>>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageEd25519ContractId(Box::new(t.0)))),
            ),
            TypeVariant::HashIdPreimageContractId => Box::new(
                ReadXdrIter::<_, Frame<HashIdPreimageContractId>>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageContractId(Box::new(t.0)))),
            ),
            TypeVariant::HashIdPreimageFromAsset => Box::new(
                ReadXdrIter::<_, Frame<HashIdPreimageFromAsset>>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageFromAsset(Box::new(t.0)))),
            ),
            TypeVariant::HashIdPreimageSourceAccountContractId => Box::new(
                ReadXdrIter::<_, Frame<HashIdPreimageSourceAccountContractId>>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageSourceAccountContractId(Box::new(t.0)))),
            ),
            TypeVariant::HashIdPreimageCreateContractArgs => Box::new(
                ReadXdrIter::<_, Frame<HashIdPreimageCreateContractArgs>>::new(r)
                    .map(|r| r.map(|t| Self::HashIdPreimageCreateContractArgs(Box::new(t.0)))),
            ),
            TypeVariant::MemoType => Box::new(
                ReadXdrIter::<_, Frame<MemoType>>::new(r)
                    .map(|r| r.map(|t| Self::MemoType(Box::new(t.0)))),
            ),
            TypeVariant::Memo => Box::new(
                ReadXdrIter::<_, Frame<Memo>>::new(r).map(|r| r.map(|t| Self::Memo(Box::new(t.0)))),
            ),
            TypeVariant::TimeBounds => Box::new(
                ReadXdrIter::<_, Frame<TimeBounds>>::new(r)
                    .map(|r| r.map(|t| Self::TimeBounds(Box::new(t.0)))),
            ),
            TypeVariant::LedgerBounds => Box::new(
                ReadXdrIter::<_, Frame<LedgerBounds>>::new(r)
                    .map(|r| r.map(|t| Self::LedgerBounds(Box::new(t.0)))),
            ),
            TypeVariant::PreconditionsV2 => Box::new(
                ReadXdrIter::<_, Frame<PreconditionsV2>>::new(r)
                    .map(|r| r.map(|t| Self::PreconditionsV2(Box::new(t.0)))),
            ),
            TypeVariant::PreconditionType => Box::new(
                ReadXdrIter::<_, Frame<PreconditionType>>::new(r)
                    .map(|r| r.map(|t| Self::PreconditionType(Box::new(t.0)))),
            ),
            TypeVariant::Preconditions => Box::new(
                ReadXdrIter::<_, Frame<Preconditions>>::new(r)
                    .map(|r| r.map(|t| Self::Preconditions(Box::new(t.0)))),
            ),
            TypeVariant::TransactionV0 => Box::new(
                ReadXdrIter::<_, Frame<TransactionV0>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionV0(Box::new(t.0)))),
            ),
            TypeVariant::TransactionV0Ext => Box::new(
                ReadXdrIter::<_, Frame<TransactionV0Ext>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionV0Ext(Box::new(t.0)))),
            ),
            TypeVariant::TransactionV0Envelope => Box::new(
                ReadXdrIter::<_, Frame<TransactionV0Envelope>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionV0Envelope(Box::new(t.0)))),
            ),
            TypeVariant::Transaction => Box::new(
                ReadXdrIter::<_, Frame<Transaction>>::new(r)
                    .map(|r| r.map(|t| Self::Transaction(Box::new(t.0)))),
            ),
            TypeVariant::TransactionExt => Box::new(
                ReadXdrIter::<_, Frame<TransactionExt>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionExt(Box::new(t.0)))),
            ),
            TypeVariant::TransactionV1Envelope => Box::new(
                ReadXdrIter::<_, Frame<TransactionV1Envelope>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionV1Envelope(Box::new(t.0)))),
            ),
            TypeVariant::FeeBumpTransaction => Box::new(
                ReadXdrIter::<_, Frame<FeeBumpTransaction>>::new(r)
                    .map(|r| r.map(|t| Self::FeeBumpTransaction(Box::new(t.0)))),
            ),
            TypeVariant::FeeBumpTransactionInnerTx => Box::new(
                ReadXdrIter::<_, Frame<FeeBumpTransactionInnerTx>>::new(r)
                    .map(|r| r.map(|t| Self::FeeBumpTransactionInnerTx(Box::new(t.0)))),
            ),
            TypeVariant::FeeBumpTransactionExt => Box::new(
                ReadXdrIter::<_, Frame<FeeBumpTransactionExt>>::new(r)
                    .map(|r| r.map(|t| Self::FeeBumpTransactionExt(Box::new(t.0)))),
            ),
            TypeVariant::FeeBumpTransactionEnvelope => Box::new(
                ReadXdrIter::<_, Frame<FeeBumpTransactionEnvelope>>::new(r)
                    .map(|r| r.map(|t| Self::FeeBumpTransactionEnvelope(Box::new(t.0)))),
            ),
            TypeVariant::TransactionEnvelope => Box::new(
                ReadXdrIter::<_, Frame<TransactionEnvelope>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionEnvelope(Box::new(t.0)))),
            ),
            TypeVariant::TransactionSignaturePayload => Box::new(
                ReadXdrIter::<_, Frame<TransactionSignaturePayload>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionSignaturePayload(Box::new(t.0)))),
            ),
            TypeVariant::TransactionSignaturePayloadTaggedTransaction => Box::new(
                ReadXdrIter::<_, Frame<TransactionSignaturePayloadTaggedTransaction>>::new(r).map(
                    |r| {
                        r.map(|t| Self::TransactionSignaturePayloadTaggedTransaction(Box::new(t.0)))
                    },
                ),
            ),
            TypeVariant::ClaimAtomType => Box::new(
                ReadXdrIter::<_, Frame<ClaimAtomType>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimAtomType(Box::new(t.0)))),
            ),
            TypeVariant::ClaimOfferAtomV0 => Box::new(
                ReadXdrIter::<_, Frame<ClaimOfferAtomV0>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimOfferAtomV0(Box::new(t.0)))),
            ),
            TypeVariant::ClaimOfferAtom => Box::new(
                ReadXdrIter::<_, Frame<ClaimOfferAtom>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimOfferAtom(Box::new(t.0)))),
            ),
            TypeVariant::ClaimLiquidityAtom => Box::new(
                ReadXdrIter::<_, Frame<ClaimLiquidityAtom>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimLiquidityAtom(Box::new(t.0)))),
            ),
            TypeVariant::ClaimAtom => Box::new(
                ReadXdrIter::<_, Frame<ClaimAtom>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimAtom(Box::new(t.0)))),
            ),
            TypeVariant::CreateAccountResultCode => Box::new(
                ReadXdrIter::<_, Frame<CreateAccountResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::CreateAccountResultCode(Box::new(t.0)))),
            ),
            TypeVariant::CreateAccountResult => Box::new(
                ReadXdrIter::<_, Frame<CreateAccountResult>>::new(r)
                    .map(|r| r.map(|t| Self::CreateAccountResult(Box::new(t.0)))),
            ),
            TypeVariant::PaymentResultCode => Box::new(
                ReadXdrIter::<_, Frame<PaymentResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::PaymentResultCode(Box::new(t.0)))),
            ),
            TypeVariant::PaymentResult => Box::new(
                ReadXdrIter::<_, Frame<PaymentResult>>::new(r)
                    .map(|r| r.map(|t| Self::PaymentResult(Box::new(t.0)))),
            ),
            TypeVariant::PathPaymentStrictReceiveResultCode => Box::new(
                ReadXdrIter::<_, Frame<PathPaymentStrictReceiveResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveResultCode(Box::new(t.0)))),
            ),
            TypeVariant::SimplePaymentResult => Box::new(
                ReadXdrIter::<_, Frame<SimplePaymentResult>>::new(r)
                    .map(|r| r.map(|t| Self::SimplePaymentResult(Box::new(t.0)))),
            ),
            TypeVariant::PathPaymentStrictReceiveResult => Box::new(
                ReadXdrIter::<_, Frame<PathPaymentStrictReceiveResult>>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveResult(Box::new(t.0)))),
            ),
            TypeVariant::PathPaymentStrictReceiveResultSuccess => Box::new(
                ReadXdrIter::<_, Frame<PathPaymentStrictReceiveResultSuccess>>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveResultSuccess(Box::new(t.0)))),
            ),
            TypeVariant::PathPaymentStrictSendResultCode => Box::new(
                ReadXdrIter::<_, Frame<PathPaymentStrictSendResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendResultCode(Box::new(t.0)))),
            ),
            TypeVariant::PathPaymentStrictSendResult => Box::new(
                ReadXdrIter::<_, Frame<PathPaymentStrictSendResult>>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendResult(Box::new(t.0)))),
            ),
            TypeVariant::PathPaymentStrictSendResultSuccess => Box::new(
                ReadXdrIter::<_, Frame<PathPaymentStrictSendResultSuccess>>::new(r)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendResultSuccess(Box::new(t.0)))),
            ),
            TypeVariant::ManageSellOfferResultCode => Box::new(
                ReadXdrIter::<_, Frame<ManageSellOfferResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::ManageSellOfferResultCode(Box::new(t.0)))),
            ),
            TypeVariant::ManageOfferEffect => Box::new(
                ReadXdrIter::<_, Frame<ManageOfferEffect>>::new(r)
                    .map(|r| r.map(|t| Self::ManageOfferEffect(Box::new(t.0)))),
            ),
            TypeVariant::ManageOfferSuccessResult => Box::new(
                ReadXdrIter::<_, Frame<ManageOfferSuccessResult>>::new(r)
                    .map(|r| r.map(|t| Self::ManageOfferSuccessResult(Box::new(t.0)))),
            ),
            TypeVariant::ManageOfferSuccessResultOffer => Box::new(
                ReadXdrIter::<_, Frame<ManageOfferSuccessResultOffer>>::new(r)
                    .map(|r| r.map(|t| Self::ManageOfferSuccessResultOffer(Box::new(t.0)))),
            ),
            TypeVariant::ManageSellOfferResult => Box::new(
                ReadXdrIter::<_, Frame<ManageSellOfferResult>>::new(r)
                    .map(|r| r.map(|t| Self::ManageSellOfferResult(Box::new(t.0)))),
            ),
            TypeVariant::ManageBuyOfferResultCode => Box::new(
                ReadXdrIter::<_, Frame<ManageBuyOfferResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::ManageBuyOfferResultCode(Box::new(t.0)))),
            ),
            TypeVariant::ManageBuyOfferResult => Box::new(
                ReadXdrIter::<_, Frame<ManageBuyOfferResult>>::new(r)
                    .map(|r| r.map(|t| Self::ManageBuyOfferResult(Box::new(t.0)))),
            ),
            TypeVariant::SetOptionsResultCode => Box::new(
                ReadXdrIter::<_, Frame<SetOptionsResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::SetOptionsResultCode(Box::new(t.0)))),
            ),
            TypeVariant::SetOptionsResult => Box::new(
                ReadXdrIter::<_, Frame<SetOptionsResult>>::new(r)
                    .map(|r| r.map(|t| Self::SetOptionsResult(Box::new(t.0)))),
            ),
            TypeVariant::ChangeTrustResultCode => Box::new(
                ReadXdrIter::<_, Frame<ChangeTrustResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::ChangeTrustResultCode(Box::new(t.0)))),
            ),
            TypeVariant::ChangeTrustResult => Box::new(
                ReadXdrIter::<_, Frame<ChangeTrustResult>>::new(r)
                    .map(|r| r.map(|t| Self::ChangeTrustResult(Box::new(t.0)))),
            ),
            TypeVariant::AllowTrustResultCode => Box::new(
                ReadXdrIter::<_, Frame<AllowTrustResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::AllowTrustResultCode(Box::new(t.0)))),
            ),
            TypeVariant::AllowTrustResult => Box::new(
                ReadXdrIter::<_, Frame<AllowTrustResult>>::new(r)
                    .map(|r| r.map(|t| Self::AllowTrustResult(Box::new(t.0)))),
            ),
            TypeVariant::AccountMergeResultCode => Box::new(
                ReadXdrIter::<_, Frame<AccountMergeResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::AccountMergeResultCode(Box::new(t.0)))),
            ),
            TypeVariant::AccountMergeResult => Box::new(
                ReadXdrIter::<_, Frame<AccountMergeResult>>::new(r)
                    .map(|r| r.map(|t| Self::AccountMergeResult(Box::new(t.0)))),
            ),
            TypeVariant::InflationResultCode => Box::new(
                ReadXdrIter::<_, Frame<InflationResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::InflationResultCode(Box::new(t.0)))),
            ),
            TypeVariant::InflationPayout => Box::new(
                ReadXdrIter::<_, Frame<InflationPayout>>::new(r)
                    .map(|r| r.map(|t| Self::InflationPayout(Box::new(t.0)))),
            ),
            TypeVariant::InflationResult => Box::new(
                ReadXdrIter::<_, Frame<InflationResult>>::new(r)
                    .map(|r| r.map(|t| Self::InflationResult(Box::new(t.0)))),
            ),
            TypeVariant::ManageDataResultCode => Box::new(
                ReadXdrIter::<_, Frame<ManageDataResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::ManageDataResultCode(Box::new(t.0)))),
            ),
            TypeVariant::ManageDataResult => Box::new(
                ReadXdrIter::<_, Frame<ManageDataResult>>::new(r)
                    .map(|r| r.map(|t| Self::ManageDataResult(Box::new(t.0)))),
            ),
            TypeVariant::BumpSequenceResultCode => Box::new(
                ReadXdrIter::<_, Frame<BumpSequenceResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::BumpSequenceResultCode(Box::new(t.0)))),
            ),
            TypeVariant::BumpSequenceResult => Box::new(
                ReadXdrIter::<_, Frame<BumpSequenceResult>>::new(r)
                    .map(|r| r.map(|t| Self::BumpSequenceResult(Box::new(t.0)))),
            ),
            TypeVariant::CreateClaimableBalanceResultCode => Box::new(
                ReadXdrIter::<_, Frame<CreateClaimableBalanceResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::CreateClaimableBalanceResultCode(Box::new(t.0)))),
            ),
            TypeVariant::CreateClaimableBalanceResult => Box::new(
                ReadXdrIter::<_, Frame<CreateClaimableBalanceResult>>::new(r)
                    .map(|r| r.map(|t| Self::CreateClaimableBalanceResult(Box::new(t.0)))),
            ),
            TypeVariant::ClaimClaimableBalanceResultCode => Box::new(
                ReadXdrIter::<_, Frame<ClaimClaimableBalanceResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimClaimableBalanceResultCode(Box::new(t.0)))),
            ),
            TypeVariant::ClaimClaimableBalanceResult => Box::new(
                ReadXdrIter::<_, Frame<ClaimClaimableBalanceResult>>::new(r)
                    .map(|r| r.map(|t| Self::ClaimClaimableBalanceResult(Box::new(t.0)))),
            ),
            TypeVariant::BeginSponsoringFutureReservesResultCode => Box::new(
                ReadXdrIter::<_, Frame<BeginSponsoringFutureReservesResultCode>>::new(r).map(|r| {
                    r.map(|t| Self::BeginSponsoringFutureReservesResultCode(Box::new(t.0)))
                }),
            ),
            TypeVariant::BeginSponsoringFutureReservesResult => Box::new(
                ReadXdrIter::<_, Frame<BeginSponsoringFutureReservesResult>>::new(r)
                    .map(|r| r.map(|t| Self::BeginSponsoringFutureReservesResult(Box::new(t.0)))),
            ),
            TypeVariant::EndSponsoringFutureReservesResultCode => Box::new(
                ReadXdrIter::<_, Frame<EndSponsoringFutureReservesResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::EndSponsoringFutureReservesResultCode(Box::new(t.0)))),
            ),
            TypeVariant::EndSponsoringFutureReservesResult => Box::new(
                ReadXdrIter::<_, Frame<EndSponsoringFutureReservesResult>>::new(r)
                    .map(|r| r.map(|t| Self::EndSponsoringFutureReservesResult(Box::new(t.0)))),
            ),
            TypeVariant::RevokeSponsorshipResultCode => Box::new(
                ReadXdrIter::<_, Frame<RevokeSponsorshipResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipResultCode(Box::new(t.0)))),
            ),
            TypeVariant::RevokeSponsorshipResult => Box::new(
                ReadXdrIter::<_, Frame<RevokeSponsorshipResult>>::new(r)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipResult(Box::new(t.0)))),
            ),
            TypeVariant::ClawbackResultCode => Box::new(
                ReadXdrIter::<_, Frame<ClawbackResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackResultCode(Box::new(t.0)))),
            ),
            TypeVariant::ClawbackResult => Box::new(
                ReadXdrIter::<_, Frame<ClawbackResult>>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackResult(Box::new(t.0)))),
            ),
            TypeVariant::ClawbackClaimableBalanceResultCode => Box::new(
                ReadXdrIter::<_, Frame<ClawbackClaimableBalanceResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackClaimableBalanceResultCode(Box::new(t.0)))),
            ),
            TypeVariant::ClawbackClaimableBalanceResult => Box::new(
                ReadXdrIter::<_, Frame<ClawbackClaimableBalanceResult>>::new(r)
                    .map(|r| r.map(|t| Self::ClawbackClaimableBalanceResult(Box::new(t.0)))),
            ),
            TypeVariant::SetTrustLineFlagsResultCode => Box::new(
                ReadXdrIter::<_, Frame<SetTrustLineFlagsResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::SetTrustLineFlagsResultCode(Box::new(t.0)))),
            ),
            TypeVariant::SetTrustLineFlagsResult => Box::new(
                ReadXdrIter::<_, Frame<SetTrustLineFlagsResult>>::new(r)
                    .map(|r| r.map(|t| Self::SetTrustLineFlagsResult(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolDepositResultCode => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolDepositResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolDepositResultCode(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolDepositResult => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolDepositResult>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolDepositResult(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolWithdrawResultCode => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolWithdrawResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolWithdrawResultCode(Box::new(t.0)))),
            ),
            TypeVariant::LiquidityPoolWithdrawResult => Box::new(
                ReadXdrIter::<_, Frame<LiquidityPoolWithdrawResult>>::new(r)
                    .map(|r| r.map(|t| Self::LiquidityPoolWithdrawResult(Box::new(t.0)))),
            ),
            TypeVariant::InvokeHostFunctionResultCode => Box::new(
                ReadXdrIter::<_, Frame<InvokeHostFunctionResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::InvokeHostFunctionResultCode(Box::new(t.0)))),
            ),
            TypeVariant::InvokeHostFunctionResult => Box::new(
                ReadXdrIter::<_, Frame<InvokeHostFunctionResult>>::new(r)
                    .map(|r| r.map(|t| Self::InvokeHostFunctionResult(Box::new(t.0)))),
            ),
            TypeVariant::OperationResultCode => Box::new(
                ReadXdrIter::<_, Frame<OperationResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::OperationResultCode(Box::new(t.0)))),
            ),
            TypeVariant::OperationResult => Box::new(
                ReadXdrIter::<_, Frame<OperationResult>>::new(r)
                    .map(|r| r.map(|t| Self::OperationResult(Box::new(t.0)))),
            ),
            TypeVariant::OperationResultTr => Box::new(
                ReadXdrIter::<_, Frame<OperationResultTr>>::new(r)
                    .map(|r| r.map(|t| Self::OperationResultTr(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResultCode => Box::new(
                ReadXdrIter::<_, Frame<TransactionResultCode>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultCode(Box::new(t.0)))),
            ),
            TypeVariant::InnerTransactionResult => Box::new(
                ReadXdrIter::<_, Frame<InnerTransactionResult>>::new(r)
                    .map(|r| r.map(|t| Self::InnerTransactionResult(Box::new(t.0)))),
            ),
            TypeVariant::InnerTransactionResultResult => Box::new(
                ReadXdrIter::<_, Frame<InnerTransactionResultResult>>::new(r)
                    .map(|r| r.map(|t| Self::InnerTransactionResultResult(Box::new(t.0)))),
            ),
            TypeVariant::InnerTransactionResultExt => Box::new(
                ReadXdrIter::<_, Frame<InnerTransactionResultExt>>::new(r)
                    .map(|r| r.map(|t| Self::InnerTransactionResultExt(Box::new(t.0)))),
            ),
            TypeVariant::InnerTransactionResultPair => Box::new(
                ReadXdrIter::<_, Frame<InnerTransactionResultPair>>::new(r)
                    .map(|r| r.map(|t| Self::InnerTransactionResultPair(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResult => Box::new(
                ReadXdrIter::<_, Frame<TransactionResult>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResult(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResultResult => Box::new(
                ReadXdrIter::<_, Frame<TransactionResultResult>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultResult(Box::new(t.0)))),
            ),
            TypeVariant::TransactionResultExt => Box::new(
                ReadXdrIter::<_, Frame<TransactionResultExt>>::new(r)
                    .map(|r| r.map(|t| Self::TransactionResultExt(Box::new(t.0)))),
            ),
            TypeVariant::Hash => Box::new(
                ReadXdrIter::<_, Frame<Hash>>::new(r).map(|r| r.map(|t| Self::Hash(Box::new(t.0)))),
            ),
            TypeVariant::Uint256 => Box::new(
                ReadXdrIter::<_, Frame<Uint256>>::new(r)
                    .map(|r| r.map(|t| Self::Uint256(Box::new(t.0)))),
            ),
            TypeVariant::Uint32 => Box::new(
                ReadXdrIter::<_, Frame<Uint32>>::new(r)
                    .map(|r| r.map(|t| Self::Uint32(Box::new(t.0)))),
            ),
            TypeVariant::Int32 => Box::new(
                ReadXdrIter::<_, Frame<Int32>>::new(r)
                    .map(|r| r.map(|t| Self::Int32(Box::new(t.0)))),
            ),
            TypeVariant::Uint64 => Box::new(
                ReadXdrIter::<_, Frame<Uint64>>::new(r)
                    .map(|r| r.map(|t| Self::Uint64(Box::new(t.0)))),
            ),
            TypeVariant::Int64 => Box::new(
                ReadXdrIter::<_, Frame<Int64>>::new(r)
                    .map(|r| r.map(|t| Self::Int64(Box::new(t.0)))),
            ),
            TypeVariant::ExtensionPoint => Box::new(
                ReadXdrIter::<_, Frame<ExtensionPoint>>::new(r)
                    .map(|r| r.map(|t| Self::ExtensionPoint(Box::new(t.0)))),
            ),
            TypeVariant::CryptoKeyType => Box::new(
                ReadXdrIter::<_, Frame<CryptoKeyType>>::new(r)
                    .map(|r| r.map(|t| Self::CryptoKeyType(Box::new(t.0)))),
            ),
            TypeVariant::PublicKeyType => Box::new(
                ReadXdrIter::<_, Frame<PublicKeyType>>::new(r)
                    .map(|r| r.map(|t| Self::PublicKeyType(Box::new(t.0)))),
            ),
            TypeVariant::SignerKeyType => Box::new(
                ReadXdrIter::<_, Frame<SignerKeyType>>::new(r)
                    .map(|r| r.map(|t| Self::SignerKeyType(Box::new(t.0)))),
            ),
            TypeVariant::PublicKey => Box::new(
                ReadXdrIter::<_, Frame<PublicKey>>::new(r)
                    .map(|r| r.map(|t| Self::PublicKey(Box::new(t.0)))),
            ),
            TypeVariant::SignerKey => Box::new(
                ReadXdrIter::<_, Frame<SignerKey>>::new(r)
                    .map(|r| r.map(|t| Self::SignerKey(Box::new(t.0)))),
            ),
            TypeVariant::SignerKeyEd25519SignedPayload => Box::new(
                ReadXdrIter::<_, Frame<SignerKeyEd25519SignedPayload>>::new(r)
                    .map(|r| r.map(|t| Self::SignerKeyEd25519SignedPayload(Box::new(t.0)))),
            ),
            TypeVariant::Signature => Box::new(
                ReadXdrIter::<_, Frame<Signature>>::new(r)
                    .map(|r| r.map(|t| Self::Signature(Box::new(t.0)))),
            ),
            TypeVariant::SignatureHint => Box::new(
                ReadXdrIter::<_, Frame<SignatureHint>>::new(r)
                    .map(|r| r.map(|t| Self::SignatureHint(Box::new(t.0)))),
            ),
            TypeVariant::NodeId => Box::new(
                ReadXdrIter::<_, Frame<NodeId>>::new(r)
                    .map(|r| r.map(|t| Self::NodeId(Box::new(t.0)))),
            ),
            TypeVariant::AccountId => Box::new(
                ReadXdrIter::<_, Frame<AccountId>>::new(r)
                    .map(|r| r.map(|t| Self::AccountId(Box::new(t.0)))),
            ),
            TypeVariant::Curve25519Secret => Box::new(
                ReadXdrIter::<_, Frame<Curve25519Secret>>::new(r)
                    .map(|r| r.map(|t| Self::Curve25519Secret(Box::new(t.0)))),
            ),
            TypeVariant::Curve25519Public => Box::new(
                ReadXdrIter::<_, Frame<Curve25519Public>>::new(r)
                    .map(|r| r.map(|t| Self::Curve25519Public(Box::new(t.0)))),
            ),
            TypeVariant::HmacSha256Key => Box::new(
                ReadXdrIter::<_, Frame<HmacSha256Key>>::new(r)
                    .map(|r| r.map(|t| Self::HmacSha256Key(Box::new(t.0)))),
            ),
            TypeVariant::HmacSha256Mac => Box::new(
                ReadXdrIter::<_, Frame<HmacSha256Mac>>::new(r)
                    .map(|r| r.map(|t| Self::HmacSha256Mac(Box::new(t.0)))),
            ),
        }
    }

    #[cfg(feature = "base64")]
    #[allow(clippy::too_many_lines)]
    pub fn read_xdr_base64_iter<R: Read>(
        v: TypeVariant,
        r: &mut R,
    ) -> Box<dyn Iterator<Item = Result<Self>> + '_> {
        let dec = base64::read::DecoderReader::new(r, base64::STANDARD);
        match v {
            TypeVariant::Value => Box::new(
                ReadXdrIter::<_, Value>::new(dec).map(|r| r.map(|t| Self::Value(Box::new(t)))),
            ),
            TypeVariant::ScpBallot => Box::new(
                ReadXdrIter::<_, ScpBallot>::new(dec)
                    .map(|r| r.map(|t| Self::ScpBallot(Box::new(t)))),
            ),
            TypeVariant::ScpStatementType => Box::new(
                ReadXdrIter::<_, ScpStatementType>::new(dec)
                    .map(|r| r.map(|t| Self::ScpStatementType(Box::new(t)))),
            ),
            TypeVariant::ScpNomination => Box::new(
                ReadXdrIter::<_, ScpNomination>::new(dec)
                    .map(|r| r.map(|t| Self::ScpNomination(Box::new(t)))),
            ),
            TypeVariant::ScpStatement => Box::new(
                ReadXdrIter::<_, ScpStatement>::new(dec)
                    .map(|r| r.map(|t| Self::ScpStatement(Box::new(t)))),
            ),
            TypeVariant::ScpStatementPledges => Box::new(
                ReadXdrIter::<_, ScpStatementPledges>::new(dec)
                    .map(|r| r.map(|t| Self::ScpStatementPledges(Box::new(t)))),
            ),
            TypeVariant::ScpStatementPrepare => Box::new(
                ReadXdrIter::<_, ScpStatementPrepare>::new(dec)
                    .map(|r| r.map(|t| Self::ScpStatementPrepare(Box::new(t)))),
            ),
            TypeVariant::ScpStatementConfirm => Box::new(
                ReadXdrIter::<_, ScpStatementConfirm>::new(dec)
                    .map(|r| r.map(|t| Self::ScpStatementConfirm(Box::new(t)))),
            ),
            TypeVariant::ScpStatementExternalize => Box::new(
                ReadXdrIter::<_, ScpStatementExternalize>::new(dec)
                    .map(|r| r.map(|t| Self::ScpStatementExternalize(Box::new(t)))),
            ),
            TypeVariant::ScpEnvelope => Box::new(
                ReadXdrIter::<_, ScpEnvelope>::new(dec)
                    .map(|r| r.map(|t| Self::ScpEnvelope(Box::new(t)))),
            ),
            TypeVariant::ScpQuorumSet => Box::new(
                ReadXdrIter::<_, ScpQuorumSet>::new(dec)
                    .map(|r| r.map(|t| Self::ScpQuorumSet(Box::new(t)))),
            ),
            TypeVariant::ScEnvMetaKind => Box::new(
                ReadXdrIter::<_, ScEnvMetaKind>::new(dec)
                    .map(|r| r.map(|t| Self::ScEnvMetaKind(Box::new(t)))),
            ),
            TypeVariant::ScEnvMetaEntry => Box::new(
                ReadXdrIter::<_, ScEnvMetaEntry>::new(dec)
                    .map(|r| r.map(|t| Self::ScEnvMetaEntry(Box::new(t)))),
            ),
            TypeVariant::ScSpecType => Box::new(
                ReadXdrIter::<_, ScSpecType>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecType(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeOption => Box::new(
                ReadXdrIter::<_, ScSpecTypeOption>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecTypeOption(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeResult => Box::new(
                ReadXdrIter::<_, ScSpecTypeResult>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecTypeResult(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeVec => Box::new(
                ReadXdrIter::<_, ScSpecTypeVec>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecTypeVec(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeMap => Box::new(
                ReadXdrIter::<_, ScSpecTypeMap>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecTypeMap(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeSet => Box::new(
                ReadXdrIter::<_, ScSpecTypeSet>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecTypeSet(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeTuple => Box::new(
                ReadXdrIter::<_, ScSpecTypeTuple>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecTypeTuple(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeBytesN => Box::new(
                ReadXdrIter::<_, ScSpecTypeBytesN>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecTypeBytesN(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeUdt => Box::new(
                ReadXdrIter::<_, ScSpecTypeUdt>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecTypeUdt(Box::new(t)))),
            ),
            TypeVariant::ScSpecTypeDef => Box::new(
                ReadXdrIter::<_, ScSpecTypeDef>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecTypeDef(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtStructFieldV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtStructFieldV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecUdtStructFieldV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtStructV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtStructV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecUdtStructV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtUnionCaseV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtUnionCaseV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecUdtUnionCaseV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtUnionV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtUnionV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecUdtUnionV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtEnumCaseV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtEnumCaseV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecUdtEnumCaseV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtEnumV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtEnumV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecUdtEnumV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtErrorEnumCaseV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtErrorEnumCaseV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecUdtErrorEnumCaseV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecUdtErrorEnumV0 => Box::new(
                ReadXdrIter::<_, ScSpecUdtErrorEnumV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecUdtErrorEnumV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecFunctionInputV0 => Box::new(
                ReadXdrIter::<_, ScSpecFunctionInputV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecFunctionInputV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecFunctionV0 => Box::new(
                ReadXdrIter::<_, ScSpecFunctionV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecFunctionV0(Box::new(t)))),
            ),
            TypeVariant::ScSpecEntryKind => Box::new(
                ReadXdrIter::<_, ScSpecEntryKind>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecEntryKind(Box::new(t)))),
            ),
            TypeVariant::ScSpecEntry => Box::new(
                ReadXdrIter::<_, ScSpecEntry>::new(dec)
                    .map(|r| r.map(|t| Self::ScSpecEntry(Box::new(t)))),
            ),
            TypeVariant::ScSymbol => Box::new(
                ReadXdrIter::<_, ScSymbol>::new(dec)
                    .map(|r| r.map(|t| Self::ScSymbol(Box::new(t)))),
            ),
            TypeVariant::ScValType => Box::new(
                ReadXdrIter::<_, ScValType>::new(dec)
                    .map(|r| r.map(|t| Self::ScValType(Box::new(t)))),
            ),
            TypeVariant::ScStatic => Box::new(
                ReadXdrIter::<_, ScStatic>::new(dec)
                    .map(|r| r.map(|t| Self::ScStatic(Box::new(t)))),
            ),
            TypeVariant::ScStatusType => Box::new(
                ReadXdrIter::<_, ScStatusType>::new(dec)
                    .map(|r| r.map(|t| Self::ScStatusType(Box::new(t)))),
            ),
            TypeVariant::ScHostValErrorCode => Box::new(
                ReadXdrIter::<_, ScHostValErrorCode>::new(dec)
                    .map(|r| r.map(|t| Self::ScHostValErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScHostObjErrorCode => Box::new(
                ReadXdrIter::<_, ScHostObjErrorCode>::new(dec)
                    .map(|r| r.map(|t| Self::ScHostObjErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScHostFnErrorCode => Box::new(
                ReadXdrIter::<_, ScHostFnErrorCode>::new(dec)
                    .map(|r| r.map(|t| Self::ScHostFnErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScHostStorageErrorCode => Box::new(
                ReadXdrIter::<_, ScHostStorageErrorCode>::new(dec)
                    .map(|r| r.map(|t| Self::ScHostStorageErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScHostContextErrorCode => Box::new(
                ReadXdrIter::<_, ScHostContextErrorCode>::new(dec)
                    .map(|r| r.map(|t| Self::ScHostContextErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScVmErrorCode => Box::new(
                ReadXdrIter::<_, ScVmErrorCode>::new(dec)
                    .map(|r| r.map(|t| Self::ScVmErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScUnknownErrorCode => Box::new(
                ReadXdrIter::<_, ScUnknownErrorCode>::new(dec)
                    .map(|r| r.map(|t| Self::ScUnknownErrorCode(Box::new(t)))),
            ),
            TypeVariant::ScStatus => Box::new(
                ReadXdrIter::<_, ScStatus>::new(dec)
                    .map(|r| r.map(|t| Self::ScStatus(Box::new(t)))),
            ),
            TypeVariant::ScVal => Box::new(
                ReadXdrIter::<_, ScVal>::new(dec).map(|r| r.map(|t| Self::ScVal(Box::new(t)))),
            ),
            TypeVariant::ScObjectType => Box::new(
                ReadXdrIter::<_, ScObjectType>::new(dec)
                    .map(|r| r.map(|t| Self::ScObjectType(Box::new(t)))),
            ),
            TypeVariant::ScMapEntry => Box::new(
                ReadXdrIter::<_, ScMapEntry>::new(dec)
                    .map(|r| r.map(|t| Self::ScMapEntry(Box::new(t)))),
            ),
            TypeVariant::ScVec => Box::new(
                ReadXdrIter::<_, ScVec>::new(dec).map(|r| r.map(|t| Self::ScVec(Box::new(t)))),
            ),
            TypeVariant::ScMap => Box::new(
                ReadXdrIter::<_, ScMap>::new(dec).map(|r| r.map(|t| Self::ScMap(Box::new(t)))),
            ),
            TypeVariant::ScContractCodeType => Box::new(
                ReadXdrIter::<_, ScContractCodeType>::new(dec)
                    .map(|r| r.map(|t| Self::ScContractCodeType(Box::new(t)))),
            ),
            TypeVariant::ScContractCode => Box::new(
                ReadXdrIter::<_, ScContractCode>::new(dec)
                    .map(|r| r.map(|t| Self::ScContractCode(Box::new(t)))),
            ),
            TypeVariant::Int128Parts => Box::new(
                ReadXdrIter::<_, Int128Parts>::new(dec)
                    .map(|r| r.map(|t| Self::Int128Parts(Box::new(t)))),
            ),
            TypeVariant::ScObject => Box::new(
                ReadXdrIter::<_, ScObject>::new(dec)
                    .map(|r| r.map(|t| Self::ScObject(Box::new(t)))),
            ),
            TypeVariant::StoredTransactionSet => Box::new(
                ReadXdrIter::<_, StoredTransactionSet>::new(dec)
                    .map(|r| r.map(|t| Self::StoredTransactionSet(Box::new(t)))),
            ),
            TypeVariant::PersistedScpStateV0 => Box::new(
                ReadXdrIter::<_, PersistedScpStateV0>::new(dec)
                    .map(|r| r.map(|t| Self::PersistedScpStateV0(Box::new(t)))),
            ),
            TypeVariant::PersistedScpStateV1 => Box::new(
                ReadXdrIter::<_, PersistedScpStateV1>::new(dec)
                    .map(|r| r.map(|t| Self::PersistedScpStateV1(Box::new(t)))),
            ),
            TypeVariant::PersistedScpState => Box::new(
                ReadXdrIter::<_, PersistedScpState>::new(dec)
                    .map(|r| r.map(|t| Self::PersistedScpState(Box::new(t)))),
            ),
            TypeVariant::Thresholds => Box::new(
                ReadXdrIter::<_, Thresholds>::new(dec)
                    .map(|r| r.map(|t| Self::Thresholds(Box::new(t)))),
            ),
            TypeVariant::String32 => Box::new(
                ReadXdrIter::<_, String32>::new(dec)
                    .map(|r| r.map(|t| Self::String32(Box::new(t)))),
            ),
            TypeVariant::String64 => Box::new(
                ReadXdrIter::<_, String64>::new(dec)
                    .map(|r| r.map(|t| Self::String64(Box::new(t)))),
            ),
            TypeVariant::SequenceNumber => Box::new(
                ReadXdrIter::<_, SequenceNumber>::new(dec)
                    .map(|r| r.map(|t| Self::SequenceNumber(Box::new(t)))),
            ),
            TypeVariant::TimePoint => Box::new(
                ReadXdrIter::<_, TimePoint>::new(dec)
                    .map(|r| r.map(|t| Self::TimePoint(Box::new(t)))),
            ),
            TypeVariant::Duration => Box::new(
                ReadXdrIter::<_, Duration>::new(dec)
                    .map(|r| r.map(|t| Self::Duration(Box::new(t)))),
            ),
            TypeVariant::DataValue => Box::new(
                ReadXdrIter::<_, DataValue>::new(dec)
                    .map(|r| r.map(|t| Self::DataValue(Box::new(t)))),
            ),
            TypeVariant::PoolId => Box::new(
                ReadXdrIter::<_, PoolId>::new(dec).map(|r| r.map(|t| Self::PoolId(Box::new(t)))),
            ),
            TypeVariant::AssetCode4 => Box::new(
                ReadXdrIter::<_, AssetCode4>::new(dec)
                    .map(|r| r.map(|t| Self::AssetCode4(Box::new(t)))),
            ),
            TypeVariant::AssetCode12 => Box::new(
                ReadXdrIter::<_, AssetCode12>::new(dec)
                    .map(|r| r.map(|t| Self::AssetCode12(Box::new(t)))),
            ),
            TypeVariant::AssetType => Box::new(
                ReadXdrIter::<_, AssetType>::new(dec)
                    .map(|r| r.map(|t| Self::AssetType(Box::new(t)))),
            ),
            TypeVariant::AssetCode => Box::new(
                ReadXdrIter::<_, AssetCode>::new(dec)
                    .map(|r| r.map(|t| Self::AssetCode(Box::new(t)))),
            ),
            TypeVariant::AlphaNum4 => Box::new(
                ReadXdrIter::<_, AlphaNum4>::new(dec)
                    .map(|r| r.map(|t| Self::AlphaNum4(Box::new(t)))),
            ),
            TypeVariant::AlphaNum12 => Box::new(
                ReadXdrIter::<_, AlphaNum12>::new(dec)
                    .map(|r| r.map(|t| Self::AlphaNum12(Box::new(t)))),
            ),
            TypeVariant::Asset => Box::new(
                ReadXdrIter::<_, Asset>::new(dec).map(|r| r.map(|t| Self::Asset(Box::new(t)))),
            ),
            TypeVariant::Price => Box::new(
                ReadXdrIter::<_, Price>::new(dec).map(|r| r.map(|t| Self::Price(Box::new(t)))),
            ),
            TypeVariant::Liabilities => Box::new(
                ReadXdrIter::<_, Liabilities>::new(dec)
                    .map(|r| r.map(|t| Self::Liabilities(Box::new(t)))),
            ),
            TypeVariant::ThresholdIndexes => Box::new(
                ReadXdrIter::<_, ThresholdIndexes>::new(dec)
                    .map(|r| r.map(|t| Self::ThresholdIndexes(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryType => Box::new(
                ReadXdrIter::<_, LedgerEntryType>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerEntryType(Box::new(t)))),
            ),
            TypeVariant::Signer => Box::new(
                ReadXdrIter::<_, Signer>::new(dec).map(|r| r.map(|t| Self::Signer(Box::new(t)))),
            ),
            TypeVariant::AccountFlags => Box::new(
                ReadXdrIter::<_, AccountFlags>::new(dec)
                    .map(|r| r.map(|t| Self::AccountFlags(Box::new(t)))),
            ),
            TypeVariant::SponsorshipDescriptor => Box::new(
                ReadXdrIter::<_, SponsorshipDescriptor>::new(dec)
                    .map(|r| r.map(|t| Self::SponsorshipDescriptor(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV3 => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV3>::new(dec)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV3(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV2 => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV2>::new(dec)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV2(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV2Ext => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV2Ext>::new(dec)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV2Ext(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV1 => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV1>::new(dec)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV1(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExtensionV1Ext => Box::new(
                ReadXdrIter::<_, AccountEntryExtensionV1Ext>::new(dec)
                    .map(|r| r.map(|t| Self::AccountEntryExtensionV1Ext(Box::new(t)))),
            ),
            TypeVariant::AccountEntry => Box::new(
                ReadXdrIter::<_, AccountEntry>::new(dec)
                    .map(|r| r.map(|t| Self::AccountEntry(Box::new(t)))),
            ),
            TypeVariant::AccountEntryExt => Box::new(
                ReadXdrIter::<_, AccountEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::AccountEntryExt(Box::new(t)))),
            ),
            TypeVariant::TrustLineFlags => Box::new(
                ReadXdrIter::<_, TrustLineFlags>::new(dec)
                    .map(|r| r.map(|t| Self::TrustLineFlags(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolType => Box::new(
                ReadXdrIter::<_, LiquidityPoolType>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolType(Box::new(t)))),
            ),
            TypeVariant::TrustLineAsset => Box::new(
                ReadXdrIter::<_, TrustLineAsset>::new(dec)
                    .map(|r| r.map(|t| Self::TrustLineAsset(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryExtensionV2 => Box::new(
                ReadXdrIter::<_, TrustLineEntryExtensionV2>::new(dec)
                    .map(|r| r.map(|t| Self::TrustLineEntryExtensionV2(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryExtensionV2Ext => Box::new(
                ReadXdrIter::<_, TrustLineEntryExtensionV2Ext>::new(dec)
                    .map(|r| r.map(|t| Self::TrustLineEntryExtensionV2Ext(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntry => Box::new(
                ReadXdrIter::<_, TrustLineEntry>::new(dec)
                    .map(|r| r.map(|t| Self::TrustLineEntry(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryExt => Box::new(
                ReadXdrIter::<_, TrustLineEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::TrustLineEntryExt(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryV1 => Box::new(
                ReadXdrIter::<_, TrustLineEntryV1>::new(dec)
                    .map(|r| r.map(|t| Self::TrustLineEntryV1(Box::new(t)))),
            ),
            TypeVariant::TrustLineEntryV1Ext => Box::new(
                ReadXdrIter::<_, TrustLineEntryV1Ext>::new(dec)
                    .map(|r| r.map(|t| Self::TrustLineEntryV1Ext(Box::new(t)))),
            ),
            TypeVariant::OfferEntryFlags => Box::new(
                ReadXdrIter::<_, OfferEntryFlags>::new(dec)
                    .map(|r| r.map(|t| Self::OfferEntryFlags(Box::new(t)))),
            ),
            TypeVariant::OfferEntry => Box::new(
                ReadXdrIter::<_, OfferEntry>::new(dec)
                    .map(|r| r.map(|t| Self::OfferEntry(Box::new(t)))),
            ),
            TypeVariant::OfferEntryExt => Box::new(
                ReadXdrIter::<_, OfferEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::OfferEntryExt(Box::new(t)))),
            ),
            TypeVariant::DataEntry => Box::new(
                ReadXdrIter::<_, DataEntry>::new(dec)
                    .map(|r| r.map(|t| Self::DataEntry(Box::new(t)))),
            ),
            TypeVariant::DataEntryExt => Box::new(
                ReadXdrIter::<_, DataEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::DataEntryExt(Box::new(t)))),
            ),
            TypeVariant::ClaimPredicateType => Box::new(
                ReadXdrIter::<_, ClaimPredicateType>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimPredicateType(Box::new(t)))),
            ),
            TypeVariant::ClaimPredicate => Box::new(
                ReadXdrIter::<_, ClaimPredicate>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimPredicate(Box::new(t)))),
            ),
            TypeVariant::ClaimantType => Box::new(
                ReadXdrIter::<_, ClaimantType>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimantType(Box::new(t)))),
            ),
            TypeVariant::Claimant => Box::new(
                ReadXdrIter::<_, Claimant>::new(dec)
                    .map(|r| r.map(|t| Self::Claimant(Box::new(t)))),
            ),
            TypeVariant::ClaimantV0 => Box::new(
                ReadXdrIter::<_, ClaimantV0>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimantV0(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceIdType => Box::new(
                ReadXdrIter::<_, ClaimableBalanceIdType>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimableBalanceIdType(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceId => Box::new(
                ReadXdrIter::<_, ClaimableBalanceId>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimableBalanceId(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceFlags => Box::new(
                ReadXdrIter::<_, ClaimableBalanceFlags>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimableBalanceFlags(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceEntryExtensionV1 => Box::new(
                ReadXdrIter::<_, ClaimableBalanceEntryExtensionV1>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntryExtensionV1(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceEntryExtensionV1Ext => Box::new(
                ReadXdrIter::<_, ClaimableBalanceEntryExtensionV1Ext>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntryExtensionV1Ext(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceEntry => Box::new(
                ReadXdrIter::<_, ClaimableBalanceEntry>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntry(Box::new(t)))),
            ),
            TypeVariant::ClaimableBalanceEntryExt => Box::new(
                ReadXdrIter::<_, ClaimableBalanceEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimableBalanceEntryExt(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolConstantProductParameters => Box::new(
                ReadXdrIter::<_, LiquidityPoolConstantProductParameters>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolConstantProductParameters(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolEntry => Box::new(
                ReadXdrIter::<_, LiquidityPoolEntry>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolEntry(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolEntryBody => Box::new(
                ReadXdrIter::<_, LiquidityPoolEntryBody>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolEntryBody(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolEntryConstantProduct => Box::new(
                ReadXdrIter::<_, LiquidityPoolEntryConstantProduct>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolEntryConstantProduct(Box::new(t)))),
            ),
            TypeVariant::ContractDataEntry => Box::new(
                ReadXdrIter::<_, ContractDataEntry>::new(dec)
                    .map(|r| r.map(|t| Self::ContractDataEntry(Box::new(t)))),
            ),
            TypeVariant::ContractCodeEntry => Box::new(
                ReadXdrIter::<_, ContractCodeEntry>::new(dec)
                    .map(|r| r.map(|t| Self::ContractCodeEntry(Box::new(t)))),
            ),
            TypeVariant::ConfigSettingType => Box::new(
                ReadXdrIter::<_, ConfigSettingType>::new(dec)
                    .map(|r| r.map(|t| Self::ConfigSettingType(Box::new(t)))),
            ),
            TypeVariant::ConfigSetting => Box::new(
                ReadXdrIter::<_, ConfigSetting>::new(dec)
                    .map(|r| r.map(|t| Self::ConfigSetting(Box::new(t)))),
            ),
            TypeVariant::ConfigSettingId => Box::new(
                ReadXdrIter::<_, ConfigSettingId>::new(dec)
                    .map(|r| r.map(|t| Self::ConfigSettingId(Box::new(t)))),
            ),
            TypeVariant::ConfigSettingEntry => Box::new(
                ReadXdrIter::<_, ConfigSettingEntry>::new(dec)
                    .map(|r| r.map(|t| Self::ConfigSettingEntry(Box::new(t)))),
            ),
            TypeVariant::ConfigSettingEntryExt => Box::new(
                ReadXdrIter::<_, ConfigSettingEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::ConfigSettingEntryExt(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryExtensionV1 => Box::new(
                ReadXdrIter::<_, LedgerEntryExtensionV1>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerEntryExtensionV1(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryExtensionV1Ext => Box::new(
                ReadXdrIter::<_, LedgerEntryExtensionV1Ext>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerEntryExtensionV1Ext(Box::new(t)))),
            ),
            TypeVariant::LedgerEntry => Box::new(
                ReadXdrIter::<_, LedgerEntry>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerEntry(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryData => Box::new(
                ReadXdrIter::<_, LedgerEntryData>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerEntryData(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryExt => Box::new(
                ReadXdrIter::<_, LedgerEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerEntryExt(Box::new(t)))),
            ),
            TypeVariant::LedgerKey => Box::new(
                ReadXdrIter::<_, LedgerKey>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKey(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyAccount => Box::new(
                ReadXdrIter::<_, LedgerKeyAccount>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKeyAccount(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyTrustLine => Box::new(
                ReadXdrIter::<_, LedgerKeyTrustLine>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKeyTrustLine(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyOffer => Box::new(
                ReadXdrIter::<_, LedgerKeyOffer>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKeyOffer(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyData => Box::new(
                ReadXdrIter::<_, LedgerKeyData>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKeyData(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyClaimableBalance => Box::new(
                ReadXdrIter::<_, LedgerKeyClaimableBalance>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKeyClaimableBalance(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyLiquidityPool => Box::new(
                ReadXdrIter::<_, LedgerKeyLiquidityPool>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKeyLiquidityPool(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyContractData => Box::new(
                ReadXdrIter::<_, LedgerKeyContractData>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKeyContractData(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyContractCode => Box::new(
                ReadXdrIter::<_, LedgerKeyContractCode>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKeyContractCode(Box::new(t)))),
            ),
            TypeVariant::LedgerKeyConfigSetting => Box::new(
                ReadXdrIter::<_, LedgerKeyConfigSetting>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerKeyConfigSetting(Box::new(t)))),
            ),
            TypeVariant::EnvelopeType => Box::new(
                ReadXdrIter::<_, EnvelopeType>::new(dec)
                    .map(|r| r.map(|t| Self::EnvelopeType(Box::new(t)))),
            ),
            TypeVariant::UpgradeType => Box::new(
                ReadXdrIter::<_, UpgradeType>::new(dec)
                    .map(|r| r.map(|t| Self::UpgradeType(Box::new(t)))),
            ),
            TypeVariant::StellarValueType => Box::new(
                ReadXdrIter::<_, StellarValueType>::new(dec)
                    .map(|r| r.map(|t| Self::StellarValueType(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseValueSignature => Box::new(
                ReadXdrIter::<_, LedgerCloseValueSignature>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerCloseValueSignature(Box::new(t)))),
            ),
            TypeVariant::StellarValue => Box::new(
                ReadXdrIter::<_, StellarValue>::new(dec)
                    .map(|r| r.map(|t| Self::StellarValue(Box::new(t)))),
            ),
            TypeVariant::StellarValueExt => Box::new(
                ReadXdrIter::<_, StellarValueExt>::new(dec)
                    .map(|r| r.map(|t| Self::StellarValueExt(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderFlags => Box::new(
                ReadXdrIter::<_, LedgerHeaderFlags>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerHeaderFlags(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderExtensionV1 => Box::new(
                ReadXdrIter::<_, LedgerHeaderExtensionV1>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerHeaderExtensionV1(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderExtensionV1Ext => Box::new(
                ReadXdrIter::<_, LedgerHeaderExtensionV1Ext>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerHeaderExtensionV1Ext(Box::new(t)))),
            ),
            TypeVariant::LedgerHeader => Box::new(
                ReadXdrIter::<_, LedgerHeader>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerHeader(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderExt => Box::new(
                ReadXdrIter::<_, LedgerHeaderExt>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerHeaderExt(Box::new(t)))),
            ),
            TypeVariant::LedgerUpgradeType => Box::new(
                ReadXdrIter::<_, LedgerUpgradeType>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerUpgradeType(Box::new(t)))),
            ),
            TypeVariant::LedgerUpgrade => Box::new(
                ReadXdrIter::<_, LedgerUpgrade>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerUpgrade(Box::new(t)))),
            ),
            TypeVariant::LedgerUpgradeConfigSetting => Box::new(
                ReadXdrIter::<_, LedgerUpgradeConfigSetting>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerUpgradeConfigSetting(Box::new(t)))),
            ),
            TypeVariant::BucketEntryType => Box::new(
                ReadXdrIter::<_, BucketEntryType>::new(dec)
                    .map(|r| r.map(|t| Self::BucketEntryType(Box::new(t)))),
            ),
            TypeVariant::BucketMetadata => Box::new(
                ReadXdrIter::<_, BucketMetadata>::new(dec)
                    .map(|r| r.map(|t| Self::BucketMetadata(Box::new(t)))),
            ),
            TypeVariant::BucketMetadataExt => Box::new(
                ReadXdrIter::<_, BucketMetadataExt>::new(dec)
                    .map(|r| r.map(|t| Self::BucketMetadataExt(Box::new(t)))),
            ),
            TypeVariant::BucketEntry => Box::new(
                ReadXdrIter::<_, BucketEntry>::new(dec)
                    .map(|r| r.map(|t| Self::BucketEntry(Box::new(t)))),
            ),
            TypeVariant::TxSetComponentType => Box::new(
                ReadXdrIter::<_, TxSetComponentType>::new(dec)
                    .map(|r| r.map(|t| Self::TxSetComponentType(Box::new(t)))),
            ),
            TypeVariant::TxSetComponent => Box::new(
                ReadXdrIter::<_, TxSetComponent>::new(dec)
                    .map(|r| r.map(|t| Self::TxSetComponent(Box::new(t)))),
            ),
            TypeVariant::TxSetComponentTxsMaybeDiscountedFee => Box::new(
                ReadXdrIter::<_, TxSetComponentTxsMaybeDiscountedFee>::new(dec)
                    .map(|r| r.map(|t| Self::TxSetComponentTxsMaybeDiscountedFee(Box::new(t)))),
            ),
            TypeVariant::TransactionPhase => Box::new(
                ReadXdrIter::<_, TransactionPhase>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionPhase(Box::new(t)))),
            ),
            TypeVariant::TransactionSet => Box::new(
                ReadXdrIter::<_, TransactionSet>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionSet(Box::new(t)))),
            ),
            TypeVariant::TransactionSetV1 => Box::new(
                ReadXdrIter::<_, TransactionSetV1>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionSetV1(Box::new(t)))),
            ),
            TypeVariant::GeneralizedTransactionSet => Box::new(
                ReadXdrIter::<_, GeneralizedTransactionSet>::new(dec)
                    .map(|r| r.map(|t| Self::GeneralizedTransactionSet(Box::new(t)))),
            ),
            TypeVariant::TransactionResultPair => Box::new(
                ReadXdrIter::<_, TransactionResultPair>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResultPair(Box::new(t)))),
            ),
            TypeVariant::TransactionResultSet => Box::new(
                ReadXdrIter::<_, TransactionResultSet>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResultSet(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryEntry => Box::new(
                ReadXdrIter::<_, TransactionHistoryEntry>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionHistoryEntry(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryEntryExt => Box::new(
                ReadXdrIter::<_, TransactionHistoryEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionHistoryEntryExt(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryResultEntry => Box::new(
                ReadXdrIter::<_, TransactionHistoryResultEntry>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntry(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryResultEntryExt => Box::new(
                ReadXdrIter::<_, TransactionHistoryResultEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntryExt(Box::new(t)))),
            ),
            TypeVariant::TransactionResultPairV2 => Box::new(
                ReadXdrIter::<_, TransactionResultPairV2>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResultPairV2(Box::new(t)))),
            ),
            TypeVariant::TransactionResultSetV2 => Box::new(
                ReadXdrIter::<_, TransactionResultSetV2>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResultSetV2(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryResultEntryV2 => Box::new(
                ReadXdrIter::<_, TransactionHistoryResultEntryV2>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntryV2(Box::new(t)))),
            ),
            TypeVariant::TransactionHistoryResultEntryV2Ext => Box::new(
                ReadXdrIter::<_, TransactionHistoryResultEntryV2Ext>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionHistoryResultEntryV2Ext(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderHistoryEntry => Box::new(
                ReadXdrIter::<_, LedgerHeaderHistoryEntry>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerHeaderHistoryEntry(Box::new(t)))),
            ),
            TypeVariant::LedgerHeaderHistoryEntryExt => Box::new(
                ReadXdrIter::<_, LedgerHeaderHistoryEntryExt>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerHeaderHistoryEntryExt(Box::new(t)))),
            ),
            TypeVariant::LedgerScpMessages => Box::new(
                ReadXdrIter::<_, LedgerScpMessages>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerScpMessages(Box::new(t)))),
            ),
            TypeVariant::ScpHistoryEntryV0 => Box::new(
                ReadXdrIter::<_, ScpHistoryEntryV0>::new(dec)
                    .map(|r| r.map(|t| Self::ScpHistoryEntryV0(Box::new(t)))),
            ),
            TypeVariant::ScpHistoryEntry => Box::new(
                ReadXdrIter::<_, ScpHistoryEntry>::new(dec)
                    .map(|r| r.map(|t| Self::ScpHistoryEntry(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryChangeType => Box::new(
                ReadXdrIter::<_, LedgerEntryChangeType>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerEntryChangeType(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryChange => Box::new(
                ReadXdrIter::<_, LedgerEntryChange>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerEntryChange(Box::new(t)))),
            ),
            TypeVariant::LedgerEntryChanges => Box::new(
                ReadXdrIter::<_, LedgerEntryChanges>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerEntryChanges(Box::new(t)))),
            ),
            TypeVariant::OperationMeta => Box::new(
                ReadXdrIter::<_, OperationMeta>::new(dec)
                    .map(|r| r.map(|t| Self::OperationMeta(Box::new(t)))),
            ),
            TypeVariant::TransactionMetaV1 => Box::new(
                ReadXdrIter::<_, TransactionMetaV1>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionMetaV1(Box::new(t)))),
            ),
            TypeVariant::TransactionMetaV2 => Box::new(
                ReadXdrIter::<_, TransactionMetaV2>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionMetaV2(Box::new(t)))),
            ),
            TypeVariant::ContractEventType => Box::new(
                ReadXdrIter::<_, ContractEventType>::new(dec)
                    .map(|r| r.map(|t| Self::ContractEventType(Box::new(t)))),
            ),
            TypeVariant::ContractEvent => Box::new(
                ReadXdrIter::<_, ContractEvent>::new(dec)
                    .map(|r| r.map(|t| Self::ContractEvent(Box::new(t)))),
            ),
            TypeVariant::ContractEventBody => Box::new(
                ReadXdrIter::<_, ContractEventBody>::new(dec)
                    .map(|r| r.map(|t| Self::ContractEventBody(Box::new(t)))),
            ),
            TypeVariant::ContractEventV0 => Box::new(
                ReadXdrIter::<_, ContractEventV0>::new(dec)
                    .map(|r| r.map(|t| Self::ContractEventV0(Box::new(t)))),
            ),
            TypeVariant::OperationEvents => Box::new(
                ReadXdrIter::<_, OperationEvents>::new(dec)
                    .map(|r| r.map(|t| Self::OperationEvents(Box::new(t)))),
            ),
            TypeVariant::TransactionMetaV3 => Box::new(
                ReadXdrIter::<_, TransactionMetaV3>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionMetaV3(Box::new(t)))),
            ),
            TypeVariant::TransactionMeta => Box::new(
                ReadXdrIter::<_, TransactionMeta>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionMeta(Box::new(t)))),
            ),
            TypeVariant::TransactionResultMeta => Box::new(
                ReadXdrIter::<_, TransactionResultMeta>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResultMeta(Box::new(t)))),
            ),
            TypeVariant::TransactionResultMetaV2 => Box::new(
                ReadXdrIter::<_, TransactionResultMetaV2>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResultMetaV2(Box::new(t)))),
            ),
            TypeVariant::UpgradeEntryMeta => Box::new(
                ReadXdrIter::<_, UpgradeEntryMeta>::new(dec)
                    .map(|r| r.map(|t| Self::UpgradeEntryMeta(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseMetaV0 => Box::new(
                ReadXdrIter::<_, LedgerCloseMetaV0>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerCloseMetaV0(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseMetaV1 => Box::new(
                ReadXdrIter::<_, LedgerCloseMetaV1>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerCloseMetaV1(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseMetaV2 => Box::new(
                ReadXdrIter::<_, LedgerCloseMetaV2>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerCloseMetaV2(Box::new(t)))),
            ),
            TypeVariant::LedgerCloseMeta => Box::new(
                ReadXdrIter::<_, LedgerCloseMeta>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerCloseMeta(Box::new(t)))),
            ),
            TypeVariant::ErrorCode => Box::new(
                ReadXdrIter::<_, ErrorCode>::new(dec)
                    .map(|r| r.map(|t| Self::ErrorCode(Box::new(t)))),
            ),
            TypeVariant::SError => Box::new(
                ReadXdrIter::<_, SError>::new(dec).map(|r| r.map(|t| Self::SError(Box::new(t)))),
            ),
            TypeVariant::SendMore => Box::new(
                ReadXdrIter::<_, SendMore>::new(dec)
                    .map(|r| r.map(|t| Self::SendMore(Box::new(t)))),
            ),
            TypeVariant::AuthCert => Box::new(
                ReadXdrIter::<_, AuthCert>::new(dec)
                    .map(|r| r.map(|t| Self::AuthCert(Box::new(t)))),
            ),
            TypeVariant::Hello => Box::new(
                ReadXdrIter::<_, Hello>::new(dec).map(|r| r.map(|t| Self::Hello(Box::new(t)))),
            ),
            TypeVariant::Auth => Box::new(
                ReadXdrIter::<_, Auth>::new(dec).map(|r| r.map(|t| Self::Auth(Box::new(t)))),
            ),
            TypeVariant::IpAddrType => Box::new(
                ReadXdrIter::<_, IpAddrType>::new(dec)
                    .map(|r| r.map(|t| Self::IpAddrType(Box::new(t)))),
            ),
            TypeVariant::PeerAddress => Box::new(
                ReadXdrIter::<_, PeerAddress>::new(dec)
                    .map(|r| r.map(|t| Self::PeerAddress(Box::new(t)))),
            ),
            TypeVariant::PeerAddressIp => Box::new(
                ReadXdrIter::<_, PeerAddressIp>::new(dec)
                    .map(|r| r.map(|t| Self::PeerAddressIp(Box::new(t)))),
            ),
            TypeVariant::MessageType => Box::new(
                ReadXdrIter::<_, MessageType>::new(dec)
                    .map(|r| r.map(|t| Self::MessageType(Box::new(t)))),
            ),
            TypeVariant::DontHave => Box::new(
                ReadXdrIter::<_, DontHave>::new(dec)
                    .map(|r| r.map(|t| Self::DontHave(Box::new(t)))),
            ),
            TypeVariant::SurveyMessageCommandType => Box::new(
                ReadXdrIter::<_, SurveyMessageCommandType>::new(dec)
                    .map(|r| r.map(|t| Self::SurveyMessageCommandType(Box::new(t)))),
            ),
            TypeVariant::SurveyRequestMessage => Box::new(
                ReadXdrIter::<_, SurveyRequestMessage>::new(dec)
                    .map(|r| r.map(|t| Self::SurveyRequestMessage(Box::new(t)))),
            ),
            TypeVariant::SignedSurveyRequestMessage => Box::new(
                ReadXdrIter::<_, SignedSurveyRequestMessage>::new(dec)
                    .map(|r| r.map(|t| Self::SignedSurveyRequestMessage(Box::new(t)))),
            ),
            TypeVariant::EncryptedBody => Box::new(
                ReadXdrIter::<_, EncryptedBody>::new(dec)
                    .map(|r| r.map(|t| Self::EncryptedBody(Box::new(t)))),
            ),
            TypeVariant::SurveyResponseMessage => Box::new(
                ReadXdrIter::<_, SurveyResponseMessage>::new(dec)
                    .map(|r| r.map(|t| Self::SurveyResponseMessage(Box::new(t)))),
            ),
            TypeVariant::SignedSurveyResponseMessage => Box::new(
                ReadXdrIter::<_, SignedSurveyResponseMessage>::new(dec)
                    .map(|r| r.map(|t| Self::SignedSurveyResponseMessage(Box::new(t)))),
            ),
            TypeVariant::PeerStats => Box::new(
                ReadXdrIter::<_, PeerStats>::new(dec)
                    .map(|r| r.map(|t| Self::PeerStats(Box::new(t)))),
            ),
            TypeVariant::PeerStatList => Box::new(
                ReadXdrIter::<_, PeerStatList>::new(dec)
                    .map(|r| r.map(|t| Self::PeerStatList(Box::new(t)))),
            ),
            TypeVariant::TopologyResponseBody => Box::new(
                ReadXdrIter::<_, TopologyResponseBody>::new(dec)
                    .map(|r| r.map(|t| Self::TopologyResponseBody(Box::new(t)))),
            ),
            TypeVariant::SurveyResponseBody => Box::new(
                ReadXdrIter::<_, SurveyResponseBody>::new(dec)
                    .map(|r| r.map(|t| Self::SurveyResponseBody(Box::new(t)))),
            ),
            TypeVariant::TxAdvertVector => Box::new(
                ReadXdrIter::<_, TxAdvertVector>::new(dec)
                    .map(|r| r.map(|t| Self::TxAdvertVector(Box::new(t)))),
            ),
            TypeVariant::FloodAdvert => Box::new(
                ReadXdrIter::<_, FloodAdvert>::new(dec)
                    .map(|r| r.map(|t| Self::FloodAdvert(Box::new(t)))),
            ),
            TypeVariant::TxDemandVector => Box::new(
                ReadXdrIter::<_, TxDemandVector>::new(dec)
                    .map(|r| r.map(|t| Self::TxDemandVector(Box::new(t)))),
            ),
            TypeVariant::FloodDemand => Box::new(
                ReadXdrIter::<_, FloodDemand>::new(dec)
                    .map(|r| r.map(|t| Self::FloodDemand(Box::new(t)))),
            ),
            TypeVariant::StellarMessage => Box::new(
                ReadXdrIter::<_, StellarMessage>::new(dec)
                    .map(|r| r.map(|t| Self::StellarMessage(Box::new(t)))),
            ),
            TypeVariant::AuthenticatedMessage => Box::new(
                ReadXdrIter::<_, AuthenticatedMessage>::new(dec)
                    .map(|r| r.map(|t| Self::AuthenticatedMessage(Box::new(t)))),
            ),
            TypeVariant::AuthenticatedMessageV0 => Box::new(
                ReadXdrIter::<_, AuthenticatedMessageV0>::new(dec)
                    .map(|r| r.map(|t| Self::AuthenticatedMessageV0(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolParameters => Box::new(
                ReadXdrIter::<_, LiquidityPoolParameters>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolParameters(Box::new(t)))),
            ),
            TypeVariant::MuxedAccount => Box::new(
                ReadXdrIter::<_, MuxedAccount>::new(dec)
                    .map(|r| r.map(|t| Self::MuxedAccount(Box::new(t)))),
            ),
            TypeVariant::MuxedAccountMed25519 => Box::new(
                ReadXdrIter::<_, MuxedAccountMed25519>::new(dec)
                    .map(|r| r.map(|t| Self::MuxedAccountMed25519(Box::new(t)))),
            ),
            TypeVariant::DecoratedSignature => Box::new(
                ReadXdrIter::<_, DecoratedSignature>::new(dec)
                    .map(|r| r.map(|t| Self::DecoratedSignature(Box::new(t)))),
            ),
            TypeVariant::LedgerFootprint => Box::new(
                ReadXdrIter::<_, LedgerFootprint>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerFootprint(Box::new(t)))),
            ),
            TypeVariant::OperationType => Box::new(
                ReadXdrIter::<_, OperationType>::new(dec)
                    .map(|r| r.map(|t| Self::OperationType(Box::new(t)))),
            ),
            TypeVariant::CreateAccountOp => Box::new(
                ReadXdrIter::<_, CreateAccountOp>::new(dec)
                    .map(|r| r.map(|t| Self::CreateAccountOp(Box::new(t)))),
            ),
            TypeVariant::PaymentOp => Box::new(
                ReadXdrIter::<_, PaymentOp>::new(dec)
                    .map(|r| r.map(|t| Self::PaymentOp(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictReceiveOp => Box::new(
                ReadXdrIter::<_, PathPaymentStrictReceiveOp>::new(dec)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveOp(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictSendOp => Box::new(
                ReadXdrIter::<_, PathPaymentStrictSendOp>::new(dec)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendOp(Box::new(t)))),
            ),
            TypeVariant::ManageSellOfferOp => Box::new(
                ReadXdrIter::<_, ManageSellOfferOp>::new(dec)
                    .map(|r| r.map(|t| Self::ManageSellOfferOp(Box::new(t)))),
            ),
            TypeVariant::ManageBuyOfferOp => Box::new(
                ReadXdrIter::<_, ManageBuyOfferOp>::new(dec)
                    .map(|r| r.map(|t| Self::ManageBuyOfferOp(Box::new(t)))),
            ),
            TypeVariant::CreatePassiveSellOfferOp => Box::new(
                ReadXdrIter::<_, CreatePassiveSellOfferOp>::new(dec)
                    .map(|r| r.map(|t| Self::CreatePassiveSellOfferOp(Box::new(t)))),
            ),
            TypeVariant::SetOptionsOp => Box::new(
                ReadXdrIter::<_, SetOptionsOp>::new(dec)
                    .map(|r| r.map(|t| Self::SetOptionsOp(Box::new(t)))),
            ),
            TypeVariant::ChangeTrustAsset => Box::new(
                ReadXdrIter::<_, ChangeTrustAsset>::new(dec)
                    .map(|r| r.map(|t| Self::ChangeTrustAsset(Box::new(t)))),
            ),
            TypeVariant::ChangeTrustOp => Box::new(
                ReadXdrIter::<_, ChangeTrustOp>::new(dec)
                    .map(|r| r.map(|t| Self::ChangeTrustOp(Box::new(t)))),
            ),
            TypeVariant::AllowTrustOp => Box::new(
                ReadXdrIter::<_, AllowTrustOp>::new(dec)
                    .map(|r| r.map(|t| Self::AllowTrustOp(Box::new(t)))),
            ),
            TypeVariant::ManageDataOp => Box::new(
                ReadXdrIter::<_, ManageDataOp>::new(dec)
                    .map(|r| r.map(|t| Self::ManageDataOp(Box::new(t)))),
            ),
            TypeVariant::BumpSequenceOp => Box::new(
                ReadXdrIter::<_, BumpSequenceOp>::new(dec)
                    .map(|r| r.map(|t| Self::BumpSequenceOp(Box::new(t)))),
            ),
            TypeVariant::CreateClaimableBalanceOp => Box::new(
                ReadXdrIter::<_, CreateClaimableBalanceOp>::new(dec)
                    .map(|r| r.map(|t| Self::CreateClaimableBalanceOp(Box::new(t)))),
            ),
            TypeVariant::ClaimClaimableBalanceOp => Box::new(
                ReadXdrIter::<_, ClaimClaimableBalanceOp>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimClaimableBalanceOp(Box::new(t)))),
            ),
            TypeVariant::BeginSponsoringFutureReservesOp => Box::new(
                ReadXdrIter::<_, BeginSponsoringFutureReservesOp>::new(dec)
                    .map(|r| r.map(|t| Self::BeginSponsoringFutureReservesOp(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipType => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipType>::new(dec)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipType(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipOp => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipOp>::new(dec)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipOp(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipOpSigner => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipOpSigner>::new(dec)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipOpSigner(Box::new(t)))),
            ),
            TypeVariant::ClawbackOp => Box::new(
                ReadXdrIter::<_, ClawbackOp>::new(dec)
                    .map(|r| r.map(|t| Self::ClawbackOp(Box::new(t)))),
            ),
            TypeVariant::ClawbackClaimableBalanceOp => Box::new(
                ReadXdrIter::<_, ClawbackClaimableBalanceOp>::new(dec)
                    .map(|r| r.map(|t| Self::ClawbackClaimableBalanceOp(Box::new(t)))),
            ),
            TypeVariant::SetTrustLineFlagsOp => Box::new(
                ReadXdrIter::<_, SetTrustLineFlagsOp>::new(dec)
                    .map(|r| r.map(|t| Self::SetTrustLineFlagsOp(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolDepositOp => Box::new(
                ReadXdrIter::<_, LiquidityPoolDepositOp>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolDepositOp(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolWithdrawOp => Box::new(
                ReadXdrIter::<_, LiquidityPoolWithdrawOp>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolWithdrawOp(Box::new(t)))),
            ),
            TypeVariant::HostFunctionType => Box::new(
                ReadXdrIter::<_, HostFunctionType>::new(dec)
                    .map(|r| r.map(|t| Self::HostFunctionType(Box::new(t)))),
            ),
            TypeVariant::ContractIdType => Box::new(
                ReadXdrIter::<_, ContractIdType>::new(dec)
                    .map(|r| r.map(|t| Self::ContractIdType(Box::new(t)))),
            ),
            TypeVariant::ContractIdPublicKeyType => Box::new(
                ReadXdrIter::<_, ContractIdPublicKeyType>::new(dec)
                    .map(|r| r.map(|t| Self::ContractIdPublicKeyType(Box::new(t)))),
            ),
            TypeVariant::InstallContractCodeArgs => Box::new(
                ReadXdrIter::<_, InstallContractCodeArgs>::new(dec)
                    .map(|r| r.map(|t| Self::InstallContractCodeArgs(Box::new(t)))),
            ),
            TypeVariant::ContractId => Box::new(
                ReadXdrIter::<_, ContractId>::new(dec)
                    .map(|r| r.map(|t| Self::ContractId(Box::new(t)))),
            ),
            TypeVariant::ContractIdFromEd25519PublicKey => Box::new(
                ReadXdrIter::<_, ContractIdFromEd25519PublicKey>::new(dec)
                    .map(|r| r.map(|t| Self::ContractIdFromEd25519PublicKey(Box::new(t)))),
            ),
            TypeVariant::CreateContractArgs => Box::new(
                ReadXdrIter::<_, CreateContractArgs>::new(dec)
                    .map(|r| r.map(|t| Self::CreateContractArgs(Box::new(t)))),
            ),
            TypeVariant::HostFunction => Box::new(
                ReadXdrIter::<_, HostFunction>::new(dec)
                    .map(|r| r.map(|t| Self::HostFunction(Box::new(t)))),
            ),
            TypeVariant::InvokeHostFunctionOp => Box::new(
                ReadXdrIter::<_, InvokeHostFunctionOp>::new(dec)
                    .map(|r| r.map(|t| Self::InvokeHostFunctionOp(Box::new(t)))),
            ),
            TypeVariant::Operation => Box::new(
                ReadXdrIter::<_, Operation>::new(dec)
                    .map(|r| r.map(|t| Self::Operation(Box::new(t)))),
            ),
            TypeVariant::OperationBody => Box::new(
                ReadXdrIter::<_, OperationBody>::new(dec)
                    .map(|r| r.map(|t| Self::OperationBody(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimage => Box::new(
                ReadXdrIter::<_, HashIdPreimage>::new(dec)
                    .map(|r| r.map(|t| Self::HashIdPreimage(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageOperationId => Box::new(
                ReadXdrIter::<_, HashIdPreimageOperationId>::new(dec)
                    .map(|r| r.map(|t| Self::HashIdPreimageOperationId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageRevokeId => Box::new(
                ReadXdrIter::<_, HashIdPreimageRevokeId>::new(dec)
                    .map(|r| r.map(|t| Self::HashIdPreimageRevokeId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageEd25519ContractId => Box::new(
                ReadXdrIter::<_, HashIdPreimageEd25519ContractId>::new(dec)
                    .map(|r| r.map(|t| Self::HashIdPreimageEd25519ContractId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageContractId => Box::new(
                ReadXdrIter::<_, HashIdPreimageContractId>::new(dec)
                    .map(|r| r.map(|t| Self::HashIdPreimageContractId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageFromAsset => Box::new(
                ReadXdrIter::<_, HashIdPreimageFromAsset>::new(dec)
                    .map(|r| r.map(|t| Self::HashIdPreimageFromAsset(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageSourceAccountContractId => Box::new(
                ReadXdrIter::<_, HashIdPreimageSourceAccountContractId>::new(dec)
                    .map(|r| r.map(|t| Self::HashIdPreimageSourceAccountContractId(Box::new(t)))),
            ),
            TypeVariant::HashIdPreimageCreateContractArgs => Box::new(
                ReadXdrIter::<_, HashIdPreimageCreateContractArgs>::new(dec)
                    .map(|r| r.map(|t| Self::HashIdPreimageCreateContractArgs(Box::new(t)))),
            ),
            TypeVariant::MemoType => Box::new(
                ReadXdrIter::<_, MemoType>::new(dec)
                    .map(|r| r.map(|t| Self::MemoType(Box::new(t)))),
            ),
            TypeVariant::Memo => Box::new(
                ReadXdrIter::<_, Memo>::new(dec).map(|r| r.map(|t| Self::Memo(Box::new(t)))),
            ),
            TypeVariant::TimeBounds => Box::new(
                ReadXdrIter::<_, TimeBounds>::new(dec)
                    .map(|r| r.map(|t| Self::TimeBounds(Box::new(t)))),
            ),
            TypeVariant::LedgerBounds => Box::new(
                ReadXdrIter::<_, LedgerBounds>::new(dec)
                    .map(|r| r.map(|t| Self::LedgerBounds(Box::new(t)))),
            ),
            TypeVariant::PreconditionsV2 => Box::new(
                ReadXdrIter::<_, PreconditionsV2>::new(dec)
                    .map(|r| r.map(|t| Self::PreconditionsV2(Box::new(t)))),
            ),
            TypeVariant::PreconditionType => Box::new(
                ReadXdrIter::<_, PreconditionType>::new(dec)
                    .map(|r| r.map(|t| Self::PreconditionType(Box::new(t)))),
            ),
            TypeVariant::Preconditions => Box::new(
                ReadXdrIter::<_, Preconditions>::new(dec)
                    .map(|r| r.map(|t| Self::Preconditions(Box::new(t)))),
            ),
            TypeVariant::TransactionV0 => Box::new(
                ReadXdrIter::<_, TransactionV0>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionV0(Box::new(t)))),
            ),
            TypeVariant::TransactionV0Ext => Box::new(
                ReadXdrIter::<_, TransactionV0Ext>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionV0Ext(Box::new(t)))),
            ),
            TypeVariant::TransactionV0Envelope => Box::new(
                ReadXdrIter::<_, TransactionV0Envelope>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionV0Envelope(Box::new(t)))),
            ),
            TypeVariant::Transaction => Box::new(
                ReadXdrIter::<_, Transaction>::new(dec)
                    .map(|r| r.map(|t| Self::Transaction(Box::new(t)))),
            ),
            TypeVariant::TransactionExt => Box::new(
                ReadXdrIter::<_, TransactionExt>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionExt(Box::new(t)))),
            ),
            TypeVariant::TransactionV1Envelope => Box::new(
                ReadXdrIter::<_, TransactionV1Envelope>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionV1Envelope(Box::new(t)))),
            ),
            TypeVariant::FeeBumpTransaction => Box::new(
                ReadXdrIter::<_, FeeBumpTransaction>::new(dec)
                    .map(|r| r.map(|t| Self::FeeBumpTransaction(Box::new(t)))),
            ),
            TypeVariant::FeeBumpTransactionInnerTx => Box::new(
                ReadXdrIter::<_, FeeBumpTransactionInnerTx>::new(dec)
                    .map(|r| r.map(|t| Self::FeeBumpTransactionInnerTx(Box::new(t)))),
            ),
            TypeVariant::FeeBumpTransactionExt => Box::new(
                ReadXdrIter::<_, FeeBumpTransactionExt>::new(dec)
                    .map(|r| r.map(|t| Self::FeeBumpTransactionExt(Box::new(t)))),
            ),
            TypeVariant::FeeBumpTransactionEnvelope => Box::new(
                ReadXdrIter::<_, FeeBumpTransactionEnvelope>::new(dec)
                    .map(|r| r.map(|t| Self::FeeBumpTransactionEnvelope(Box::new(t)))),
            ),
            TypeVariant::TransactionEnvelope => Box::new(
                ReadXdrIter::<_, TransactionEnvelope>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionEnvelope(Box::new(t)))),
            ),
            TypeVariant::TransactionSignaturePayload => Box::new(
                ReadXdrIter::<_, TransactionSignaturePayload>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionSignaturePayload(Box::new(t)))),
            ),
            TypeVariant::TransactionSignaturePayloadTaggedTransaction => Box::new(
                ReadXdrIter::<_, TransactionSignaturePayloadTaggedTransaction>::new(dec).map(|r| {
                    r.map(|t| Self::TransactionSignaturePayloadTaggedTransaction(Box::new(t)))
                }),
            ),
            TypeVariant::ClaimAtomType => Box::new(
                ReadXdrIter::<_, ClaimAtomType>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimAtomType(Box::new(t)))),
            ),
            TypeVariant::ClaimOfferAtomV0 => Box::new(
                ReadXdrIter::<_, ClaimOfferAtomV0>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimOfferAtomV0(Box::new(t)))),
            ),
            TypeVariant::ClaimOfferAtom => Box::new(
                ReadXdrIter::<_, ClaimOfferAtom>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimOfferAtom(Box::new(t)))),
            ),
            TypeVariant::ClaimLiquidityAtom => Box::new(
                ReadXdrIter::<_, ClaimLiquidityAtom>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimLiquidityAtom(Box::new(t)))),
            ),
            TypeVariant::ClaimAtom => Box::new(
                ReadXdrIter::<_, ClaimAtom>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimAtom(Box::new(t)))),
            ),
            TypeVariant::CreateAccountResultCode => Box::new(
                ReadXdrIter::<_, CreateAccountResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::CreateAccountResultCode(Box::new(t)))),
            ),
            TypeVariant::CreateAccountResult => Box::new(
                ReadXdrIter::<_, CreateAccountResult>::new(dec)
                    .map(|r| r.map(|t| Self::CreateAccountResult(Box::new(t)))),
            ),
            TypeVariant::PaymentResultCode => Box::new(
                ReadXdrIter::<_, PaymentResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::PaymentResultCode(Box::new(t)))),
            ),
            TypeVariant::PaymentResult => Box::new(
                ReadXdrIter::<_, PaymentResult>::new(dec)
                    .map(|r| r.map(|t| Self::PaymentResult(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictReceiveResultCode => Box::new(
                ReadXdrIter::<_, PathPaymentStrictReceiveResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveResultCode(Box::new(t)))),
            ),
            TypeVariant::SimplePaymentResult => Box::new(
                ReadXdrIter::<_, SimplePaymentResult>::new(dec)
                    .map(|r| r.map(|t| Self::SimplePaymentResult(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictReceiveResult => Box::new(
                ReadXdrIter::<_, PathPaymentStrictReceiveResult>::new(dec)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveResult(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictReceiveResultSuccess => Box::new(
                ReadXdrIter::<_, PathPaymentStrictReceiveResultSuccess>::new(dec)
                    .map(|r| r.map(|t| Self::PathPaymentStrictReceiveResultSuccess(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictSendResultCode => Box::new(
                ReadXdrIter::<_, PathPaymentStrictSendResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendResultCode(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictSendResult => Box::new(
                ReadXdrIter::<_, PathPaymentStrictSendResult>::new(dec)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendResult(Box::new(t)))),
            ),
            TypeVariant::PathPaymentStrictSendResultSuccess => Box::new(
                ReadXdrIter::<_, PathPaymentStrictSendResultSuccess>::new(dec)
                    .map(|r| r.map(|t| Self::PathPaymentStrictSendResultSuccess(Box::new(t)))),
            ),
            TypeVariant::ManageSellOfferResultCode => Box::new(
                ReadXdrIter::<_, ManageSellOfferResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::ManageSellOfferResultCode(Box::new(t)))),
            ),
            TypeVariant::ManageOfferEffect => Box::new(
                ReadXdrIter::<_, ManageOfferEffect>::new(dec)
                    .map(|r| r.map(|t| Self::ManageOfferEffect(Box::new(t)))),
            ),
            TypeVariant::ManageOfferSuccessResult => Box::new(
                ReadXdrIter::<_, ManageOfferSuccessResult>::new(dec)
                    .map(|r| r.map(|t| Self::ManageOfferSuccessResult(Box::new(t)))),
            ),
            TypeVariant::ManageOfferSuccessResultOffer => Box::new(
                ReadXdrIter::<_, ManageOfferSuccessResultOffer>::new(dec)
                    .map(|r| r.map(|t| Self::ManageOfferSuccessResultOffer(Box::new(t)))),
            ),
            TypeVariant::ManageSellOfferResult => Box::new(
                ReadXdrIter::<_, ManageSellOfferResult>::new(dec)
                    .map(|r| r.map(|t| Self::ManageSellOfferResult(Box::new(t)))),
            ),
            TypeVariant::ManageBuyOfferResultCode => Box::new(
                ReadXdrIter::<_, ManageBuyOfferResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::ManageBuyOfferResultCode(Box::new(t)))),
            ),
            TypeVariant::ManageBuyOfferResult => Box::new(
                ReadXdrIter::<_, ManageBuyOfferResult>::new(dec)
                    .map(|r| r.map(|t| Self::ManageBuyOfferResult(Box::new(t)))),
            ),
            TypeVariant::SetOptionsResultCode => Box::new(
                ReadXdrIter::<_, SetOptionsResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::SetOptionsResultCode(Box::new(t)))),
            ),
            TypeVariant::SetOptionsResult => Box::new(
                ReadXdrIter::<_, SetOptionsResult>::new(dec)
                    .map(|r| r.map(|t| Self::SetOptionsResult(Box::new(t)))),
            ),
            TypeVariant::ChangeTrustResultCode => Box::new(
                ReadXdrIter::<_, ChangeTrustResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::ChangeTrustResultCode(Box::new(t)))),
            ),
            TypeVariant::ChangeTrustResult => Box::new(
                ReadXdrIter::<_, ChangeTrustResult>::new(dec)
                    .map(|r| r.map(|t| Self::ChangeTrustResult(Box::new(t)))),
            ),
            TypeVariant::AllowTrustResultCode => Box::new(
                ReadXdrIter::<_, AllowTrustResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::AllowTrustResultCode(Box::new(t)))),
            ),
            TypeVariant::AllowTrustResult => Box::new(
                ReadXdrIter::<_, AllowTrustResult>::new(dec)
                    .map(|r| r.map(|t| Self::AllowTrustResult(Box::new(t)))),
            ),
            TypeVariant::AccountMergeResultCode => Box::new(
                ReadXdrIter::<_, AccountMergeResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::AccountMergeResultCode(Box::new(t)))),
            ),
            TypeVariant::AccountMergeResult => Box::new(
                ReadXdrIter::<_, AccountMergeResult>::new(dec)
                    .map(|r| r.map(|t| Self::AccountMergeResult(Box::new(t)))),
            ),
            TypeVariant::InflationResultCode => Box::new(
                ReadXdrIter::<_, InflationResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::InflationResultCode(Box::new(t)))),
            ),
            TypeVariant::InflationPayout => Box::new(
                ReadXdrIter::<_, InflationPayout>::new(dec)
                    .map(|r| r.map(|t| Self::InflationPayout(Box::new(t)))),
            ),
            TypeVariant::InflationResult => Box::new(
                ReadXdrIter::<_, InflationResult>::new(dec)
                    .map(|r| r.map(|t| Self::InflationResult(Box::new(t)))),
            ),
            TypeVariant::ManageDataResultCode => Box::new(
                ReadXdrIter::<_, ManageDataResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::ManageDataResultCode(Box::new(t)))),
            ),
            TypeVariant::ManageDataResult => Box::new(
                ReadXdrIter::<_, ManageDataResult>::new(dec)
                    .map(|r| r.map(|t| Self::ManageDataResult(Box::new(t)))),
            ),
            TypeVariant::BumpSequenceResultCode => Box::new(
                ReadXdrIter::<_, BumpSequenceResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::BumpSequenceResultCode(Box::new(t)))),
            ),
            TypeVariant::BumpSequenceResult => Box::new(
                ReadXdrIter::<_, BumpSequenceResult>::new(dec)
                    .map(|r| r.map(|t| Self::BumpSequenceResult(Box::new(t)))),
            ),
            TypeVariant::CreateClaimableBalanceResultCode => Box::new(
                ReadXdrIter::<_, CreateClaimableBalanceResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::CreateClaimableBalanceResultCode(Box::new(t)))),
            ),
            TypeVariant::CreateClaimableBalanceResult => Box::new(
                ReadXdrIter::<_, CreateClaimableBalanceResult>::new(dec)
                    .map(|r| r.map(|t| Self::CreateClaimableBalanceResult(Box::new(t)))),
            ),
            TypeVariant::ClaimClaimableBalanceResultCode => Box::new(
                ReadXdrIter::<_, ClaimClaimableBalanceResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimClaimableBalanceResultCode(Box::new(t)))),
            ),
            TypeVariant::ClaimClaimableBalanceResult => Box::new(
                ReadXdrIter::<_, ClaimClaimableBalanceResult>::new(dec)
                    .map(|r| r.map(|t| Self::ClaimClaimableBalanceResult(Box::new(t)))),
            ),
            TypeVariant::BeginSponsoringFutureReservesResultCode => Box::new(
                ReadXdrIter::<_, BeginSponsoringFutureReservesResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::BeginSponsoringFutureReservesResultCode(Box::new(t)))),
            ),
            TypeVariant::BeginSponsoringFutureReservesResult => Box::new(
                ReadXdrIter::<_, BeginSponsoringFutureReservesResult>::new(dec)
                    .map(|r| r.map(|t| Self::BeginSponsoringFutureReservesResult(Box::new(t)))),
            ),
            TypeVariant::EndSponsoringFutureReservesResultCode => Box::new(
                ReadXdrIter::<_, EndSponsoringFutureReservesResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::EndSponsoringFutureReservesResultCode(Box::new(t)))),
            ),
            TypeVariant::EndSponsoringFutureReservesResult => Box::new(
                ReadXdrIter::<_, EndSponsoringFutureReservesResult>::new(dec)
                    .map(|r| r.map(|t| Self::EndSponsoringFutureReservesResult(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipResultCode => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipResultCode(Box::new(t)))),
            ),
            TypeVariant::RevokeSponsorshipResult => Box::new(
                ReadXdrIter::<_, RevokeSponsorshipResult>::new(dec)
                    .map(|r| r.map(|t| Self::RevokeSponsorshipResult(Box::new(t)))),
            ),
            TypeVariant::ClawbackResultCode => Box::new(
                ReadXdrIter::<_, ClawbackResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::ClawbackResultCode(Box::new(t)))),
            ),
            TypeVariant::ClawbackResult => Box::new(
                ReadXdrIter::<_, ClawbackResult>::new(dec)
                    .map(|r| r.map(|t| Self::ClawbackResult(Box::new(t)))),
            ),
            TypeVariant::ClawbackClaimableBalanceResultCode => Box::new(
                ReadXdrIter::<_, ClawbackClaimableBalanceResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::ClawbackClaimableBalanceResultCode(Box::new(t)))),
            ),
            TypeVariant::ClawbackClaimableBalanceResult => Box::new(
                ReadXdrIter::<_, ClawbackClaimableBalanceResult>::new(dec)
                    .map(|r| r.map(|t| Self::ClawbackClaimableBalanceResult(Box::new(t)))),
            ),
            TypeVariant::SetTrustLineFlagsResultCode => Box::new(
                ReadXdrIter::<_, SetTrustLineFlagsResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::SetTrustLineFlagsResultCode(Box::new(t)))),
            ),
            TypeVariant::SetTrustLineFlagsResult => Box::new(
                ReadXdrIter::<_, SetTrustLineFlagsResult>::new(dec)
                    .map(|r| r.map(|t| Self::SetTrustLineFlagsResult(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolDepositResultCode => Box::new(
                ReadXdrIter::<_, LiquidityPoolDepositResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolDepositResultCode(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolDepositResult => Box::new(
                ReadXdrIter::<_, LiquidityPoolDepositResult>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolDepositResult(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolWithdrawResultCode => Box::new(
                ReadXdrIter::<_, LiquidityPoolWithdrawResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolWithdrawResultCode(Box::new(t)))),
            ),
            TypeVariant::LiquidityPoolWithdrawResult => Box::new(
                ReadXdrIter::<_, LiquidityPoolWithdrawResult>::new(dec)
                    .map(|r| r.map(|t| Self::LiquidityPoolWithdrawResult(Box::new(t)))),
            ),
            TypeVariant::InvokeHostFunctionResultCode => Box::new(
                ReadXdrIter::<_, InvokeHostFunctionResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::InvokeHostFunctionResultCode(Box::new(t)))),
            ),
            TypeVariant::InvokeHostFunctionResult => Box::new(
                ReadXdrIter::<_, InvokeHostFunctionResult>::new(dec)
                    .map(|r| r.map(|t| Self::InvokeHostFunctionResult(Box::new(t)))),
            ),
            TypeVariant::OperationResultCode => Box::new(
                ReadXdrIter::<_, OperationResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::OperationResultCode(Box::new(t)))),
            ),
            TypeVariant::OperationResult => Box::new(
                ReadXdrIter::<_, OperationResult>::new(dec)
                    .map(|r| r.map(|t| Self::OperationResult(Box::new(t)))),
            ),
            TypeVariant::OperationResultTr => Box::new(
                ReadXdrIter::<_, OperationResultTr>::new(dec)
                    .map(|r| r.map(|t| Self::OperationResultTr(Box::new(t)))),
            ),
            TypeVariant::TransactionResultCode => Box::new(
                ReadXdrIter::<_, TransactionResultCode>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResultCode(Box::new(t)))),
            ),
            TypeVariant::InnerTransactionResult => Box::new(
                ReadXdrIter::<_, InnerTransactionResult>::new(dec)
                    .map(|r| r.map(|t| Self::InnerTransactionResult(Box::new(t)))),
            ),
            TypeVariant::InnerTransactionResultResult => Box::new(
                ReadXdrIter::<_, InnerTransactionResultResult>::new(dec)
                    .map(|r| r.map(|t| Self::InnerTransactionResultResult(Box::new(t)))),
            ),
            TypeVariant::InnerTransactionResultExt => Box::new(
                ReadXdrIter::<_, InnerTransactionResultExt>::new(dec)
                    .map(|r| r.map(|t| Self::InnerTransactionResultExt(Box::new(t)))),
            ),
            TypeVariant::InnerTransactionResultPair => Box::new(
                ReadXdrIter::<_, InnerTransactionResultPair>::new(dec)
                    .map(|r| r.map(|t| Self::InnerTransactionResultPair(Box::new(t)))),
            ),
            TypeVariant::TransactionResult => Box::new(
                ReadXdrIter::<_, TransactionResult>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResult(Box::new(t)))),
            ),
            TypeVariant::TransactionResultResult => Box::new(
                ReadXdrIter::<_, TransactionResultResult>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResultResult(Box::new(t)))),
            ),
            TypeVariant::TransactionResultExt => Box::new(
                ReadXdrIter::<_, TransactionResultExt>::new(dec)
                    .map(|r| r.map(|t| Self::TransactionResultExt(Box::new(t)))),
            ),
            TypeVariant::Hash => Box::new(
                ReadXdrIter::<_, Hash>::new(dec).map(|r| r.map(|t| Self::Hash(Box::new(t)))),
            ),
            TypeVariant::Uint256 => Box::new(
                ReadXdrIter::<_, Uint256>::new(dec).map(|r| r.map(|t| Self::Uint256(Box::new(t)))),
            ),
            TypeVariant::Uint32 => Box::new(
                ReadXdrIter::<_, Uint32>::new(dec).map(|r| r.map(|t| Self::Uint32(Box::new(t)))),
            ),
            TypeVariant::Int32 => Box::new(
                ReadXdrIter::<_, Int32>::new(dec).map(|r| r.map(|t| Self::Int32(Box::new(t)))),
            ),
            TypeVariant::Uint64 => Box::new(
                ReadXdrIter::<_, Uint64>::new(dec).map(|r| r.map(|t| Self::Uint64(Box::new(t)))),
            ),
            TypeVariant::Int64 => Box::new(
                ReadXdrIter::<_, Int64>::new(dec).map(|r| r.map(|t| Self::Int64(Box::new(t)))),
            ),
            TypeVariant::ExtensionPoint => Box::new(
                ReadXdrIter::<_, ExtensionPoint>::new(dec)
                    .map(|r| r.map(|t| Self::ExtensionPoint(Box::new(t)))),
            ),
            TypeVariant::CryptoKeyType => Box::new(
                ReadXdrIter::<_, CryptoKeyType>::new(dec)
                    .map(|r| r.map(|t| Self::CryptoKeyType(Box::new(t)))),
            ),
            TypeVariant::PublicKeyType => Box::new(
                ReadXdrIter::<_, PublicKeyType>::new(dec)
                    .map(|r| r.map(|t| Self::PublicKeyType(Box::new(t)))),
            ),
            TypeVariant::SignerKeyType => Box::new(
                ReadXdrIter::<_, SignerKeyType>::new(dec)
                    .map(|r| r.map(|t| Self::SignerKeyType(Box::new(t)))),
            ),
            TypeVariant::PublicKey => Box::new(
                ReadXdrIter::<_, PublicKey>::new(dec)
                    .map(|r| r.map(|t| Self::PublicKey(Box::new(t)))),
            ),
            TypeVariant::SignerKey => Box::new(
                ReadXdrIter::<_, SignerKey>::new(dec)
                    .map(|r| r.map(|t| Self::SignerKey(Box::new(t)))),
            ),
            TypeVariant::SignerKeyEd25519SignedPayload => Box::new(
                ReadXdrIter::<_, SignerKeyEd25519SignedPayload>::new(dec)
                    .map(|r| r.map(|t| Self::SignerKeyEd25519SignedPayload(Box::new(t)))),
            ),
            TypeVariant::Signature => Box::new(
                ReadXdrIter::<_, Signature>::new(dec)
                    .map(|r| r.map(|t| Self::Signature(Box::new(t)))),
            ),
            TypeVariant::SignatureHint => Box::new(
                ReadXdrIter::<_, SignatureHint>::new(dec)
                    .map(|r| r.map(|t| Self::SignatureHint(Box::new(t)))),
            ),
            TypeVariant::NodeId => Box::new(
                ReadXdrIter::<_, NodeId>::new(dec).map(|r| r.map(|t| Self::NodeId(Box::new(t)))),
            ),
            TypeVariant::AccountId => Box::new(
                ReadXdrIter::<_, AccountId>::new(dec)
                    .map(|r| r.map(|t| Self::AccountId(Box::new(t)))),
            ),
            TypeVariant::Curve25519Secret => Box::new(
                ReadXdrIter::<_, Curve25519Secret>::new(dec)
                    .map(|r| r.map(|t| Self::Curve25519Secret(Box::new(t)))),
            ),
            TypeVariant::Curve25519Public => Box::new(
                ReadXdrIter::<_, Curve25519Public>::new(dec)
                    .map(|r| r.map(|t| Self::Curve25519Public(Box::new(t)))),
            ),
            TypeVariant::HmacSha256Key => Box::new(
                ReadXdrIter::<_, HmacSha256Key>::new(dec)
                    .map(|r| r.map(|t| Self::HmacSha256Key(Box::new(t)))),
            ),
            TypeVariant::HmacSha256Mac => Box::new(
                ReadXdrIter::<_, HmacSha256Mac>::new(dec)
                    .map(|r| r.map(|t| Self::HmacSha256Mac(Box::new(t)))),
            ),
        }
    }

    #[cfg(feature = "std")]
    pub fn from_xdr<B: AsRef<[u8]>>(v: TypeVariant, bytes: B) -> Result<Self> {
        let mut cursor = Cursor::new(bytes.as_ref());
        let t = Self::read_xdr_to_end(v, &mut cursor)?;
        Ok(t)
    }

    #[cfg(feature = "base64")]
    pub fn from_xdr_base64(v: TypeVariant, b64: String) -> Result<Self> {
        let mut b64_reader = Cursor::new(b64);
        let mut dec = base64::read::DecoderReader::new(&mut b64_reader, base64::STANDARD);
        let t = Self::read_xdr_to_end(v, &mut dec)?;
        Ok(t)
    }

    #[cfg(feature = "alloc")]
    #[must_use]
    #[allow(clippy::too_many_lines)]
    pub fn value(&self) -> &dyn core::any::Any {
        match self {
            Self::Value(ref v) => v.as_ref(),
            Self::ScpBallot(ref v) => v.as_ref(),
            Self::ScpStatementType(ref v) => v.as_ref(),
            Self::ScpNomination(ref v) => v.as_ref(),
            Self::ScpStatement(ref v) => v.as_ref(),
            Self::ScpStatementPledges(ref v) => v.as_ref(),
            Self::ScpStatementPrepare(ref v) => v.as_ref(),
            Self::ScpStatementConfirm(ref v) => v.as_ref(),
            Self::ScpStatementExternalize(ref v) => v.as_ref(),
            Self::ScpEnvelope(ref v) => v.as_ref(),
            Self::ScpQuorumSet(ref v) => v.as_ref(),
            Self::ScEnvMetaKind(ref v) => v.as_ref(),
            Self::ScEnvMetaEntry(ref v) => v.as_ref(),
            Self::ScSpecType(ref v) => v.as_ref(),
            Self::ScSpecTypeOption(ref v) => v.as_ref(),
            Self::ScSpecTypeResult(ref v) => v.as_ref(),
            Self::ScSpecTypeVec(ref v) => v.as_ref(),
            Self::ScSpecTypeMap(ref v) => v.as_ref(),
            Self::ScSpecTypeSet(ref v) => v.as_ref(),
            Self::ScSpecTypeTuple(ref v) => v.as_ref(),
            Self::ScSpecTypeBytesN(ref v) => v.as_ref(),
            Self::ScSpecTypeUdt(ref v) => v.as_ref(),
            Self::ScSpecTypeDef(ref v) => v.as_ref(),
            Self::ScSpecUdtStructFieldV0(ref v) => v.as_ref(),
            Self::ScSpecUdtStructV0(ref v) => v.as_ref(),
            Self::ScSpecUdtUnionCaseV0(ref v) => v.as_ref(),
            Self::ScSpecUdtUnionV0(ref v) => v.as_ref(),
            Self::ScSpecUdtEnumCaseV0(ref v) => v.as_ref(),
            Self::ScSpecUdtEnumV0(ref v) => v.as_ref(),
            Self::ScSpecUdtErrorEnumCaseV0(ref v) => v.as_ref(),
            Self::ScSpecUdtErrorEnumV0(ref v) => v.as_ref(),
            Self::ScSpecFunctionInputV0(ref v) => v.as_ref(),
            Self::ScSpecFunctionV0(ref v) => v.as_ref(),
            Self::ScSpecEntryKind(ref v) => v.as_ref(),
            Self::ScSpecEntry(ref v) => v.as_ref(),
            Self::ScSymbol(ref v) => v.as_ref(),
            Self::ScValType(ref v) => v.as_ref(),
            Self::ScStatic(ref v) => v.as_ref(),
            Self::ScStatusType(ref v) => v.as_ref(),
            Self::ScHostValErrorCode(ref v) => v.as_ref(),
            Self::ScHostObjErrorCode(ref v) => v.as_ref(),
            Self::ScHostFnErrorCode(ref v) => v.as_ref(),
            Self::ScHostStorageErrorCode(ref v) => v.as_ref(),
            Self::ScHostContextErrorCode(ref v) => v.as_ref(),
            Self::ScVmErrorCode(ref v) => v.as_ref(),
            Self::ScUnknownErrorCode(ref v) => v.as_ref(),
            Self::ScStatus(ref v) => v.as_ref(),
            Self::ScVal(ref v) => v.as_ref(),
            Self::ScObjectType(ref v) => v.as_ref(),
            Self::ScMapEntry(ref v) => v.as_ref(),
            Self::ScVec(ref v) => v.as_ref(),
            Self::ScMap(ref v) => v.as_ref(),
            Self::ScContractCodeType(ref v) => v.as_ref(),
            Self::ScContractCode(ref v) => v.as_ref(),
            Self::Int128Parts(ref v) => v.as_ref(),
            Self::ScObject(ref v) => v.as_ref(),
            Self::StoredTransactionSet(ref v) => v.as_ref(),
            Self::PersistedScpStateV0(ref v) => v.as_ref(),
            Self::PersistedScpStateV1(ref v) => v.as_ref(),
            Self::PersistedScpState(ref v) => v.as_ref(),
            Self::Thresholds(ref v) => v.as_ref(),
            Self::String32(ref v) => v.as_ref(),
            Self::String64(ref v) => v.as_ref(),
            Self::SequenceNumber(ref v) => v.as_ref(),
            Self::TimePoint(ref v) => v.as_ref(),
            Self::Duration(ref v) => v.as_ref(),
            Self::DataValue(ref v) => v.as_ref(),
            Self::PoolId(ref v) => v.as_ref(),
            Self::AssetCode4(ref v) => v.as_ref(),
            Self::AssetCode12(ref v) => v.as_ref(),
            Self::AssetType(ref v) => v.as_ref(),
            Self::AssetCode(ref v) => v.as_ref(),
            Self::AlphaNum4(ref v) => v.as_ref(),
            Self::AlphaNum12(ref v) => v.as_ref(),
            Self::Asset(ref v) => v.as_ref(),
            Self::Price(ref v) => v.as_ref(),
            Self::Liabilities(ref v) => v.as_ref(),
            Self::ThresholdIndexes(ref v) => v.as_ref(),
            Self::LedgerEntryType(ref v) => v.as_ref(),
            Self::Signer(ref v) => v.as_ref(),
            Self::AccountFlags(ref v) => v.as_ref(),
            Self::SponsorshipDescriptor(ref v) => v.as_ref(),
            Self::AccountEntryExtensionV3(ref v) => v.as_ref(),
            Self::AccountEntryExtensionV2(ref v) => v.as_ref(),
            Self::AccountEntryExtensionV2Ext(ref v) => v.as_ref(),
            Self::AccountEntryExtensionV1(ref v) => v.as_ref(),
            Self::AccountEntryExtensionV1Ext(ref v) => v.as_ref(),
            Self::AccountEntry(ref v) => v.as_ref(),
            Self::AccountEntryExt(ref v) => v.as_ref(),
            Self::TrustLineFlags(ref v) => v.as_ref(),
            Self::LiquidityPoolType(ref v) => v.as_ref(),
            Self::TrustLineAsset(ref v) => v.as_ref(),
            Self::TrustLineEntryExtensionV2(ref v) => v.as_ref(),
            Self::TrustLineEntryExtensionV2Ext(ref v) => v.as_ref(),
            Self::TrustLineEntry(ref v) => v.as_ref(),
            Self::TrustLineEntryExt(ref v) => v.as_ref(),
            Self::TrustLineEntryV1(ref v) => v.as_ref(),
            Self::TrustLineEntryV1Ext(ref v) => v.as_ref(),
            Self::OfferEntryFlags(ref v) => v.as_ref(),
            Self::OfferEntry(ref v) => v.as_ref(),
            Self::OfferEntryExt(ref v) => v.as_ref(),
            Self::DataEntry(ref v) => v.as_ref(),
            Self::DataEntryExt(ref v) => v.as_ref(),
            Self::ClaimPredicateType(ref v) => v.as_ref(),
            Self::ClaimPredicate(ref v) => v.as_ref(),
            Self::ClaimantType(ref v) => v.as_ref(),
            Self::Claimant(ref v) => v.as_ref(),
            Self::ClaimantV0(ref v) => v.as_ref(),
            Self::ClaimableBalanceIdType(ref v) => v.as_ref(),
            Self::ClaimableBalanceId(ref v) => v.as_ref(),
            Self::ClaimableBalanceFlags(ref v) => v.as_ref(),
            Self::ClaimableBalanceEntryExtensionV1(ref v) => v.as_ref(),
            Self::ClaimableBalanceEntryExtensionV1Ext(ref v) => v.as_ref(),
            Self::ClaimableBalanceEntry(ref v) => v.as_ref(),
            Self::ClaimableBalanceEntryExt(ref v) => v.as_ref(),
            Self::LiquidityPoolConstantProductParameters(ref v) => v.as_ref(),
            Self::LiquidityPoolEntry(ref v) => v.as_ref(),
            Self::LiquidityPoolEntryBody(ref v) => v.as_ref(),
            Self::LiquidityPoolEntryConstantProduct(ref v) => v.as_ref(),
            Self::ContractDataEntry(ref v) => v.as_ref(),
            Self::ContractCodeEntry(ref v) => v.as_ref(),
            Self::ConfigSettingType(ref v) => v.as_ref(),
            Self::ConfigSetting(ref v) => v.as_ref(),
            Self::ConfigSettingId(ref v) => v.as_ref(),
            Self::ConfigSettingEntry(ref v) => v.as_ref(),
            Self::ConfigSettingEntryExt(ref v) => v.as_ref(),
            Self::LedgerEntryExtensionV1(ref v) => v.as_ref(),
            Self::LedgerEntryExtensionV1Ext(ref v) => v.as_ref(),
            Self::LedgerEntry(ref v) => v.as_ref(),
            Self::LedgerEntryData(ref v) => v.as_ref(),
            Self::LedgerEntryExt(ref v) => v.as_ref(),
            Self::LedgerKey(ref v) => v.as_ref(),
            Self::LedgerKeyAccount(ref v) => v.as_ref(),
            Self::LedgerKeyTrustLine(ref v) => v.as_ref(),
            Self::LedgerKeyOffer(ref v) => v.as_ref(),
            Self::LedgerKeyData(ref v) => v.as_ref(),
            Self::LedgerKeyClaimableBalance(ref v) => v.as_ref(),
            Self::LedgerKeyLiquidityPool(ref v) => v.as_ref(),
            Self::LedgerKeyContractData(ref v) => v.as_ref(),
            Self::LedgerKeyContractCode(ref v) => v.as_ref(),
            Self::LedgerKeyConfigSetting(ref v) => v.as_ref(),
            Self::EnvelopeType(ref v) => v.as_ref(),
            Self::UpgradeType(ref v) => v.as_ref(),
            Self::StellarValueType(ref v) => v.as_ref(),
            Self::LedgerCloseValueSignature(ref v) => v.as_ref(),
            Self::StellarValue(ref v) => v.as_ref(),
            Self::StellarValueExt(ref v) => v.as_ref(),
            Self::LedgerHeaderFlags(ref v) => v.as_ref(),
            Self::LedgerHeaderExtensionV1(ref v) => v.as_ref(),
            Self::LedgerHeaderExtensionV1Ext(ref v) => v.as_ref(),
            Self::LedgerHeader(ref v) => v.as_ref(),
            Self::LedgerHeaderExt(ref v) => v.as_ref(),
            Self::LedgerUpgradeType(ref v) => v.as_ref(),
            Self::LedgerUpgrade(ref v) => v.as_ref(),
            Self::LedgerUpgradeConfigSetting(ref v) => v.as_ref(),
            Self::BucketEntryType(ref v) => v.as_ref(),
            Self::BucketMetadata(ref v) => v.as_ref(),
            Self::BucketMetadataExt(ref v) => v.as_ref(),
            Self::BucketEntry(ref v) => v.as_ref(),
            Self::TxSetComponentType(ref v) => v.as_ref(),
            Self::TxSetComponent(ref v) => v.as_ref(),
            Self::TxSetComponentTxsMaybeDiscountedFee(ref v) => v.as_ref(),
            Self::TransactionPhase(ref v) => v.as_ref(),
            Self::TransactionSet(ref v) => v.as_ref(),
            Self::TransactionSetV1(ref v) => v.as_ref(),
            Self::GeneralizedTransactionSet(ref v) => v.as_ref(),
            Self::TransactionResultPair(ref v) => v.as_ref(),
            Self::TransactionResultSet(ref v) => v.as_ref(),
            Self::TransactionHistoryEntry(ref v) => v.as_ref(),
            Self::TransactionHistoryEntryExt(ref v) => v.as_ref(),
            Self::TransactionHistoryResultEntry(ref v) => v.as_ref(),
            Self::TransactionHistoryResultEntryExt(ref v) => v.as_ref(),
            Self::TransactionResultPairV2(ref v) => v.as_ref(),
            Self::TransactionResultSetV2(ref v) => v.as_ref(),
            Self::TransactionHistoryResultEntryV2(ref v) => v.as_ref(),
            Self::TransactionHistoryResultEntryV2Ext(ref v) => v.as_ref(),
            Self::LedgerHeaderHistoryEntry(ref v) => v.as_ref(),
            Self::LedgerHeaderHistoryEntryExt(ref v) => v.as_ref(),
            Self::LedgerScpMessages(ref v) => v.as_ref(),
            Self::ScpHistoryEntryV0(ref v) => v.as_ref(),
            Self::ScpHistoryEntry(ref v) => v.as_ref(),
            Self::LedgerEntryChangeType(ref v) => v.as_ref(),
            Self::LedgerEntryChange(ref v) => v.as_ref(),
            Self::LedgerEntryChanges(ref v) => v.as_ref(),
            Self::OperationMeta(ref v) => v.as_ref(),
            Self::TransactionMetaV1(ref v) => v.as_ref(),
            Self::TransactionMetaV2(ref v) => v.as_ref(),
            Self::ContractEventType(ref v) => v.as_ref(),
            Self::ContractEvent(ref v) => v.as_ref(),
            Self::ContractEventBody(ref v) => v.as_ref(),
            Self::ContractEventV0(ref v) => v.as_ref(),
            Self::OperationEvents(ref v) => v.as_ref(),
            Self::TransactionMetaV3(ref v) => v.as_ref(),
            Self::TransactionMeta(ref v) => v.as_ref(),
            Self::TransactionResultMeta(ref v) => v.as_ref(),
            Self::TransactionResultMetaV2(ref v) => v.as_ref(),
            Self::UpgradeEntryMeta(ref v) => v.as_ref(),
            Self::LedgerCloseMetaV0(ref v) => v.as_ref(),
            Self::LedgerCloseMetaV1(ref v) => v.as_ref(),
            Self::LedgerCloseMetaV2(ref v) => v.as_ref(),
            Self::LedgerCloseMeta(ref v) => v.as_ref(),
            Self::ErrorCode(ref v) => v.as_ref(),
            Self::SError(ref v) => v.as_ref(),
            Self::SendMore(ref v) => v.as_ref(),
            Self::AuthCert(ref v) => v.as_ref(),
            Self::Hello(ref v) => v.as_ref(),
            Self::Auth(ref v) => v.as_ref(),
            Self::IpAddrType(ref v) => v.as_ref(),
            Self::PeerAddress(ref v) => v.as_ref(),
            Self::PeerAddressIp(ref v) => v.as_ref(),
            Self::MessageType(ref v) => v.as_ref(),
            Self::DontHave(ref v) => v.as_ref(),
            Self::SurveyMessageCommandType(ref v) => v.as_ref(),
            Self::SurveyRequestMessage(ref v) => v.as_ref(),
            Self::SignedSurveyRequestMessage(ref v) => v.as_ref(),
            Self::EncryptedBody(ref v) => v.as_ref(),
            Self::SurveyResponseMessage(ref v) => v.as_ref(),
            Self::SignedSurveyResponseMessage(ref v) => v.as_ref(),
            Self::PeerStats(ref v) => v.as_ref(),
            Self::PeerStatList(ref v) => v.as_ref(),
            Self::TopologyResponseBody(ref v) => v.as_ref(),
            Self::SurveyResponseBody(ref v) => v.as_ref(),
            Self::TxAdvertVector(ref v) => v.as_ref(),
            Self::FloodAdvert(ref v) => v.as_ref(),
            Self::TxDemandVector(ref v) => v.as_ref(),
            Self::FloodDemand(ref v) => v.as_ref(),
            Self::StellarMessage(ref v) => v.as_ref(),
            Self::AuthenticatedMessage(ref v) => v.as_ref(),
            Self::AuthenticatedMessageV0(ref v) => v.as_ref(),
            Self::LiquidityPoolParameters(ref v) => v.as_ref(),
            Self::MuxedAccount(ref v) => v.as_ref(),
            Self::MuxedAccountMed25519(ref v) => v.as_ref(),
            Self::DecoratedSignature(ref v) => v.as_ref(),
            Self::LedgerFootprint(ref v) => v.as_ref(),
            Self::OperationType(ref v) => v.as_ref(),
            Self::CreateAccountOp(ref v) => v.as_ref(),
            Self::PaymentOp(ref v) => v.as_ref(),
            Self::PathPaymentStrictReceiveOp(ref v) => v.as_ref(),
            Self::PathPaymentStrictSendOp(ref v) => v.as_ref(),
            Self::ManageSellOfferOp(ref v) => v.as_ref(),
            Self::ManageBuyOfferOp(ref v) => v.as_ref(),
            Self::CreatePassiveSellOfferOp(ref v) => v.as_ref(),
            Self::SetOptionsOp(ref v) => v.as_ref(),
            Self::ChangeTrustAsset(ref v) => v.as_ref(),
            Self::ChangeTrustOp(ref v) => v.as_ref(),
            Self::AllowTrustOp(ref v) => v.as_ref(),
            Self::ManageDataOp(ref v) => v.as_ref(),
            Self::BumpSequenceOp(ref v) => v.as_ref(),
            Self::CreateClaimableBalanceOp(ref v) => v.as_ref(),
            Self::ClaimClaimableBalanceOp(ref v) => v.as_ref(),
            Self::BeginSponsoringFutureReservesOp(ref v) => v.as_ref(),
            Self::RevokeSponsorshipType(ref v) => v.as_ref(),
            Self::RevokeSponsorshipOp(ref v) => v.as_ref(),
            Self::RevokeSponsorshipOpSigner(ref v) => v.as_ref(),
            Self::ClawbackOp(ref v) => v.as_ref(),
            Self::ClawbackClaimableBalanceOp(ref v) => v.as_ref(),
            Self::SetTrustLineFlagsOp(ref v) => v.as_ref(),
            Self::LiquidityPoolDepositOp(ref v) => v.as_ref(),
            Self::LiquidityPoolWithdrawOp(ref v) => v.as_ref(),
            Self::HostFunctionType(ref v) => v.as_ref(),
            Self::ContractIdType(ref v) => v.as_ref(),
            Self::ContractIdPublicKeyType(ref v) => v.as_ref(),
            Self::InstallContractCodeArgs(ref v) => v.as_ref(),
            Self::ContractId(ref v) => v.as_ref(),
            Self::ContractIdFromEd25519PublicKey(ref v) => v.as_ref(),
            Self::CreateContractArgs(ref v) => v.as_ref(),
            Self::HostFunction(ref v) => v.as_ref(),
            Self::InvokeHostFunctionOp(ref v) => v.as_ref(),
            Self::Operation(ref v) => v.as_ref(),
            Self::OperationBody(ref v) => v.as_ref(),
            Self::HashIdPreimage(ref v) => v.as_ref(),
            Self::HashIdPreimageOperationId(ref v) => v.as_ref(),
            Self::HashIdPreimageRevokeId(ref v) => v.as_ref(),
            Self::HashIdPreimageEd25519ContractId(ref v) => v.as_ref(),
            Self::HashIdPreimageContractId(ref v) => v.as_ref(),
            Self::HashIdPreimageFromAsset(ref v) => v.as_ref(),
            Self::HashIdPreimageSourceAccountContractId(ref v) => v.as_ref(),
            Self::HashIdPreimageCreateContractArgs(ref v) => v.as_ref(),
            Self::MemoType(ref v) => v.as_ref(),
            Self::Memo(ref v) => v.as_ref(),
            Self::TimeBounds(ref v) => v.as_ref(),
            Self::LedgerBounds(ref v) => v.as_ref(),
            Self::PreconditionsV2(ref v) => v.as_ref(),
            Self::PreconditionType(ref v) => v.as_ref(),
            Self::Preconditions(ref v) => v.as_ref(),
            Self::TransactionV0(ref v) => v.as_ref(),
            Self::TransactionV0Ext(ref v) => v.as_ref(),
            Self::TransactionV0Envelope(ref v) => v.as_ref(),
            Self::Transaction(ref v) => v.as_ref(),
            Self::TransactionExt(ref v) => v.as_ref(),
            Self::TransactionV1Envelope(ref v) => v.as_ref(),
            Self::FeeBumpTransaction(ref v) => v.as_ref(),
            Self::FeeBumpTransactionInnerTx(ref v) => v.as_ref(),
            Self::FeeBumpTransactionExt(ref v) => v.as_ref(),
            Self::FeeBumpTransactionEnvelope(ref v) => v.as_ref(),
            Self::TransactionEnvelope(ref v) => v.as_ref(),
            Self::TransactionSignaturePayload(ref v) => v.as_ref(),
            Self::TransactionSignaturePayloadTaggedTransaction(ref v) => v.as_ref(),
            Self::ClaimAtomType(ref v) => v.as_ref(),
            Self::ClaimOfferAtomV0(ref v) => v.as_ref(),
            Self::ClaimOfferAtom(ref v) => v.as_ref(),
            Self::ClaimLiquidityAtom(ref v) => v.as_ref(),
            Self::ClaimAtom(ref v) => v.as_ref(),
            Self::CreateAccountResultCode(ref v) => v.as_ref(),
            Self::CreateAccountResult(ref v) => v.as_ref(),
            Self::PaymentResultCode(ref v) => v.as_ref(),
            Self::PaymentResult(ref v) => v.as_ref(),
            Self::PathPaymentStrictReceiveResultCode(ref v) => v.as_ref(),
            Self::SimplePaymentResult(ref v) => v.as_ref(),
            Self::PathPaymentStrictReceiveResult(ref v) => v.as_ref(),
            Self::PathPaymentStrictReceiveResultSuccess(ref v) => v.as_ref(),
            Self::PathPaymentStrictSendResultCode(ref v) => v.as_ref(),
            Self::PathPaymentStrictSendResult(ref v) => v.as_ref(),
            Self::PathPaymentStrictSendResultSuccess(ref v) => v.as_ref(),
            Self::ManageSellOfferResultCode(ref v) => v.as_ref(),
            Self::ManageOfferEffect(ref v) => v.as_ref(),
            Self::ManageOfferSuccessResult(ref v) => v.as_ref(),
            Self::ManageOfferSuccessResultOffer(ref v) => v.as_ref(),
            Self::ManageSellOfferResult(ref v) => v.as_ref(),
            Self::ManageBuyOfferResultCode(ref v) => v.as_ref(),
            Self::ManageBuyOfferResult(ref v) => v.as_ref(),
            Self::SetOptionsResultCode(ref v) => v.as_ref(),
            Self::SetOptionsResult(ref v) => v.as_ref(),
            Self::ChangeTrustResultCode(ref v) => v.as_ref(),
            Self::ChangeTrustResult(ref v) => v.as_ref(),
            Self::AllowTrustResultCode(ref v) => v.as_ref(),
            Self::AllowTrustResult(ref v) => v.as_ref(),
            Self::AccountMergeResultCode(ref v) => v.as_ref(),
            Self::AccountMergeResult(ref v) => v.as_ref(),
            Self::InflationResultCode(ref v) => v.as_ref(),
            Self::InflationPayout(ref v) => v.as_ref(),
            Self::InflationResult(ref v) => v.as_ref(),
            Self::ManageDataResultCode(ref v) => v.as_ref(),
            Self::ManageDataResult(ref v) => v.as_ref(),
            Self::BumpSequenceResultCode(ref v) => v.as_ref(),
            Self::BumpSequenceResult(ref v) => v.as_ref(),
            Self::CreateClaimableBalanceResultCode(ref v) => v.as_ref(),
            Self::CreateClaimableBalanceResult(ref v) => v.as_ref(),
            Self::ClaimClaimableBalanceResultCode(ref v) => v.as_ref(),
            Self::ClaimClaimableBalanceResult(ref v) => v.as_ref(),
            Self::BeginSponsoringFutureReservesResultCode(ref v) => v.as_ref(),
            Self::BeginSponsoringFutureReservesResult(ref v) => v.as_ref(),
            Self::EndSponsoringFutureReservesResultCode(ref v) => v.as_ref(),
            Self::EndSponsoringFutureReservesResult(ref v) => v.as_ref(),
            Self::RevokeSponsorshipResultCode(ref v) => v.as_ref(),
            Self::RevokeSponsorshipResult(ref v) => v.as_ref(),
            Self::ClawbackResultCode(ref v) => v.as_ref(),
            Self::ClawbackResult(ref v) => v.as_ref(),
            Self::ClawbackClaimableBalanceResultCode(ref v) => v.as_ref(),
            Self::ClawbackClaimableBalanceResult(ref v) => v.as_ref(),
            Self::SetTrustLineFlagsResultCode(ref v) => v.as_ref(),
            Self::SetTrustLineFlagsResult(ref v) => v.as_ref(),
            Self::LiquidityPoolDepositResultCode(ref v) => v.as_ref(),
            Self::LiquidityPoolDepositResult(ref v) => v.as_ref(),
            Self::LiquidityPoolWithdrawResultCode(ref v) => v.as_ref(),
            Self::LiquidityPoolWithdrawResult(ref v) => v.as_ref(),
            Self::InvokeHostFunctionResultCode(ref v) => v.as_ref(),
            Self::InvokeHostFunctionResult(ref v) => v.as_ref(),
            Self::OperationResultCode(ref v) => v.as_ref(),
            Self::OperationResult(ref v) => v.as_ref(),
            Self::OperationResultTr(ref v) => v.as_ref(),
            Self::TransactionResultCode(ref v) => v.as_ref(),
            Self::InnerTransactionResult(ref v) => v.as_ref(),
            Self::InnerTransactionResultResult(ref v) => v.as_ref(),
            Self::InnerTransactionResultExt(ref v) => v.as_ref(),
            Self::InnerTransactionResultPair(ref v) => v.as_ref(),
            Self::TransactionResult(ref v) => v.as_ref(),
            Self::TransactionResultResult(ref v) => v.as_ref(),
            Self::TransactionResultExt(ref v) => v.as_ref(),
            Self::Hash(ref v) => v.as_ref(),
            Self::Uint256(ref v) => v.as_ref(),
            Self::Uint32(ref v) => v.as_ref(),
            Self::Int32(ref v) => v.as_ref(),
            Self::Uint64(ref v) => v.as_ref(),
            Self::Int64(ref v) => v.as_ref(),
            Self::ExtensionPoint(ref v) => v.as_ref(),
            Self::CryptoKeyType(ref v) => v.as_ref(),
            Self::PublicKeyType(ref v) => v.as_ref(),
            Self::SignerKeyType(ref v) => v.as_ref(),
            Self::PublicKey(ref v) => v.as_ref(),
            Self::SignerKey(ref v) => v.as_ref(),
            Self::SignerKeyEd25519SignedPayload(ref v) => v.as_ref(),
            Self::Signature(ref v) => v.as_ref(),
            Self::SignatureHint(ref v) => v.as_ref(),
            Self::NodeId(ref v) => v.as_ref(),
            Self::AccountId(ref v) => v.as_ref(),
            Self::Curve25519Secret(ref v) => v.as_ref(),
            Self::Curve25519Public(ref v) => v.as_ref(),
            Self::HmacSha256Key(ref v) => v.as_ref(),
            Self::HmacSha256Mac(ref v) => v.as_ref(),
        }
    }

    #[must_use]
    #[allow(clippy::too_many_lines)]
    pub const fn name(&self) -> &'static str {
        match self {
            Self::Value(_) => "Value",
            Self::ScpBallot(_) => "ScpBallot",
            Self::ScpStatementType(_) => "ScpStatementType",
            Self::ScpNomination(_) => "ScpNomination",
            Self::ScpStatement(_) => "ScpStatement",
            Self::ScpStatementPledges(_) => "ScpStatementPledges",
            Self::ScpStatementPrepare(_) => "ScpStatementPrepare",
            Self::ScpStatementConfirm(_) => "ScpStatementConfirm",
            Self::ScpStatementExternalize(_) => "ScpStatementExternalize",
            Self::ScpEnvelope(_) => "ScpEnvelope",
            Self::ScpQuorumSet(_) => "ScpQuorumSet",
            Self::ScEnvMetaKind(_) => "ScEnvMetaKind",
            Self::ScEnvMetaEntry(_) => "ScEnvMetaEntry",
            Self::ScSpecType(_) => "ScSpecType",
            Self::ScSpecTypeOption(_) => "ScSpecTypeOption",
            Self::ScSpecTypeResult(_) => "ScSpecTypeResult",
            Self::ScSpecTypeVec(_) => "ScSpecTypeVec",
            Self::ScSpecTypeMap(_) => "ScSpecTypeMap",
            Self::ScSpecTypeSet(_) => "ScSpecTypeSet",
            Self::ScSpecTypeTuple(_) => "ScSpecTypeTuple",
            Self::ScSpecTypeBytesN(_) => "ScSpecTypeBytesN",
            Self::ScSpecTypeUdt(_) => "ScSpecTypeUdt",
            Self::ScSpecTypeDef(_) => "ScSpecTypeDef",
            Self::ScSpecUdtStructFieldV0(_) => "ScSpecUdtStructFieldV0",
            Self::ScSpecUdtStructV0(_) => "ScSpecUdtStructV0",
            Self::ScSpecUdtUnionCaseV0(_) => "ScSpecUdtUnionCaseV0",
            Self::ScSpecUdtUnionV0(_) => "ScSpecUdtUnionV0",
            Self::ScSpecUdtEnumCaseV0(_) => "ScSpecUdtEnumCaseV0",
            Self::ScSpecUdtEnumV0(_) => "ScSpecUdtEnumV0",
            Self::ScSpecUdtErrorEnumCaseV0(_) => "ScSpecUdtErrorEnumCaseV0",
            Self::ScSpecUdtErrorEnumV0(_) => "ScSpecUdtErrorEnumV0",
            Self::ScSpecFunctionInputV0(_) => "ScSpecFunctionInputV0",
            Self::ScSpecFunctionV0(_) => "ScSpecFunctionV0",
            Self::ScSpecEntryKind(_) => "ScSpecEntryKind",
            Self::ScSpecEntry(_) => "ScSpecEntry",
            Self::ScSymbol(_) => "ScSymbol",
            Self::ScValType(_) => "ScValType",
            Self::ScStatic(_) => "ScStatic",
            Self::ScStatusType(_) => "ScStatusType",
            Self::ScHostValErrorCode(_) => "ScHostValErrorCode",
            Self::ScHostObjErrorCode(_) => "ScHostObjErrorCode",
            Self::ScHostFnErrorCode(_) => "ScHostFnErrorCode",
            Self::ScHostStorageErrorCode(_) => "ScHostStorageErrorCode",
            Self::ScHostContextErrorCode(_) => "ScHostContextErrorCode",
            Self::ScVmErrorCode(_) => "ScVmErrorCode",
            Self::ScUnknownErrorCode(_) => "ScUnknownErrorCode",
            Self::ScStatus(_) => "ScStatus",
            Self::ScVal(_) => "ScVal",
            Self::ScObjectType(_) => "ScObjectType",
            Self::ScMapEntry(_) => "ScMapEntry",
            Self::ScVec(_) => "ScVec",
            Self::ScMap(_) => "ScMap",
            Self::ScContractCodeType(_) => "ScContractCodeType",
            Self::ScContractCode(_) => "ScContractCode",
            Self::Int128Parts(_) => "Int128Parts",
            Self::ScObject(_) => "ScObject",
            Self::StoredTransactionSet(_) => "StoredTransactionSet",
            Self::PersistedScpStateV0(_) => "PersistedScpStateV0",
            Self::PersistedScpStateV1(_) => "PersistedScpStateV1",
            Self::PersistedScpState(_) => "PersistedScpState",
            Self::Thresholds(_) => "Thresholds",
            Self::String32(_) => "String32",
            Self::String64(_) => "String64",
            Self::SequenceNumber(_) => "SequenceNumber",
            Self::TimePoint(_) => "TimePoint",
            Self::Duration(_) => "Duration",
            Self::DataValue(_) => "DataValue",
            Self::PoolId(_) => "PoolId",
            Self::AssetCode4(_) => "AssetCode4",
            Self::AssetCode12(_) => "AssetCode12",
            Self::AssetType(_) => "AssetType",
            Self::AssetCode(_) => "AssetCode",
            Self::AlphaNum4(_) => "AlphaNum4",
            Self::AlphaNum12(_) => "AlphaNum12",
            Self::Asset(_) => "Asset",
            Self::Price(_) => "Price",
            Self::Liabilities(_) => "Liabilities",
            Self::ThresholdIndexes(_) => "ThresholdIndexes",
            Self::LedgerEntryType(_) => "LedgerEntryType",
            Self::Signer(_) => "Signer",
            Self::AccountFlags(_) => "AccountFlags",
            Self::SponsorshipDescriptor(_) => "SponsorshipDescriptor",
            Self::AccountEntryExtensionV3(_) => "AccountEntryExtensionV3",
            Self::AccountEntryExtensionV2(_) => "AccountEntryExtensionV2",
            Self::AccountEntryExtensionV2Ext(_) => "AccountEntryExtensionV2Ext",
            Self::AccountEntryExtensionV1(_) => "AccountEntryExtensionV1",
            Self::AccountEntryExtensionV1Ext(_) => "AccountEntryExtensionV1Ext",
            Self::AccountEntry(_) => "AccountEntry",
            Self::AccountEntryExt(_) => "AccountEntryExt",
            Self::TrustLineFlags(_) => "TrustLineFlags",
            Self::LiquidityPoolType(_) => "LiquidityPoolType",
            Self::TrustLineAsset(_) => "TrustLineAsset",
            Self::TrustLineEntryExtensionV2(_) => "TrustLineEntryExtensionV2",
            Self::TrustLineEntryExtensionV2Ext(_) => "TrustLineEntryExtensionV2Ext",
            Self::TrustLineEntry(_) => "TrustLineEntry",
            Self::TrustLineEntryExt(_) => "TrustLineEntryExt",
            Self::TrustLineEntryV1(_) => "TrustLineEntryV1",
            Self::TrustLineEntryV1Ext(_) => "TrustLineEntryV1Ext",
            Self::OfferEntryFlags(_) => "OfferEntryFlags",
            Self::OfferEntry(_) => "OfferEntry",
            Self::OfferEntryExt(_) => "OfferEntryExt",
            Self::DataEntry(_) => "DataEntry",
            Self::DataEntryExt(_) => "DataEntryExt",
            Self::ClaimPredicateType(_) => "ClaimPredicateType",
            Self::ClaimPredicate(_) => "ClaimPredicate",
            Self::ClaimantType(_) => "ClaimantType",
            Self::Claimant(_) => "Claimant",
            Self::ClaimantV0(_) => "ClaimantV0",
            Self::ClaimableBalanceIdType(_) => "ClaimableBalanceIdType",
            Self::ClaimableBalanceId(_) => "ClaimableBalanceId",
            Self::ClaimableBalanceFlags(_) => "ClaimableBalanceFlags",
            Self::ClaimableBalanceEntryExtensionV1(_) => "ClaimableBalanceEntryExtensionV1",
            Self::ClaimableBalanceEntryExtensionV1Ext(_) => "ClaimableBalanceEntryExtensionV1Ext",
            Self::ClaimableBalanceEntry(_) => "ClaimableBalanceEntry",
            Self::ClaimableBalanceEntryExt(_) => "ClaimableBalanceEntryExt",
            Self::LiquidityPoolConstantProductParameters(_) => {
                "LiquidityPoolConstantProductParameters"
            }
            Self::LiquidityPoolEntry(_) => "LiquidityPoolEntry",
            Self::LiquidityPoolEntryBody(_) => "LiquidityPoolEntryBody",
            Self::LiquidityPoolEntryConstantProduct(_) => "LiquidityPoolEntryConstantProduct",
            Self::ContractDataEntry(_) => "ContractDataEntry",
            Self::ContractCodeEntry(_) => "ContractCodeEntry",
            Self::ConfigSettingType(_) => "ConfigSettingType",
            Self::ConfigSetting(_) => "ConfigSetting",
            Self::ConfigSettingId(_) => "ConfigSettingId",
            Self::ConfigSettingEntry(_) => "ConfigSettingEntry",
            Self::ConfigSettingEntryExt(_) => "ConfigSettingEntryExt",
            Self::LedgerEntryExtensionV1(_) => "LedgerEntryExtensionV1",
            Self::LedgerEntryExtensionV1Ext(_) => "LedgerEntryExtensionV1Ext",
            Self::LedgerEntry(_) => "LedgerEntry",
            Self::LedgerEntryData(_) => "LedgerEntryData",
            Self::LedgerEntryExt(_) => "LedgerEntryExt",
            Self::LedgerKey(_) => "LedgerKey",
            Self::LedgerKeyAccount(_) => "LedgerKeyAccount",
            Self::LedgerKeyTrustLine(_) => "LedgerKeyTrustLine",
            Self::LedgerKeyOffer(_) => "LedgerKeyOffer",
            Self::LedgerKeyData(_) => "LedgerKeyData",
            Self::LedgerKeyClaimableBalance(_) => "LedgerKeyClaimableBalance",
            Self::LedgerKeyLiquidityPool(_) => "LedgerKeyLiquidityPool",
            Self::LedgerKeyContractData(_) => "LedgerKeyContractData",
            Self::LedgerKeyContractCode(_) => "LedgerKeyContractCode",
            Self::LedgerKeyConfigSetting(_) => "LedgerKeyConfigSetting",
            Self::EnvelopeType(_) => "EnvelopeType",
            Self::UpgradeType(_) => "UpgradeType",
            Self::StellarValueType(_) => "StellarValueType",
            Self::LedgerCloseValueSignature(_) => "LedgerCloseValueSignature",
            Self::StellarValue(_) => "StellarValue",
            Self::StellarValueExt(_) => "StellarValueExt",
            Self::LedgerHeaderFlags(_) => "LedgerHeaderFlags",
            Self::LedgerHeaderExtensionV1(_) => "LedgerHeaderExtensionV1",
            Self::LedgerHeaderExtensionV1Ext(_) => "LedgerHeaderExtensionV1Ext",
            Self::LedgerHeader(_) => "LedgerHeader",
            Self::LedgerHeaderExt(_) => "LedgerHeaderExt",
            Self::LedgerUpgradeType(_) => "LedgerUpgradeType",
            Self::LedgerUpgrade(_) => "LedgerUpgrade",
            Self::LedgerUpgradeConfigSetting(_) => "LedgerUpgradeConfigSetting",
            Self::BucketEntryType(_) => "BucketEntryType",
            Self::BucketMetadata(_) => "BucketMetadata",
            Self::BucketMetadataExt(_) => "BucketMetadataExt",
            Self::BucketEntry(_) => "BucketEntry",
            Self::TxSetComponentType(_) => "TxSetComponentType",
            Self::TxSetComponent(_) => "TxSetComponent",
            Self::TxSetComponentTxsMaybeDiscountedFee(_) => "TxSetComponentTxsMaybeDiscountedFee",
            Self::TransactionPhase(_) => "TransactionPhase",
            Self::TransactionSet(_) => "TransactionSet",
            Self::TransactionSetV1(_) => "TransactionSetV1",
            Self::GeneralizedTransactionSet(_) => "GeneralizedTransactionSet",
            Self::TransactionResultPair(_) => "TransactionResultPair",
            Self::TransactionResultSet(_) => "TransactionResultSet",
            Self::TransactionHistoryEntry(_) => "TransactionHistoryEntry",
            Self::TransactionHistoryEntryExt(_) => "TransactionHistoryEntryExt",
            Self::TransactionHistoryResultEntry(_) => "TransactionHistoryResultEntry",
            Self::TransactionHistoryResultEntryExt(_) => "TransactionHistoryResultEntryExt",
            Self::TransactionResultPairV2(_) => "TransactionResultPairV2",
            Self::TransactionResultSetV2(_) => "TransactionResultSetV2",
            Self::TransactionHistoryResultEntryV2(_) => "TransactionHistoryResultEntryV2",
            Self::TransactionHistoryResultEntryV2Ext(_) => "TransactionHistoryResultEntryV2Ext",
            Self::LedgerHeaderHistoryEntry(_) => "LedgerHeaderHistoryEntry",
            Self::LedgerHeaderHistoryEntryExt(_) => "LedgerHeaderHistoryEntryExt",
            Self::LedgerScpMessages(_) => "LedgerScpMessages",
            Self::ScpHistoryEntryV0(_) => "ScpHistoryEntryV0",
            Self::ScpHistoryEntry(_) => "ScpHistoryEntry",
            Self::LedgerEntryChangeType(_) => "LedgerEntryChangeType",
            Self::LedgerEntryChange(_) => "LedgerEntryChange",
            Self::LedgerEntryChanges(_) => "LedgerEntryChanges",
            Self::OperationMeta(_) => "OperationMeta",
            Self::TransactionMetaV1(_) => "TransactionMetaV1",
            Self::TransactionMetaV2(_) => "TransactionMetaV2",
            Self::ContractEventType(_) => "ContractEventType",
            Self::ContractEvent(_) => "ContractEvent",
            Self::ContractEventBody(_) => "ContractEventBody",
            Self::ContractEventV0(_) => "ContractEventV0",
            Self::OperationEvents(_) => "OperationEvents",
            Self::TransactionMetaV3(_) => "TransactionMetaV3",
            Self::TransactionMeta(_) => "TransactionMeta",
            Self::TransactionResultMeta(_) => "TransactionResultMeta",
            Self::TransactionResultMetaV2(_) => "TransactionResultMetaV2",
            Self::UpgradeEntryMeta(_) => "UpgradeEntryMeta",
            Self::LedgerCloseMetaV0(_) => "LedgerCloseMetaV0",
            Self::LedgerCloseMetaV1(_) => "LedgerCloseMetaV1",
            Self::LedgerCloseMetaV2(_) => "LedgerCloseMetaV2",
            Self::LedgerCloseMeta(_) => "LedgerCloseMeta",
            Self::ErrorCode(_) => "ErrorCode",
            Self::SError(_) => "SError",
            Self::SendMore(_) => "SendMore",
            Self::AuthCert(_) => "AuthCert",
            Self::Hello(_) => "Hello",
            Self::Auth(_) => "Auth",
            Self::IpAddrType(_) => "IpAddrType",
            Self::PeerAddress(_) => "PeerAddress",
            Self::PeerAddressIp(_) => "PeerAddressIp",
            Self::MessageType(_) => "MessageType",
            Self::DontHave(_) => "DontHave",
            Self::SurveyMessageCommandType(_) => "SurveyMessageCommandType",
            Self::SurveyRequestMessage(_) => "SurveyRequestMessage",
            Self::SignedSurveyRequestMessage(_) => "SignedSurveyRequestMessage",
            Self::EncryptedBody(_) => "EncryptedBody",
            Self::SurveyResponseMessage(_) => "SurveyResponseMessage",
            Self::SignedSurveyResponseMessage(_) => "SignedSurveyResponseMessage",
            Self::PeerStats(_) => "PeerStats",
            Self::PeerStatList(_) => "PeerStatList",
            Self::TopologyResponseBody(_) => "TopologyResponseBody",
            Self::SurveyResponseBody(_) => "SurveyResponseBody",
            Self::TxAdvertVector(_) => "TxAdvertVector",
            Self::FloodAdvert(_) => "FloodAdvert",
            Self::TxDemandVector(_) => "TxDemandVector",
            Self::FloodDemand(_) => "FloodDemand",
            Self::StellarMessage(_) => "StellarMessage",
            Self::AuthenticatedMessage(_) => "AuthenticatedMessage",
            Self::AuthenticatedMessageV0(_) => "AuthenticatedMessageV0",
            Self::LiquidityPoolParameters(_) => "LiquidityPoolParameters",
            Self::MuxedAccount(_) => "MuxedAccount",
            Self::MuxedAccountMed25519(_) => "MuxedAccountMed25519",
            Self::DecoratedSignature(_) => "DecoratedSignature",
            Self::LedgerFootprint(_) => "LedgerFootprint",
            Self::OperationType(_) => "OperationType",
            Self::CreateAccountOp(_) => "CreateAccountOp",
            Self::PaymentOp(_) => "PaymentOp",
            Self::PathPaymentStrictReceiveOp(_) => "PathPaymentStrictReceiveOp",
            Self::PathPaymentStrictSendOp(_) => "PathPaymentStrictSendOp",
            Self::ManageSellOfferOp(_) => "ManageSellOfferOp",
            Self::ManageBuyOfferOp(_) => "ManageBuyOfferOp",
            Self::CreatePassiveSellOfferOp(_) => "CreatePassiveSellOfferOp",
            Self::SetOptionsOp(_) => "SetOptionsOp",
            Self::ChangeTrustAsset(_) => "ChangeTrustAsset",
            Self::ChangeTrustOp(_) => "ChangeTrustOp",
            Self::AllowTrustOp(_) => "AllowTrustOp",
            Self::ManageDataOp(_) => "ManageDataOp",
            Self::BumpSequenceOp(_) => "BumpSequenceOp",
            Self::CreateClaimableBalanceOp(_) => "CreateClaimableBalanceOp",
            Self::ClaimClaimableBalanceOp(_) => "ClaimClaimableBalanceOp",
            Self::BeginSponsoringFutureReservesOp(_) => "BeginSponsoringFutureReservesOp",
            Self::RevokeSponsorshipType(_) => "RevokeSponsorshipType",
            Self::RevokeSponsorshipOp(_) => "RevokeSponsorshipOp",
            Self::RevokeSponsorshipOpSigner(_) => "RevokeSponsorshipOpSigner",
            Self::ClawbackOp(_) => "ClawbackOp",
            Self::ClawbackClaimableBalanceOp(_) => "ClawbackClaimableBalanceOp",
            Self::SetTrustLineFlagsOp(_) => "SetTrustLineFlagsOp",
            Self::LiquidityPoolDepositOp(_) => "LiquidityPoolDepositOp",
            Self::LiquidityPoolWithdrawOp(_) => "LiquidityPoolWithdrawOp",
            Self::HostFunctionType(_) => "HostFunctionType",
            Self::ContractIdType(_) => "ContractIdType",
            Self::ContractIdPublicKeyType(_) => "ContractIdPublicKeyType",
            Self::InstallContractCodeArgs(_) => "InstallContractCodeArgs",
            Self::ContractId(_) => "ContractId",
            Self::ContractIdFromEd25519PublicKey(_) => "ContractIdFromEd25519PublicKey",
            Self::CreateContractArgs(_) => "CreateContractArgs",
            Self::HostFunction(_) => "HostFunction",
            Self::InvokeHostFunctionOp(_) => "InvokeHostFunctionOp",
            Self::Operation(_) => "Operation",
            Self::OperationBody(_) => "OperationBody",
            Self::HashIdPreimage(_) => "HashIdPreimage",
            Self::HashIdPreimageOperationId(_) => "HashIdPreimageOperationId",
            Self::HashIdPreimageRevokeId(_) => "HashIdPreimageRevokeId",
            Self::HashIdPreimageEd25519ContractId(_) => "HashIdPreimageEd25519ContractId",
            Self::HashIdPreimageContractId(_) => "HashIdPreimageContractId",
            Self::HashIdPreimageFromAsset(_) => "HashIdPreimageFromAsset",
            Self::HashIdPreimageSourceAccountContractId(_) => {
                "HashIdPreimageSourceAccountContractId"
            }
            Self::HashIdPreimageCreateContractArgs(_) => "HashIdPreimageCreateContractArgs",
            Self::MemoType(_) => "MemoType",
            Self::Memo(_) => "Memo",
            Self::TimeBounds(_) => "TimeBounds",
            Self::LedgerBounds(_) => "LedgerBounds",
            Self::PreconditionsV2(_) => "PreconditionsV2",
            Self::PreconditionType(_) => "PreconditionType",
            Self::Preconditions(_) => "Preconditions",
            Self::TransactionV0(_) => "TransactionV0",
            Self::TransactionV0Ext(_) => "TransactionV0Ext",
            Self::TransactionV0Envelope(_) => "TransactionV0Envelope",
            Self::Transaction(_) => "Transaction",
            Self::TransactionExt(_) => "TransactionExt",
            Self::TransactionV1Envelope(_) => "TransactionV1Envelope",
            Self::FeeBumpTransaction(_) => "FeeBumpTransaction",
            Self::FeeBumpTransactionInnerTx(_) => "FeeBumpTransactionInnerTx",
            Self::FeeBumpTransactionExt(_) => "FeeBumpTransactionExt",
            Self::FeeBumpTransactionEnvelope(_) => "FeeBumpTransactionEnvelope",
            Self::TransactionEnvelope(_) => "TransactionEnvelope",
            Self::TransactionSignaturePayload(_) => "TransactionSignaturePayload",
            Self::TransactionSignaturePayloadTaggedTransaction(_) => {
                "TransactionSignaturePayloadTaggedTransaction"
            }
            Self::ClaimAtomType(_) => "ClaimAtomType",
            Self::ClaimOfferAtomV0(_) => "ClaimOfferAtomV0",
            Self::ClaimOfferAtom(_) => "ClaimOfferAtom",
            Self::ClaimLiquidityAtom(_) => "ClaimLiquidityAtom",
            Self::ClaimAtom(_) => "ClaimAtom",
            Self::CreateAccountResultCode(_) => "CreateAccountResultCode",
            Self::CreateAccountResult(_) => "CreateAccountResult",
            Self::PaymentResultCode(_) => "PaymentResultCode",
            Self::PaymentResult(_) => "PaymentResult",
            Self::PathPaymentStrictReceiveResultCode(_) => "PathPaymentStrictReceiveResultCode",
            Self::SimplePaymentResult(_) => "SimplePaymentResult",
            Self::PathPaymentStrictReceiveResult(_) => "PathPaymentStrictReceiveResult",
            Self::PathPaymentStrictReceiveResultSuccess(_) => {
                "PathPaymentStrictReceiveResultSuccess"
            }
            Self::PathPaymentStrictSendResultCode(_) => "PathPaymentStrictSendResultCode",
            Self::PathPaymentStrictSendResult(_) => "PathPaymentStrictSendResult",
            Self::PathPaymentStrictSendResultSuccess(_) => "PathPaymentStrictSendResultSuccess",
            Self::ManageSellOfferResultCode(_) => "ManageSellOfferResultCode",
            Self::ManageOfferEffect(_) => "ManageOfferEffect",
            Self::ManageOfferSuccessResult(_) => "ManageOfferSuccessResult",
            Self::ManageOfferSuccessResultOffer(_) => "ManageOfferSuccessResultOffer",
            Self::ManageSellOfferResult(_) => "ManageSellOfferResult",
            Self::ManageBuyOfferResultCode(_) => "ManageBuyOfferResultCode",
            Self::ManageBuyOfferResult(_) => "ManageBuyOfferResult",
            Self::SetOptionsResultCode(_) => "SetOptionsResultCode",
            Self::SetOptionsResult(_) => "SetOptionsResult",
            Self::ChangeTrustResultCode(_) => "ChangeTrustResultCode",
            Self::ChangeTrustResult(_) => "ChangeTrustResult",
            Self::AllowTrustResultCode(_) => "AllowTrustResultCode",
            Self::AllowTrustResult(_) => "AllowTrustResult",
            Self::AccountMergeResultCode(_) => "AccountMergeResultCode",
            Self::AccountMergeResult(_) => "AccountMergeResult",
            Self::InflationResultCode(_) => "InflationResultCode",
            Self::InflationPayout(_) => "InflationPayout",
            Self::InflationResult(_) => "InflationResult",
            Self::ManageDataResultCode(_) => "ManageDataResultCode",
            Self::ManageDataResult(_) => "ManageDataResult",
            Self::BumpSequenceResultCode(_) => "BumpSequenceResultCode",
            Self::BumpSequenceResult(_) => "BumpSequenceResult",
            Self::CreateClaimableBalanceResultCode(_) => "CreateClaimableBalanceResultCode",
            Self::CreateClaimableBalanceResult(_) => "CreateClaimableBalanceResult",
            Self::ClaimClaimableBalanceResultCode(_) => "ClaimClaimableBalanceResultCode",
            Self::ClaimClaimableBalanceResult(_) => "ClaimClaimableBalanceResult",
            Self::BeginSponsoringFutureReservesResultCode(_) => {
                "BeginSponsoringFutureReservesResultCode"
            }
            Self::BeginSponsoringFutureReservesResult(_) => "BeginSponsoringFutureReservesResult",
            Self::EndSponsoringFutureReservesResultCode(_) => {
                "EndSponsoringFutureReservesResultCode"
            }
            Self::EndSponsoringFutureReservesResult(_) => "EndSponsoringFutureReservesResult",
            Self::RevokeSponsorshipResultCode(_) => "RevokeSponsorshipResultCode",
            Self::RevokeSponsorshipResult(_) => "RevokeSponsorshipResult",
            Self::ClawbackResultCode(_) => "ClawbackResultCode",
            Self::ClawbackResult(_) => "ClawbackResult",
            Self::ClawbackClaimableBalanceResultCode(_) => "ClawbackClaimableBalanceResultCode",
            Self::ClawbackClaimableBalanceResult(_) => "ClawbackClaimableBalanceResult",
            Self::SetTrustLineFlagsResultCode(_) => "SetTrustLineFlagsResultCode",
            Self::SetTrustLineFlagsResult(_) => "SetTrustLineFlagsResult",
            Self::LiquidityPoolDepositResultCode(_) => "LiquidityPoolDepositResultCode",
            Self::LiquidityPoolDepositResult(_) => "LiquidityPoolDepositResult",
            Self::LiquidityPoolWithdrawResultCode(_) => "LiquidityPoolWithdrawResultCode",
            Self::LiquidityPoolWithdrawResult(_) => "LiquidityPoolWithdrawResult",
            Self::InvokeHostFunctionResultCode(_) => "InvokeHostFunctionResultCode",
            Self::InvokeHostFunctionResult(_) => "InvokeHostFunctionResult",
            Self::OperationResultCode(_) => "OperationResultCode",
            Self::OperationResult(_) => "OperationResult",
            Self::OperationResultTr(_) => "OperationResultTr",
            Self::TransactionResultCode(_) => "TransactionResultCode",
            Self::InnerTransactionResult(_) => "InnerTransactionResult",
            Self::InnerTransactionResultResult(_) => "InnerTransactionResultResult",
            Self::InnerTransactionResultExt(_) => "InnerTransactionResultExt",
            Self::InnerTransactionResultPair(_) => "InnerTransactionResultPair",
            Self::TransactionResult(_) => "TransactionResult",
            Self::TransactionResultResult(_) => "TransactionResultResult",
            Self::TransactionResultExt(_) => "TransactionResultExt",
            Self::Hash(_) => "Hash",
            Self::Uint256(_) => "Uint256",
            Self::Uint32(_) => "Uint32",
            Self::Int32(_) => "Int32",
            Self::Uint64(_) => "Uint64",
            Self::Int64(_) => "Int64",
            Self::ExtensionPoint(_) => "ExtensionPoint",
            Self::CryptoKeyType(_) => "CryptoKeyType",
            Self::PublicKeyType(_) => "PublicKeyType",
            Self::SignerKeyType(_) => "SignerKeyType",
            Self::PublicKey(_) => "PublicKey",
            Self::SignerKey(_) => "SignerKey",
            Self::SignerKeyEd25519SignedPayload(_) => "SignerKeyEd25519SignedPayload",
            Self::Signature(_) => "Signature",
            Self::SignatureHint(_) => "SignatureHint",
            Self::NodeId(_) => "NodeId",
            Self::AccountId(_) => "AccountId",
            Self::Curve25519Secret(_) => "Curve25519Secret",
            Self::Curve25519Public(_) => "Curve25519Public",
            Self::HmacSha256Key(_) => "HmacSha256Key",
            Self::HmacSha256Mac(_) => "HmacSha256Mac",
        }
    }

    #[must_use]
    #[allow(clippy::too_many_lines)]
    pub const fn variants() -> [TypeVariant; 390] {
        Self::VARIANTS
    }

    #[must_use]
    #[allow(clippy::too_many_lines)]
    pub const fn variant(&self) -> TypeVariant {
        match self {
            Self::Value(_) => TypeVariant::Value,
            Self::ScpBallot(_) => TypeVariant::ScpBallot,
            Self::ScpStatementType(_) => TypeVariant::ScpStatementType,
            Self::ScpNomination(_) => TypeVariant::ScpNomination,
            Self::ScpStatement(_) => TypeVariant::ScpStatement,
            Self::ScpStatementPledges(_) => TypeVariant::ScpStatementPledges,
            Self::ScpStatementPrepare(_) => TypeVariant::ScpStatementPrepare,
            Self::ScpStatementConfirm(_) => TypeVariant::ScpStatementConfirm,
            Self::ScpStatementExternalize(_) => TypeVariant::ScpStatementExternalize,
            Self::ScpEnvelope(_) => TypeVariant::ScpEnvelope,
            Self::ScpQuorumSet(_) => TypeVariant::ScpQuorumSet,
            Self::ScEnvMetaKind(_) => TypeVariant::ScEnvMetaKind,
            Self::ScEnvMetaEntry(_) => TypeVariant::ScEnvMetaEntry,
            Self::ScSpecType(_) => TypeVariant::ScSpecType,
            Self::ScSpecTypeOption(_) => TypeVariant::ScSpecTypeOption,
            Self::ScSpecTypeResult(_) => TypeVariant::ScSpecTypeResult,
            Self::ScSpecTypeVec(_) => TypeVariant::ScSpecTypeVec,
            Self::ScSpecTypeMap(_) => TypeVariant::ScSpecTypeMap,
            Self::ScSpecTypeSet(_) => TypeVariant::ScSpecTypeSet,
            Self::ScSpecTypeTuple(_) => TypeVariant::ScSpecTypeTuple,
            Self::ScSpecTypeBytesN(_) => TypeVariant::ScSpecTypeBytesN,
            Self::ScSpecTypeUdt(_) => TypeVariant::ScSpecTypeUdt,
            Self::ScSpecTypeDef(_) => TypeVariant::ScSpecTypeDef,
            Self::ScSpecUdtStructFieldV0(_) => TypeVariant::ScSpecUdtStructFieldV0,
            Self::ScSpecUdtStructV0(_) => TypeVariant::ScSpecUdtStructV0,
            Self::ScSpecUdtUnionCaseV0(_) => TypeVariant::ScSpecUdtUnionCaseV0,
            Self::ScSpecUdtUnionV0(_) => TypeVariant::ScSpecUdtUnionV0,
            Self::ScSpecUdtEnumCaseV0(_) => TypeVariant::ScSpecUdtEnumCaseV0,
            Self::ScSpecUdtEnumV0(_) => TypeVariant::ScSpecUdtEnumV0,
            Self::ScSpecUdtErrorEnumCaseV0(_) => TypeVariant::ScSpecUdtErrorEnumCaseV0,
            Self::ScSpecUdtErrorEnumV0(_) => TypeVariant::ScSpecUdtErrorEnumV0,
            Self::ScSpecFunctionInputV0(_) => TypeVariant::ScSpecFunctionInputV0,
            Self::ScSpecFunctionV0(_) => TypeVariant::ScSpecFunctionV0,
            Self::ScSpecEntryKind(_) => TypeVariant::ScSpecEntryKind,
            Self::ScSpecEntry(_) => TypeVariant::ScSpecEntry,
            Self::ScSymbol(_) => TypeVariant::ScSymbol,
            Self::ScValType(_) => TypeVariant::ScValType,
            Self::ScStatic(_) => TypeVariant::ScStatic,
            Self::ScStatusType(_) => TypeVariant::ScStatusType,
            Self::ScHostValErrorCode(_) => TypeVariant::ScHostValErrorCode,
            Self::ScHostObjErrorCode(_) => TypeVariant::ScHostObjErrorCode,
            Self::ScHostFnErrorCode(_) => TypeVariant::ScHostFnErrorCode,
            Self::ScHostStorageErrorCode(_) => TypeVariant::ScHostStorageErrorCode,
            Self::ScHostContextErrorCode(_) => TypeVariant::ScHostContextErrorCode,
            Self::ScVmErrorCode(_) => TypeVariant::ScVmErrorCode,
            Self::ScUnknownErrorCode(_) => TypeVariant::ScUnknownErrorCode,
            Self::ScStatus(_) => TypeVariant::ScStatus,
            Self::ScVal(_) => TypeVariant::ScVal,
            Self::ScObjectType(_) => TypeVariant::ScObjectType,
            Self::ScMapEntry(_) => TypeVariant::ScMapEntry,
            Self::ScVec(_) => TypeVariant::ScVec,
            Self::ScMap(_) => TypeVariant::ScMap,
            Self::ScContractCodeType(_) => TypeVariant::ScContractCodeType,
            Self::ScContractCode(_) => TypeVariant::ScContractCode,
            Self::Int128Parts(_) => TypeVariant::Int128Parts,
            Self::ScObject(_) => TypeVariant::ScObject,
            Self::StoredTransactionSet(_) => TypeVariant::StoredTransactionSet,
            Self::PersistedScpStateV0(_) => TypeVariant::PersistedScpStateV0,
            Self::PersistedScpStateV1(_) => TypeVariant::PersistedScpStateV1,
            Self::PersistedScpState(_) => TypeVariant::PersistedScpState,
            Self::Thresholds(_) => TypeVariant::Thresholds,
            Self::String32(_) => TypeVariant::String32,
            Self::String64(_) => TypeVariant::String64,
            Self::SequenceNumber(_) => TypeVariant::SequenceNumber,
            Self::TimePoint(_) => TypeVariant::TimePoint,
            Self::Duration(_) => TypeVariant::Duration,
            Self::DataValue(_) => TypeVariant::DataValue,
            Self::PoolId(_) => TypeVariant::PoolId,
            Self::AssetCode4(_) => TypeVariant::AssetCode4,
            Self::AssetCode12(_) => TypeVariant::AssetCode12,
            Self::AssetType(_) => TypeVariant::AssetType,
            Self::AssetCode(_) => TypeVariant::AssetCode,
            Self::AlphaNum4(_) => TypeVariant::AlphaNum4,
            Self::AlphaNum12(_) => TypeVariant::AlphaNum12,
            Self::Asset(_) => TypeVariant::Asset,
            Self::Price(_) => TypeVariant::Price,
            Self::Liabilities(_) => TypeVariant::Liabilities,
            Self::ThresholdIndexes(_) => TypeVariant::ThresholdIndexes,
            Self::LedgerEntryType(_) => TypeVariant::LedgerEntryType,
            Self::Signer(_) => TypeVariant::Signer,
            Self::AccountFlags(_) => TypeVariant::AccountFlags,
            Self::SponsorshipDescriptor(_) => TypeVariant::SponsorshipDescriptor,
            Self::AccountEntryExtensionV3(_) => TypeVariant::AccountEntryExtensionV3,
            Self::AccountEntryExtensionV2(_) => TypeVariant::AccountEntryExtensionV2,
            Self::AccountEntryExtensionV2Ext(_) => TypeVariant::AccountEntryExtensionV2Ext,
            Self::AccountEntryExtensionV1(_) => TypeVariant::AccountEntryExtensionV1,
            Self::AccountEntryExtensionV1Ext(_) => TypeVariant::AccountEntryExtensionV1Ext,
            Self::AccountEntry(_) => TypeVariant::AccountEntry,
            Self::AccountEntryExt(_) => TypeVariant::AccountEntryExt,
            Self::TrustLineFlags(_) => TypeVariant::TrustLineFlags,
            Self::LiquidityPoolType(_) => TypeVariant::LiquidityPoolType,
            Self::TrustLineAsset(_) => TypeVariant::TrustLineAsset,
            Self::TrustLineEntryExtensionV2(_) => TypeVariant::TrustLineEntryExtensionV2,
            Self::TrustLineEntryExtensionV2Ext(_) => TypeVariant::TrustLineEntryExtensionV2Ext,
            Self::TrustLineEntry(_) => TypeVariant::TrustLineEntry,
            Self::TrustLineEntryExt(_) => TypeVariant::TrustLineEntryExt,
            Self::TrustLineEntryV1(_) => TypeVariant::TrustLineEntryV1,
            Self::TrustLineEntryV1Ext(_) => TypeVariant::TrustLineEntryV1Ext,
            Self::OfferEntryFlags(_) => TypeVariant::OfferEntryFlags,
            Self::OfferEntry(_) => TypeVariant::OfferEntry,
            Self::OfferEntryExt(_) => TypeVariant::OfferEntryExt,
            Self::DataEntry(_) => TypeVariant::DataEntry,
            Self::DataEntryExt(_) => TypeVariant::DataEntryExt,
            Self::ClaimPredicateType(_) => TypeVariant::ClaimPredicateType,
            Self::ClaimPredicate(_) => TypeVariant::ClaimPredicate,
            Self::ClaimantType(_) => TypeVariant::ClaimantType,
            Self::Claimant(_) => TypeVariant::Claimant,
            Self::ClaimantV0(_) => TypeVariant::ClaimantV0,
            Self::ClaimableBalanceIdType(_) => TypeVariant::ClaimableBalanceIdType,
            Self::ClaimableBalanceId(_) => TypeVariant::ClaimableBalanceId,
            Self::ClaimableBalanceFlags(_) => TypeVariant::ClaimableBalanceFlags,
            Self::ClaimableBalanceEntryExtensionV1(_) => {
                TypeVariant::ClaimableBalanceEntryExtensionV1
            }
            Self::ClaimableBalanceEntryExtensionV1Ext(_) => {
                TypeVariant::ClaimableBalanceEntryExtensionV1Ext
            }
            Self::ClaimableBalanceEntry(_) => TypeVariant::ClaimableBalanceEntry,
            Self::ClaimableBalanceEntryExt(_) => TypeVariant::ClaimableBalanceEntryExt,
            Self::LiquidityPoolConstantProductParameters(_) => {
                TypeVariant::LiquidityPoolConstantProductParameters
            }
            Self::LiquidityPoolEntry(_) => TypeVariant::LiquidityPoolEntry,
            Self::LiquidityPoolEntryBody(_) => TypeVariant::LiquidityPoolEntryBody,
            Self::LiquidityPoolEntryConstantProduct(_) => {
                TypeVariant::LiquidityPoolEntryConstantProduct
            }
            Self::ContractDataEntry(_) => TypeVariant::ContractDataEntry,
            Self::ContractCodeEntry(_) => TypeVariant::ContractCodeEntry,
            Self::ConfigSettingType(_) => TypeVariant::ConfigSettingType,
            Self::ConfigSetting(_) => TypeVariant::ConfigSetting,
            Self::ConfigSettingId(_) => TypeVariant::ConfigSettingId,
            Self::ConfigSettingEntry(_) => TypeVariant::ConfigSettingEntry,
            Self::ConfigSettingEntryExt(_) => TypeVariant::ConfigSettingEntryExt,
            Self::LedgerEntryExtensionV1(_) => TypeVariant::LedgerEntryExtensionV1,
            Self::LedgerEntryExtensionV1Ext(_) => TypeVariant::LedgerEntryExtensionV1Ext,
            Self::LedgerEntry(_) => TypeVariant::LedgerEntry,
            Self::LedgerEntryData(_) => TypeVariant::LedgerEntryData,
            Self::LedgerEntryExt(_) => TypeVariant::LedgerEntryExt,
            Self::LedgerKey(_) => TypeVariant::LedgerKey,
            Self::LedgerKeyAccount(_) => TypeVariant::LedgerKeyAccount,
            Self::LedgerKeyTrustLine(_) => TypeVariant::LedgerKeyTrustLine,
            Self::LedgerKeyOffer(_) => TypeVariant::LedgerKeyOffer,
            Self::LedgerKeyData(_) => TypeVariant::LedgerKeyData,
            Self::LedgerKeyClaimableBalance(_) => TypeVariant::LedgerKeyClaimableBalance,
            Self::LedgerKeyLiquidityPool(_) => TypeVariant::LedgerKeyLiquidityPool,
            Self::LedgerKeyContractData(_) => TypeVariant::LedgerKeyContractData,
            Self::LedgerKeyContractCode(_) => TypeVariant::LedgerKeyContractCode,
            Self::LedgerKeyConfigSetting(_) => TypeVariant::LedgerKeyConfigSetting,
            Self::EnvelopeType(_) => TypeVariant::EnvelopeType,
            Self::UpgradeType(_) => TypeVariant::UpgradeType,
            Self::StellarValueType(_) => TypeVariant::StellarValueType,
            Self::LedgerCloseValueSignature(_) => TypeVariant::LedgerCloseValueSignature,
            Self::StellarValue(_) => TypeVariant::StellarValue,
            Self::StellarValueExt(_) => TypeVariant::StellarValueExt,
            Self::LedgerHeaderFlags(_) => TypeVariant::LedgerHeaderFlags,
            Self::LedgerHeaderExtensionV1(_) => TypeVariant::LedgerHeaderExtensionV1,
            Self::LedgerHeaderExtensionV1Ext(_) => TypeVariant::LedgerHeaderExtensionV1Ext,
            Self::LedgerHeader(_) => TypeVariant::LedgerHeader,
            Self::LedgerHeaderExt(_) => TypeVariant::LedgerHeaderExt,
            Self::LedgerUpgradeType(_) => TypeVariant::LedgerUpgradeType,
            Self::LedgerUpgrade(_) => TypeVariant::LedgerUpgrade,
            Self::LedgerUpgradeConfigSetting(_) => TypeVariant::LedgerUpgradeConfigSetting,
            Self::BucketEntryType(_) => TypeVariant::BucketEntryType,
            Self::BucketMetadata(_) => TypeVariant::BucketMetadata,
            Self::BucketMetadataExt(_) => TypeVariant::BucketMetadataExt,
            Self::BucketEntry(_) => TypeVariant::BucketEntry,
            Self::TxSetComponentType(_) => TypeVariant::TxSetComponentType,
            Self::TxSetComponent(_) => TypeVariant::TxSetComponent,
            Self::TxSetComponentTxsMaybeDiscountedFee(_) => {
                TypeVariant::TxSetComponentTxsMaybeDiscountedFee
            }
            Self::TransactionPhase(_) => TypeVariant::TransactionPhase,
            Self::TransactionSet(_) => TypeVariant::TransactionSet,
            Self::TransactionSetV1(_) => TypeVariant::TransactionSetV1,
            Self::GeneralizedTransactionSet(_) => TypeVariant::GeneralizedTransactionSet,
            Self::TransactionResultPair(_) => TypeVariant::TransactionResultPair,
            Self::TransactionResultSet(_) => TypeVariant::TransactionResultSet,
            Self::TransactionHistoryEntry(_) => TypeVariant::TransactionHistoryEntry,
            Self::TransactionHistoryEntryExt(_) => TypeVariant::TransactionHistoryEntryExt,
            Self::TransactionHistoryResultEntry(_) => TypeVariant::TransactionHistoryResultEntry,
            Self::TransactionHistoryResultEntryExt(_) => {
                TypeVariant::TransactionHistoryResultEntryExt
            }
            Self::TransactionResultPairV2(_) => TypeVariant::TransactionResultPairV2,
            Self::TransactionResultSetV2(_) => TypeVariant::TransactionResultSetV2,
            Self::TransactionHistoryResultEntryV2(_) => {
                TypeVariant::TransactionHistoryResultEntryV2
            }
            Self::TransactionHistoryResultEntryV2Ext(_) => {
                TypeVariant::TransactionHistoryResultEntryV2Ext
            }
            Self::LedgerHeaderHistoryEntry(_) => TypeVariant::LedgerHeaderHistoryEntry,
            Self::LedgerHeaderHistoryEntryExt(_) => TypeVariant::LedgerHeaderHistoryEntryExt,
            Self::LedgerScpMessages(_) => TypeVariant::LedgerScpMessages,
            Self::ScpHistoryEntryV0(_) => TypeVariant::ScpHistoryEntryV0,
            Self::ScpHistoryEntry(_) => TypeVariant::ScpHistoryEntry,
            Self::LedgerEntryChangeType(_) => TypeVariant::LedgerEntryChangeType,
            Self::LedgerEntryChange(_) => TypeVariant::LedgerEntryChange,
            Self::LedgerEntryChanges(_) => TypeVariant::LedgerEntryChanges,
            Self::OperationMeta(_) => TypeVariant::OperationMeta,
            Self::TransactionMetaV1(_) => TypeVariant::TransactionMetaV1,
            Self::TransactionMetaV2(_) => TypeVariant::TransactionMetaV2,
            Self::ContractEventType(_) => TypeVariant::ContractEventType,
            Self::ContractEvent(_) => TypeVariant::ContractEvent,
            Self::ContractEventBody(_) => TypeVariant::ContractEventBody,
            Self::ContractEventV0(_) => TypeVariant::ContractEventV0,
            Self::OperationEvents(_) => TypeVariant::OperationEvents,
            Self::TransactionMetaV3(_) => TypeVariant::TransactionMetaV3,
            Self::TransactionMeta(_) => TypeVariant::TransactionMeta,
            Self::TransactionResultMeta(_) => TypeVariant::TransactionResultMeta,
            Self::TransactionResultMetaV2(_) => TypeVariant::TransactionResultMetaV2,
            Self::UpgradeEntryMeta(_) => TypeVariant::UpgradeEntryMeta,
            Self::LedgerCloseMetaV0(_) => TypeVariant::LedgerCloseMetaV0,
            Self::LedgerCloseMetaV1(_) => TypeVariant::LedgerCloseMetaV1,
            Self::LedgerCloseMetaV2(_) => TypeVariant::LedgerCloseMetaV2,
            Self::LedgerCloseMeta(_) => TypeVariant::LedgerCloseMeta,
            Self::ErrorCode(_) => TypeVariant::ErrorCode,
            Self::SError(_) => TypeVariant::SError,
            Self::SendMore(_) => TypeVariant::SendMore,
            Self::AuthCert(_) => TypeVariant::AuthCert,
            Self::Hello(_) => TypeVariant::Hello,
            Self::Auth(_) => TypeVariant::Auth,
            Self::IpAddrType(_) => TypeVariant::IpAddrType,
            Self::PeerAddress(_) => TypeVariant::PeerAddress,
            Self::PeerAddressIp(_) => TypeVariant::PeerAddressIp,
            Self::MessageType(_) => TypeVariant::MessageType,
            Self::DontHave(_) => TypeVariant::DontHave,
            Self::SurveyMessageCommandType(_) => TypeVariant::SurveyMessageCommandType,
            Self::SurveyRequestMessage(_) => TypeVariant::SurveyRequestMessage,
            Self::SignedSurveyRequestMessage(_) => TypeVariant::SignedSurveyRequestMessage,
            Self::EncryptedBody(_) => TypeVariant::EncryptedBody,
            Self::SurveyResponseMessage(_) => TypeVariant::SurveyResponseMessage,
            Self::SignedSurveyResponseMessage(_) => TypeVariant::SignedSurveyResponseMessage,
            Self::PeerStats(_) => TypeVariant::PeerStats,
            Self::PeerStatList(_) => TypeVariant::PeerStatList,
            Self::TopologyResponseBody(_) => TypeVariant::TopologyResponseBody,
            Self::SurveyResponseBody(_) => TypeVariant::SurveyResponseBody,
            Self::TxAdvertVector(_) => TypeVariant::TxAdvertVector,
            Self::FloodAdvert(_) => TypeVariant::FloodAdvert,
            Self::TxDemandVector(_) => TypeVariant::TxDemandVector,
            Self::FloodDemand(_) => TypeVariant::FloodDemand,
            Self::StellarMessage(_) => TypeVariant::StellarMessage,
            Self::AuthenticatedMessage(_) => TypeVariant::AuthenticatedMessage,
            Self::AuthenticatedMessageV0(_) => TypeVariant::AuthenticatedMessageV0,
            Self::LiquidityPoolParameters(_) => TypeVariant::LiquidityPoolParameters,
            Self::MuxedAccount(_) => TypeVariant::MuxedAccount,
            Self::MuxedAccountMed25519(_) => TypeVariant::MuxedAccountMed25519,
            Self::DecoratedSignature(_) => TypeVariant::DecoratedSignature,
            Self::LedgerFootprint(_) => TypeVariant::LedgerFootprint,
            Self::OperationType(_) => TypeVariant::OperationType,
            Self::CreateAccountOp(_) => TypeVariant::CreateAccountOp,
            Self::PaymentOp(_) => TypeVariant::PaymentOp,
            Self::PathPaymentStrictReceiveOp(_) => TypeVariant::PathPaymentStrictReceiveOp,
            Self::PathPaymentStrictSendOp(_) => TypeVariant::PathPaymentStrictSendOp,
            Self::ManageSellOfferOp(_) => TypeVariant::ManageSellOfferOp,
            Self::ManageBuyOfferOp(_) => TypeVariant::ManageBuyOfferOp,
            Self::CreatePassiveSellOfferOp(_) => TypeVariant::CreatePassiveSellOfferOp,
            Self::SetOptionsOp(_) => TypeVariant::SetOptionsOp,
            Self::ChangeTrustAsset(_) => TypeVariant::ChangeTrustAsset,
            Self::ChangeTrustOp(_) => TypeVariant::ChangeTrustOp,
            Self::AllowTrustOp(_) => TypeVariant::AllowTrustOp,
            Self::ManageDataOp(_) => TypeVariant::ManageDataOp,
            Self::BumpSequenceOp(_) => TypeVariant::BumpSequenceOp,
            Self::CreateClaimableBalanceOp(_) => TypeVariant::CreateClaimableBalanceOp,
            Self::ClaimClaimableBalanceOp(_) => TypeVariant::ClaimClaimableBalanceOp,
            Self::BeginSponsoringFutureReservesOp(_) => {
                TypeVariant::BeginSponsoringFutureReservesOp
            }
            Self::RevokeSponsorshipType(_) => TypeVariant::RevokeSponsorshipType,
            Self::RevokeSponsorshipOp(_) => TypeVariant::RevokeSponsorshipOp,
            Self::RevokeSponsorshipOpSigner(_) => TypeVariant::RevokeSponsorshipOpSigner,
            Self::ClawbackOp(_) => TypeVariant::ClawbackOp,
            Self::ClawbackClaimableBalanceOp(_) => TypeVariant::ClawbackClaimableBalanceOp,
            Self::SetTrustLineFlagsOp(_) => TypeVariant::SetTrustLineFlagsOp,
            Self::LiquidityPoolDepositOp(_) => TypeVariant::LiquidityPoolDepositOp,
            Self::LiquidityPoolWithdrawOp(_) => TypeVariant::LiquidityPoolWithdrawOp,
            Self::HostFunctionType(_) => TypeVariant::HostFunctionType,
            Self::ContractIdType(_) => TypeVariant::ContractIdType,
            Self::ContractIdPublicKeyType(_) => TypeVariant::ContractIdPublicKeyType,
            Self::InstallContractCodeArgs(_) => TypeVariant::InstallContractCodeArgs,
            Self::ContractId(_) => TypeVariant::ContractId,
            Self::ContractIdFromEd25519PublicKey(_) => TypeVariant::ContractIdFromEd25519PublicKey,
            Self::CreateContractArgs(_) => TypeVariant::CreateContractArgs,
            Self::HostFunction(_) => TypeVariant::HostFunction,
            Self::InvokeHostFunctionOp(_) => TypeVariant::InvokeHostFunctionOp,
            Self::Operation(_) => TypeVariant::Operation,
            Self::OperationBody(_) => TypeVariant::OperationBody,
            Self::HashIdPreimage(_) => TypeVariant::HashIdPreimage,
            Self::HashIdPreimageOperationId(_) => TypeVariant::HashIdPreimageOperationId,
            Self::HashIdPreimageRevokeId(_) => TypeVariant::HashIdPreimageRevokeId,
            Self::HashIdPreimageEd25519ContractId(_) => {
                TypeVariant::HashIdPreimageEd25519ContractId
            }
            Self::HashIdPreimageContractId(_) => TypeVariant::HashIdPreimageContractId,
            Self::HashIdPreimageFromAsset(_) => TypeVariant::HashIdPreimageFromAsset,
            Self::HashIdPreimageSourceAccountContractId(_) => {
                TypeVariant::HashIdPreimageSourceAccountContractId
            }
            Self::HashIdPreimageCreateContractArgs(_) => {
                TypeVariant::HashIdPreimageCreateContractArgs
            }
            Self::MemoType(_) => TypeVariant::MemoType,
            Self::Memo(_) => TypeVariant::Memo,
            Self::TimeBounds(_) => TypeVariant::TimeBounds,
            Self::LedgerBounds(_) => TypeVariant::LedgerBounds,
            Self::PreconditionsV2(_) => TypeVariant::PreconditionsV2,
            Self::PreconditionType(_) => TypeVariant::PreconditionType,
            Self::Preconditions(_) => TypeVariant::Preconditions,
            Self::TransactionV0(_) => TypeVariant::TransactionV0,
            Self::TransactionV0Ext(_) => TypeVariant::TransactionV0Ext,
            Self::TransactionV0Envelope(_) => TypeVariant::TransactionV0Envelope,
            Self::Transaction(_) => TypeVariant::Transaction,
            Self::TransactionExt(_) => TypeVariant::TransactionExt,
            Self::TransactionV1Envelope(_) => TypeVariant::TransactionV1Envelope,
            Self::FeeBumpTransaction(_) => TypeVariant::FeeBumpTransaction,
            Self::FeeBumpTransactionInnerTx(_) => TypeVariant::FeeBumpTransactionInnerTx,
            Self::FeeBumpTransactionExt(_) => TypeVariant::FeeBumpTransactionExt,
            Self::FeeBumpTransactionEnvelope(_) => TypeVariant::FeeBumpTransactionEnvelope,
            Self::TransactionEnvelope(_) => TypeVariant::TransactionEnvelope,
            Self::TransactionSignaturePayload(_) => TypeVariant::TransactionSignaturePayload,
            Self::TransactionSignaturePayloadTaggedTransaction(_) => {
                TypeVariant::TransactionSignaturePayloadTaggedTransaction
            }
            Self::ClaimAtomType(_) => TypeVariant::ClaimAtomType,
            Self::ClaimOfferAtomV0(_) => TypeVariant::ClaimOfferAtomV0,
            Self::ClaimOfferAtom(_) => TypeVariant::ClaimOfferAtom,
            Self::ClaimLiquidityAtom(_) => TypeVariant::ClaimLiquidityAtom,
            Self::ClaimAtom(_) => TypeVariant::ClaimAtom,
            Self::CreateAccountResultCode(_) => TypeVariant::CreateAccountResultCode,
            Self::CreateAccountResult(_) => TypeVariant::CreateAccountResult,
            Self::PaymentResultCode(_) => TypeVariant::PaymentResultCode,
            Self::PaymentResult(_) => TypeVariant::PaymentResult,
            Self::PathPaymentStrictReceiveResultCode(_) => {
                TypeVariant::PathPaymentStrictReceiveResultCode
            }
            Self::SimplePaymentResult(_) => TypeVariant::SimplePaymentResult,
            Self::PathPaymentStrictReceiveResult(_) => TypeVariant::PathPaymentStrictReceiveResult,
            Self::PathPaymentStrictReceiveResultSuccess(_) => {
                TypeVariant::PathPaymentStrictReceiveResultSuccess
            }
            Self::PathPaymentStrictSendResultCode(_) => {
                TypeVariant::PathPaymentStrictSendResultCode
            }
            Self::PathPaymentStrictSendResult(_) => TypeVariant::PathPaymentStrictSendResult,
            Self::PathPaymentStrictSendResultSuccess(_) => {
                TypeVariant::PathPaymentStrictSendResultSuccess
            }
            Self::ManageSellOfferResultCode(_) => TypeVariant::ManageSellOfferResultCode,
            Self::ManageOfferEffect(_) => TypeVariant::ManageOfferEffect,
            Self::ManageOfferSuccessResult(_) => TypeVariant::ManageOfferSuccessResult,
            Self::ManageOfferSuccessResultOffer(_) => TypeVariant::ManageOfferSuccessResultOffer,
            Self::ManageSellOfferResult(_) => TypeVariant::ManageSellOfferResult,
            Self::ManageBuyOfferResultCode(_) => TypeVariant::ManageBuyOfferResultCode,
            Self::ManageBuyOfferResult(_) => TypeVariant::ManageBuyOfferResult,
            Self::SetOptionsResultCode(_) => TypeVariant::SetOptionsResultCode,
            Self::SetOptionsResult(_) => TypeVariant::SetOptionsResult,
            Self::ChangeTrustResultCode(_) => TypeVariant::ChangeTrustResultCode,
            Self::ChangeTrustResult(_) => TypeVariant::ChangeTrustResult,
            Self::AllowTrustResultCode(_) => TypeVariant::AllowTrustResultCode,
            Self::AllowTrustResult(_) => TypeVariant::AllowTrustResult,
            Self::AccountMergeResultCode(_) => TypeVariant::AccountMergeResultCode,
            Self::AccountMergeResult(_) => TypeVariant::AccountMergeResult,
            Self::InflationResultCode(_) => TypeVariant::InflationResultCode,
            Self::InflationPayout(_) => TypeVariant::InflationPayout,
            Self::InflationResult(_) => TypeVariant::InflationResult,
            Self::ManageDataResultCode(_) => TypeVariant::ManageDataResultCode,
            Self::ManageDataResult(_) => TypeVariant::ManageDataResult,
            Self::BumpSequenceResultCode(_) => TypeVariant::BumpSequenceResultCode,
            Self::BumpSequenceResult(_) => TypeVariant::BumpSequenceResult,
            Self::CreateClaimableBalanceResultCode(_) => {
                TypeVariant::CreateClaimableBalanceResultCode
            }
            Self::CreateClaimableBalanceResult(_) => TypeVariant::CreateClaimableBalanceResult,
            Self::ClaimClaimableBalanceResultCode(_) => {
                TypeVariant::ClaimClaimableBalanceResultCode
            }
            Self::ClaimClaimableBalanceResult(_) => TypeVariant::ClaimClaimableBalanceResult,
            Self::BeginSponsoringFutureReservesResultCode(_) => {
                TypeVariant::BeginSponsoringFutureReservesResultCode
            }
            Self::BeginSponsoringFutureReservesResult(_) => {
                TypeVariant::BeginSponsoringFutureReservesResult
            }
            Self::EndSponsoringFutureReservesResultCode(_) => {
                TypeVariant::EndSponsoringFutureReservesResultCode
            }
            Self::EndSponsoringFutureReservesResult(_) => {
                TypeVariant::EndSponsoringFutureReservesResult
            }
            Self::RevokeSponsorshipResultCode(_) => TypeVariant::RevokeSponsorshipResultCode,
            Self::RevokeSponsorshipResult(_) => TypeVariant::RevokeSponsorshipResult,
            Self::ClawbackResultCode(_) => TypeVariant::ClawbackResultCode,
            Self::ClawbackResult(_) => TypeVariant::ClawbackResult,
            Self::ClawbackClaimableBalanceResultCode(_) => {
                TypeVariant::ClawbackClaimableBalanceResultCode
            }
            Self::ClawbackClaimableBalanceResult(_) => TypeVariant::ClawbackClaimableBalanceResult,
            Self::SetTrustLineFlagsResultCode(_) => TypeVariant::SetTrustLineFlagsResultCode,
            Self::SetTrustLineFlagsResult(_) => TypeVariant::SetTrustLineFlagsResult,
            Self::LiquidityPoolDepositResultCode(_) => TypeVariant::LiquidityPoolDepositResultCode,
            Self::LiquidityPoolDepositResult(_) => TypeVariant::LiquidityPoolDepositResult,
            Self::LiquidityPoolWithdrawResultCode(_) => {
                TypeVariant::LiquidityPoolWithdrawResultCode
            }
            Self::LiquidityPoolWithdrawResult(_) => TypeVariant::LiquidityPoolWithdrawResult,
            Self::InvokeHostFunctionResultCode(_) => TypeVariant::InvokeHostFunctionResultCode,
            Self::InvokeHostFunctionResult(_) => TypeVariant::InvokeHostFunctionResult,
            Self::OperationResultCode(_) => TypeVariant::OperationResultCode,
            Self::OperationResult(_) => TypeVariant::OperationResult,
            Self::OperationResultTr(_) => TypeVariant::OperationResultTr,
            Self::TransactionResultCode(_) => TypeVariant::TransactionResultCode,
            Self::InnerTransactionResult(_) => TypeVariant::InnerTransactionResult,
            Self::InnerTransactionResultResult(_) => TypeVariant::InnerTransactionResultResult,
            Self::InnerTransactionResultExt(_) => TypeVariant::InnerTransactionResultExt,
            Self::InnerTransactionResultPair(_) => TypeVariant::InnerTransactionResultPair,
            Self::TransactionResult(_) => TypeVariant::TransactionResult,
            Self::TransactionResultResult(_) => TypeVariant::TransactionResultResult,
            Self::TransactionResultExt(_) => TypeVariant::TransactionResultExt,
            Self::Hash(_) => TypeVariant::Hash,
            Self::Uint256(_) => TypeVariant::Uint256,
            Self::Uint32(_) => TypeVariant::Uint32,
            Self::Int32(_) => TypeVariant::Int32,
            Self::Uint64(_) => TypeVariant::Uint64,
            Self::Int64(_) => TypeVariant::Int64,
            Self::ExtensionPoint(_) => TypeVariant::ExtensionPoint,
            Self::CryptoKeyType(_) => TypeVariant::CryptoKeyType,
            Self::PublicKeyType(_) => TypeVariant::PublicKeyType,
            Self::SignerKeyType(_) => TypeVariant::SignerKeyType,
            Self::PublicKey(_) => TypeVariant::PublicKey,
            Self::SignerKey(_) => TypeVariant::SignerKey,
            Self::SignerKeyEd25519SignedPayload(_) => TypeVariant::SignerKeyEd25519SignedPayload,
            Self::Signature(_) => TypeVariant::Signature,
            Self::SignatureHint(_) => TypeVariant::SignatureHint,
            Self::NodeId(_) => TypeVariant::NodeId,
            Self::AccountId(_) => TypeVariant::AccountId,
            Self::Curve25519Secret(_) => TypeVariant::Curve25519Secret,
            Self::Curve25519Public(_) => TypeVariant::Curve25519Public,
            Self::HmacSha256Key(_) => TypeVariant::HmacSha256Key,
            Self::HmacSha256Mac(_) => TypeVariant::HmacSha256Mac,
        }
    }
}

impl Name for Type {
    #[must_use]
    fn name(&self) -> &'static str {
        Self::name(self)
    }
}

impl Variants<TypeVariant> for Type {
    fn variants() -> slice::Iter<'static, TypeVariant> {
        Self::VARIANTS.iter()
    }
}