use {
    crate::asn1::{common::*, rfc3280::*, rfc3281::*, rfc5280::*},
    bcder::{
        decode::{Constructed, Malformed, Source, Unimplemented},
        encode,
        encode::{PrimitiveContent, Values},
        BitString, Captured, ConstOid, Integer, Mode, OctetString, Oid, Tag,
    },
    std::{
        io::Write,
        ops::{Deref, DerefMut},
    },
};
pub const OID_ID_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 1]);
pub const OID_ID_SIGNED_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 2]);
pub const OID_ENVELOPE_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 3]);
pub const OID_DIGESTED_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 5]);
pub const OID_ENCRYPTED_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 7, 6]);
pub const OID_AUTHENTICATED_DATA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 16, 1, 2]);
pub const OID_CONTENT_TYPE: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 3]);
pub const OID_MESSAGE_DIGEST: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 4]);
pub const OID_SIGNING_TIME: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 5]);
pub const OID_COUNTER_SIGNATURE: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 9, 6]);
#[derive(Clone, Debug)]
pub struct ContentInfo {
    pub content_type: ContentType,
    pub content: Captured,
}
impl PartialEq for ContentInfo {
    fn eq(&self, other: &Self) -> bool {
        self.content_type == other.content_type
            && self.content.as_slice() == other.content.as_slice()
    }
}
impl Eq for ContentInfo {}
impl ContentInfo {
    pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> {
        cons.take_opt_sequence(|cons| Self::from_sequence(cons))
    }
    pub fn from_sequence<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        let content_type = ContentType::take_from(cons)?;
        let content = cons.take_constructed_if(Tag::CTX_0, |cons| cons.capture_all())?;
        Ok(Self {
            content_type,
            content,
        })
    }
}
impl Values for ContentInfo {
    fn encoded_len(&self, mode: Mode) -> usize {
        encode::sequence((self.content_type.encode_ref(), &self.content)).encoded_len(mode)
    }
    fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
        encode::sequence((self.content_type.encode_ref(), &self.content))
            .write_encoded(mode, target)
    }
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SignedData {
    pub version: CmsVersion,
    pub digest_algorithms: DigestAlgorithmIdentifiers,
    pub content_info: EncapsulatedContentInfo,
    pub certificates: Option<CertificateSet>,
    pub crls: Option<RevocationInfoChoices>,
    pub signer_infos: SignerInfos,
}
impl SignedData {
    
    pub fn decode_ber(data: &[u8]) -> Result<Self, bcder::decode::Error> {
        Constructed::decode(data, bcder::Mode::Ber, |cons| Self::decode(cons))
    }
    pub fn decode<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        cons.take_sequence(|cons| {
            let oid = Oid::take_from(cons)?;
            if oid != OID_ID_SIGNED_DATA {
                return Err(Malformed.into());
            }
            cons.take_constructed_if(Tag::CTX_0, Self::take_from)
        })
    }
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        cons.take_sequence(|cons| {
            let version = CmsVersion::take_from(cons)?;
            let digest_algorithms = DigestAlgorithmIdentifiers::take_from(cons)?;
            let content_info = EncapsulatedContentInfo::take_from(cons)?;
            let certificates =
                cons.take_opt_constructed_if(Tag::CTX_0, |cons| CertificateSet::take_from(cons))?;
            let crls = cons.take_opt_constructed_if(Tag::CTX_1, |cons| {
                RevocationInfoChoices::take_from(cons)
            })?;
            let signer_infos = SignerInfos::take_from(cons)?;
            Ok(Self {
                version,
                digest_algorithms,
                content_info,
                certificates,
                crls,
                signer_infos,
            })
        })
    }
    pub fn encode_ref(&self) -> impl Values + '_ {
        encode::sequence((
            OID_ID_SIGNED_DATA.encode_ref(),
            encode::sequence_as(
                Tag::CTX_0,
                encode::sequence((
                    self.version.encode(),
                    self.digest_algorithms.encode_ref(),
                    self.content_info.encode_ref(),
                    if let Some(certs) = self.certificates.as_ref() {
                        Some(certs.encode_ref_as(Tag::CTX_0))
                    } else {
                        None
                    },
                    
                    self.signer_infos.encode_ref(),
                )),
            ),
        ))
    }
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct DigestAlgorithmIdentifiers(Vec<DigestAlgorithmIdentifier>);
impl Deref for DigestAlgorithmIdentifiers {
    type Target = Vec<DigestAlgorithmIdentifier>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for DigestAlgorithmIdentifiers {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl DigestAlgorithmIdentifiers {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        cons.take_set(|cons| {
            let mut identifiers = Vec::new();
            while let Some(identifier) = AlgorithmIdentifier::take_opt_from(cons)? {
                identifiers.push(identifier);
            }
            Ok(Self(identifiers))
        })
    }
    pub fn encode_ref(&self) -> impl Values + '_ {
        encode::set(&self.0)
    }
}
pub type DigestAlgorithmIdentifier = AlgorithmIdentifier;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct SignerInfos(Vec<SignerInfo>);
impl Deref for SignerInfos {
    type Target = Vec<SignerInfo>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for SignerInfos {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl SignerInfos {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        cons.take_set(|cons| {
            let mut infos = Vec::new();
            while let Some(info) = SignerInfo::take_opt_from(cons)? {
                infos.push(info);
            }
            Ok(Self(infos))
        })
    }
    pub fn encode_ref(&self) -> impl Values + '_ {
        encode::set(&self.0)
    }
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EncapsulatedContentInfo {
    pub content_type: ContentType,
    pub content: Option<OctetString>,
}
impl EncapsulatedContentInfo {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        cons.take_sequence(|cons| {
            let content_type = ContentType::take_from(cons)?;
            let content =
                cons.take_opt_constructed_if(Tag::CTX_0, |cons| OctetString::take_from(cons))?;
            Ok(Self {
                content_type,
                content,
            })
        })
    }
    pub fn encode_ref(&self) -> impl Values + '_ {
        encode::sequence((
            self.content_type.encode_ref(),
            if let Some(content) = self.content.as_ref() {
                Some(encode::sequence_as(Tag::CTX_0, content.encode_ref()))
            } else {
                None
            },
        ))
    }
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SignerInfo {
    pub version: CmsVersion,
    pub sid: SignerIdentifier,
    pub digest_algorithm: DigestAlgorithmIdentifier,
    pub signed_attributes: Option<SignedAttributes>,
    pub signature_algorithm: SignatureAlgorithmIdentifier,
    pub signature: SignatureValue,
    pub unsigned_attributes: Option<UnsignedAttributes>,
    
    
    
    pub signed_attributes_data: Option<Vec<u8>>,
}
impl SignerInfo {
    pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> {
        cons.take_opt_sequence(|cons| Self::from_sequence(cons))
    }
    pub fn from_sequence<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        let version = CmsVersion::take_from(cons)?;
        let sid = SignerIdentifier::take_from(cons)?;
        let digest_algorithm = DigestAlgorithmIdentifier::take_from(cons)?;
        let signed_attributes = cons.take_opt_constructed_if(Tag::CTX_0, |cons| {
            
            
            
            let der = cons.capture_all()?;
            
            
            
            
            
            let der_data = der.as_slice().to_vec();
            Ok((
                Constructed::decode(der.as_slice(), bcder::Mode::Der, |cons| {
                    SignedAttributes::take_from_set(cons)
                })?,
                der_data,
            ))
        })?;
        let (signed_attributes, signed_attributes_data) = if let Some((x, y)) = signed_attributes {
            (Some(x), Some(y))
        } else {
            (None, None)
        };
        let signature_algorithm = SignatureAlgorithmIdentifier::take_from(cons)?;
        let signature = SignatureValue::take_from(cons)?;
        let unsigned_attributes = cons
            .take_opt_constructed_if(Tag::CTX_1, |cons| UnsignedAttributes::take_from_set(cons))?;
        Ok(Self {
            version,
            sid,
            digest_algorithm,
            signed_attributes,
            signature_algorithm,
            signature,
            unsigned_attributes,
            signed_attributes_data,
        })
    }
    pub fn encode_ref(&self) -> impl Values + '_ {
        encode::sequence((
            u8::from(self.version).encode(),
            &self.sid,
            self.digest_algorithm.encode_ref(),
            if let Some(attrs) = self.signed_attributes.as_ref() {
                Some(attrs.encode_ref_as(Tag::CTX_0))
            } else {
                None
            },
            self.signature_algorithm.encode_ref(),
            self.signature.encode_ref(),
            if let Some(attrs) = self.unsigned_attributes.as_ref() {
                Some(attrs.encode_ref_as(Tag::CTX_1))
            } else {
                None
            },
        ))
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    pub fn signed_attributes_digested_content(&self) -> Result<Option<Vec<u8>>, std::io::Error> {
        if let Some(signed_attributes) = &self.signed_attributes {
            if let Some(existing_data) = &self.signed_attributes_data {
                
                let mut buffer = Vec::with_capacity(existing_data.len() + 8);
                
                buffer.write_all(&[0x31])?;
                
                if existing_data.len() < 0x80 {
                    buffer.write_all(&[existing_data.len() as u8])?;
                } else if existing_data.len() < 0x100 {
                    buffer.write_all(&[0x81, existing_data.len() as u8])?;
                } else if existing_data.len() < 0x10000 {
                    buffer.write_all(&[
                        0x82,
                        (existing_data.len() >> 8) as u8,
                        existing_data.len() as u8,
                    ])?;
                } else if existing_data.len() < 0x1000000 {
                    buffer.write_all(&[
                        0x83,
                        (existing_data.len() >> 16) as u8,
                        (existing_data.len() >> 8) as u8,
                        existing_data.len() as u8,
                    ])?;
                } else {
                    return Err(std::io::Error::new(
                        std::io::ErrorKind::InvalidData,
                        "signed attributes length too long",
                    ));
                }
                buffer.write_all(existing_data)?;
                Ok(Some(buffer))
            } else {
                
                let mut der = Vec::new();
                signed_attributes
                    .encode_ref()
                    .write_encoded(bcder::Mode::Der, &mut der)?;
                Ok(Some(der))
            }
        } else {
            Ok(None)
        }
    }
}
impl Values for SignerInfo {
    fn encoded_len(&self, mode: Mode) -> usize {
        self.encode_ref().encoded_len(mode)
    }
    fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
        self.encode_ref().write_encoded(mode, target)
    }
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SignerIdentifier {
    IssuerAndSerialNumber(IssuerAndSerialNumber),
    SubjectKeyIdentifier(SubjectKeyIdentifier),
}
impl SignerIdentifier {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        if let Some(identifier) =
            cons.take_opt_constructed_if(Tag::CTX_0, |cons| SubjectKeyIdentifier::take_from(cons))?
        {
            Ok(Self::SubjectKeyIdentifier(identifier))
        } else {
            Ok(Self::IssuerAndSerialNumber(
                IssuerAndSerialNumber::take_from(cons)?,
            ))
        }
    }
}
impl Values for SignerIdentifier {
    fn encoded_len(&self, mode: Mode) -> usize {
        match self {
            Self::IssuerAndSerialNumber(v) => v.encode_ref().encoded_len(mode),
            Self::SubjectKeyIdentifier(v) => v.encode_ref_as(Tag::CTX_0).encoded_len(mode),
        }
    }
    fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
        match self {
            Self::IssuerAndSerialNumber(v) => v.encode_ref().write_encoded(mode, target),
            Self::SubjectKeyIdentifier(v) => {
                v.encode_ref_as(Tag::CTX_0).write_encoded(mode, target)
            }
        }
    }
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct SignedAttributes(Vec<Attribute>);
impl Deref for SignedAttributes {
    type Target = Vec<Attribute>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for SignedAttributes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl SignedAttributes {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        cons.take_set(|cons| Self::take_from_set(cons))
    }
    pub fn take_from_set<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        let mut attributes = Vec::new();
        while let Some(attribute) = Attribute::take_opt_from(cons)? {
            attributes.push(attribute);
        }
        Ok(Self(attributes))
    }
    pub fn encode_ref(&self) -> impl Values + '_ {
        encode::set(encode::slice(&self.0, |x| x.clone().encode()))
    }
    pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
        encode::set_as(tag, encode::slice(&self.0, |x| x.clone().encode()))
    }
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct UnsignedAttributes(Vec<Attribute>);
impl Deref for UnsignedAttributes {
    type Target = Vec<Attribute>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for UnsignedAttributes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl UnsignedAttributes {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        cons.take_set(|cons| Self::take_from_set(cons))
    }
    pub fn take_from_set<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        let mut attributes = Vec::new();
        while let Some(attribute) = Attribute::take_opt_from(cons)? {
            attributes.push(attribute);
        }
        Ok(Self(attributes))
    }
    pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
        encode::set_as(tag, encode::slice(&self.0, |x| x.clone().encode()))
    }
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Attribute {
    pub typ: Oid,
    pub values: Vec<AttributeValue>,
}
impl Attribute {
    pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> {
        cons.take_opt_sequence(|cons| {
            let typ = Oid::take_from(cons)?;
            let values = cons.take_set(|cons| {
                let mut values = Vec::new();
                while let Some(value) = AttributeValue::take_opt_from(cons)? {
                    values.push(value);
                }
                Ok(values)
            })?;
            Ok(Self { typ, values })
        })
    }
    pub fn encode_ref(&self) -> impl Values + '_ {
        encode::sequence((self.typ.encode_ref(), encode::set(&self.values)))
    }
    pub fn encode(self) -> impl Values {
        encode::sequence((self.typ.encode(), encode::set(self.values)))
    }
}
#[derive(Clone, Debug)]
pub struct AttributeValue(Captured);
impl AttributeValue {
    
    pub fn new(captured: Captured) -> Self {
        Self(captured)
    }
    pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> {
        let captured = cons.capture_all()?;
        if captured.is_empty() {
            Ok(None)
        } else {
            Ok(Some(Self(captured)))
        }
    }
}
impl Values for AttributeValue {
    fn encoded_len(&self, mode: Mode) -> usize {
        self.0.encoded_len(mode)
    }
    fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
        self.0.write_encoded(mode, target)
    }
}
impl Deref for AttributeValue {
    type Target = Captured;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for AttributeValue {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl PartialEq for AttributeValue {
    fn eq(&self, other: &Self) -> bool {
        self.0.as_slice() == other.0.as_slice()
    }
}
impl Eq for AttributeValue {}
pub type SignatureValue = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EnvelopedData {
    pub version: CmsVersion,
    pub originator_info: Option<OriginatorInfo>,
    pub recipient_infos: RecipientInfos,
    pub encrypted_content_info: EncryptedContentInfo,
    pub unprotected_attributes: Option<UnprotectedAttributes>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OriginatorInfo {
    pub certs: Option<CertificateSet>,
    pub crls: Option<RevocationInfoChoices>,
}
pub type RecipientInfos = Vec<RecipientInfo>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EncryptedContentInfo {
    pub content_type: ContentType,
    pub content_encryption_algorithms: ContentEncryptionAlgorithmIdentifier,
    pub encrypted_content: Option<EncryptedContent>,
}
pub type EncryptedContent = OctetString;
pub type UnprotectedAttributes = Vec<Attribute>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RecipientInfo {
    KeyTransRecipientInfo(KeyTransRecipientInfo),
    KeyAgreeRecipientInfo(KeyAgreeRecipientInfo),
    KekRecipientInfo(KekRecipientInfo),
    PasswordRecipientInfo(PasswordRecipientInfo),
    OtherRecipientInfo(OtherRecipientInfo),
}
pub type EncryptedKey = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeyTransRecipientInfo {
    pub version: CmsVersion,
    pub rid: RecipientIdentifier,
    pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
    pub encrypted_key: EncryptedKey,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RecipientIdentifier {
    IssuerAndSerialNumber(IssuerAndSerialNumber),
    SubjectKeyIdentifier(SubjectKeyIdentifier),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeyAgreeRecipientInfo {
    pub version: CmsVersion,
    pub originator: OriginatorIdentifierOrKey,
    pub ukm: Option<UserKeyingMaterial>,
    pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
    pub recipient_encrypted_keys: RecipientEncryptedKeys,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum OriginatorIdentifierOrKey {
    IssuerAndSerialNumber(IssuerAndSerialNumber),
    SubjectKeyIdentifier(SubjectKeyIdentifier),
    OriginatorKey(OriginatorPublicKey),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OriginatorPublicKey {
    pub algorithm: AlgorithmIdentifier,
    pub public_key: BitString,
}
type RecipientEncryptedKeys = Vec<RecipientEncryptedKey>;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RecipientEncryptedKey {
    pub rid: KeyAgreeRecipientInfo,
    pub encrypted_key: EncryptedKey,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum KeyAgreeRecipientIdentifier {
    IssuerAndSerialNumber(IssuerAndSerialNumber),
    RKeyId(RecipientKeyIdentifier),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RecipientKeyIdentifier {
    pub subject_key_identifier: SubjectKeyIdentifier,
    pub date: Option<GeneralizedTime>,
    pub other: Option<OtherKeyAttribute>,
}
type SubjectKeyIdentifier = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KekRecipientInfo {
    pub version: CmsVersion,
    pub kek_id: KekIdentifier,
    pub kek_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
    pub encrypted_key: EncryptedKey,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct KekIdentifier {
    pub key_identifier: OctetString,
    pub date: Option<GeneralizedTime>,
    pub other: Option<OtherKeyAttribute>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PasswordRecipientInfo {
    pub version: CmsVersion,
    pub key_derivation_algorithm: Option<KeyDerivationAlgorithmIdentifier>,
    pub key_encryption_algorithm: KeyEncryptionAlgorithmIdentifier,
    pub encrypted_key: EncryptedKey,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherRecipientInfo {
    pub ori_type: Oid,
    
    pub ori_value: Option<()>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DigestedData {
    pub version: CmsVersion,
    pub digest_algorithm: DigestAlgorithmIdentifier,
    pub content_type: EncapsulatedContentInfo,
    pub digest: Digest,
}
pub type Digest = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EncryptedData {
    pub version: CmsVersion,
    pub encrypted_content_info: EncryptedContentInfo,
    pub unprotected_attributes: Option<UnprotectedAttributes>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AuthenticatedData {
    pub version: CmsVersion,
    pub originator_info: Option<OriginatorInfo>,
    pub recipient_infos: RecipientInfos,
    pub mac_algorithm: MessageAuthenticationCodeAlgorithm,
    pub digest_algorithm: Option<DigestAlgorithmIdentifier>,
    pub content_info: EncapsulatedContentInfo,
    pub authenticated_attributes: Option<AuthAttributes>,
    pub mac: MessageAuthenticationCode,
    pub unauthenticated_attributes: Option<UnauthAttributes>,
}
pub type AuthAttributes = Vec<Attribute>;
pub type UnauthAttributes = Vec<Attribute>;
pub type MessageAuthenticationCode = OctetString;
pub type SignatureAlgorithmIdentifier = AlgorithmIdentifier;
pub type KeyEncryptionAlgorithmIdentifier = AlgorithmIdentifier;
pub type ContentEncryptionAlgorithmIdentifier = AlgorithmIdentifier;
pub type MessageAuthenticationCodeAlgorithm = AlgorithmIdentifier;
pub type KeyDerivationAlgorithmIdentifier = AlgorithmIdentifier;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RevocationInfoChoices(Vec<RevocationInfoChoice>);
impl RevocationInfoChoices {
    pub fn take_from<S: Source>(_cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        Err(Unimplemented.into())
    }
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RevocationInfoChoice {
    Crl(CertificateList),
    Other(OtherRevocationInfoFormat),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherRevocationInfoFormat {
    pub other_rev_info_info_format: Oid,
    
    pub other_rev_info: Option<()>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum CertificateChoices {
    Certificate(Box<Certificate>),
    
    
    AttributeCertificateV2(Box<AttributeCertificateV2>),
    Other(Box<OtherCertificateFormat>),
}
impl CertificateChoices {
    pub fn take_opt_from<S: Source>(cons: &mut Constructed<S>) -> Result<Option<Self>, S::Err> {
        cons.take_opt_constructed_if(Tag::CTX_0, |_cons| -> Result<(), S::Err> {
            Err(Unimplemented.into())
        })?;
        cons.take_opt_constructed_if(Tag::CTX_1, |_cons| -> Result<(), S::Err> {
            Err(Unimplemented.into())
        })?;
        
        if let Some(certificate) = cons
            .take_opt_constructed_if(Tag::CTX_2, |cons| AttributeCertificateV2::take_from(cons))?
        {
            Ok(Some(Self::AttributeCertificateV2(Box::new(certificate))))
        } else if let Some(certificate) = cons
            .take_opt_constructed_if(Tag::CTX_3, |cons| OtherCertificateFormat::take_from(cons))?
        {
            Ok(Some(Self::Other(Box::new(certificate))))
        } else if let Some(certificate) =
            cons.take_opt_constructed(|_, cons| Certificate::from_sequence(cons))?
        {
            Ok(Some(Self::Certificate(Box::new(certificate))))
        } else {
            Ok(None)
        }
    }
    pub fn encode_ref(&self) -> impl Values + '_ {
        match self {
            Self::Certificate(cert) => cert.encode_ref(),
            Self::AttributeCertificateV2(_) => unimplemented!(),
            Self::Other(_) => unimplemented!(),
        }
    }
}
impl Values for CertificateChoices {
    fn encoded_len(&self, mode: Mode) -> usize {
        self.encode_ref().encoded_len(mode)
    }
    fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
        self.encode_ref().write_encoded(mode, target)
    }
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherCertificateFormat {
    pub other_cert_format: Oid,
    
    pub other_cert: Option<()>,
}
impl OtherCertificateFormat {
    pub fn take_from<S: Source>(_cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        Err(Unimplemented.into())
    }
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct CertificateSet(Vec<CertificateChoices>);
impl Deref for CertificateSet {
    type Target = Vec<CertificateChoices>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl DerefMut for CertificateSet {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl CertificateSet {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        let mut certs = Vec::new();
        while let Some(cert) = CertificateChoices::take_opt_from(cons)? {
            certs.push(cert);
        }
        Ok(Self(certs))
    }
    pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
        encode::set_as(tag, &self.0)
    }
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct IssuerAndSerialNumber {
    pub issuer: Name,
    pub serial_number: CertificateSerialNumber,
}
impl IssuerAndSerialNumber {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        cons.take_sequence(|cons| {
            let issuer = Name::take_from(cons)?;
            let serial_number = Integer::take_from(cons)?;
            Ok(Self {
                issuer,
                serial_number,
            })
        })
    }
    pub fn encode_ref(&self) -> impl Values + '_ {
        encode::sequence((self.issuer.encode_ref(), (&self.serial_number).encode()))
    }
}
pub type CertificateSerialNumber = Integer;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CmsVersion {
    V0 = 0,
    V1 = 1,
    V2 = 2,
    V3 = 3,
    V4 = 4,
    V5 = 5,
}
impl CmsVersion {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        match cons.take_primitive_if(Tag::INTEGER, Integer::i8_from_primitive)? {
            0 => Ok(Self::V0),
            1 => Ok(Self::V1),
            2 => Ok(Self::V2),
            3 => Ok(Self::V3),
            4 => Ok(Self::V4),
            5 => Ok(Self::V5),
            _ => Err(Malformed.into()),
        }
    }
    pub fn encode(self) -> impl Values {
        u8::from(self).encode()
    }
}
impl From<CmsVersion> for u8 {
    fn from(v: CmsVersion) -> u8 {
        match v {
            CmsVersion::V0 => 0,
            CmsVersion::V1 => 1,
            CmsVersion::V2 => 2,
            CmsVersion::V3 => 3,
            CmsVersion::V4 => 4,
            CmsVersion::V5 => 5,
        }
    }
}
pub type UserKeyingMaterial = OctetString;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherKeyAttribute {
    pub key_attribute_id: Oid,
    
    pub key_attribute: Option<()>,
}
pub type ContentType = Oid;
pub type MessageDigest = OctetString;
pub type SigningTime = Time;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Time {
    UtcTime(UtcTime),
    GeneralizedTime(GeneralizedTime),
}
impl Time {
    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, S::Err> {
        if let Some(utc) =
            cons.take_opt_primitive_if(Tag::UTC_TIME, |prim| UtcTime::from_primitive(prim))?
        {
            Ok(Self::UtcTime(utc))
        } else if let Some(generalized) = cons
            .take_opt_primitive_if(Tag::GENERALIZED_TIME, |prim| {
                GeneralizedTime::from_primitive(prim)
            })?
        {
            Ok(Self::GeneralizedTime(generalized))
        } else {
            Err(Malformed.into())
        }
    }
}
impl From<Time> for chrono::DateTime<chrono::Utc> {
    fn from(t: Time) -> Self {
        match t {
            Time::UtcTime(utc) => *utc,
            Time::GeneralizedTime(gt) => *gt,
        }
    }
}
pub type CounterSignature = SignerInfo;
pub type AttributeCertificateV2 = AttributeCertificate;