Import asn1-rs-derive crate.

Request Document: go/android-rust-importing-crates
For CL Reviewers: go/android3p#cl-review
For Build Team: go/ab-third-party-imports
Bug: 312436720
Test: Treehugger

Change-Id: I44b17fd2de8eeae4ee43fda51177bad85c99e4bc
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..2109421
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "28257314e48d1ad4e62b8159c939518e17caf826"
+  },
+  "path_in_vcs": "derive"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..061d74a
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,20 @@
+// This file is generated by cargo_embargo.
+// Do not modify this file as changes will be overridden on upgrade.
+
+// TODO: Add license.
+rust_proc_macro {
+    name: "libasn1_rs_derive",
+    crate_name: "asn1_rs_derive",
+    cargo_env_compat: true,
+    cargo_pkg_version: "0.4.0",
+    srcs: ["src/lib.rs"],
+    edition: "2018",
+    rustlibs: [
+        "libproc_macro2",
+        "libquote",
+        "libsyn",
+        "libsynstructure",
+    ],
+    product_available: true,
+    vendor_available: true,
+}
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..8dc4bad
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,36 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "asn1-rs-derive"
+version = "0.4.0"
+authors = ["Pierre Chifflier <chifflier@wzdftpd.net>"]
+description = "Derive macros for the `asn1-rs` crate"
+homepage = "https://github.com/rusticata/asn1-rs"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rusticata/asn1-rs.git"
+
+[lib]
+proc-macro = true
+
+[dependencies.proc-macro2]
+version = "1.0"
+
+[dependencies.quote]
+version = "1.0"
+
+[dependencies.syn]
+version = "1.0"
+features = ["full"]
+
+[dependencies.synstructure]
+version = "0.12"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..5a3a945
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,18 @@
+[package]
+name = "asn1-rs-derive"
+version = "0.4.0"
+authors = ["Pierre Chifflier <chifflier@wzdftpd.net>"]
+description = "Derive macros for the `asn1-rs` crate"
+license = "MIT/Apache-2.0"
+homepage = "https://github.com/rusticata/asn1-rs"
+repository = "https://github.com/rusticata/asn1-rs.git"
+edition = "2018"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "1.0"
+quote = "1.0"
+syn = { version="1.0", features = ["full"] }
+synstructure = "0.12"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1217acf
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,229 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-----
+
+Copyright (c) 2017 Pierre Chifflier
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..290e7b9
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2017 Pierre Chifflier
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..73549c5
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,20 @@
+name: "asn1-rs-derive"
+description: "Derive macros for the `asn1-rs` crate"
+third_party {
+  identifier {
+    type: "crates.io"
+    value: "https://crates.io/crates/asn1-rs-derive"
+  }
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/asn1-rs-derive/asn1-rs-derive-0.4.0.crate"
+  }
+  version: "0.4.0"
+  # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same.
+  license_type: NOTICE
+  last_upgrade_date {
+    year: 2023
+    month: 11
+    day: 21
+  }
+}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..5a2b844
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1 @@
+include platform/prebuilts/rust:main:/OWNERS
diff --git a/cargo_embargo.json b/cargo_embargo.json
new file mode 100644
index 0000000..fca634f
--- /dev/null
+++ b/cargo_embargo.json
@@ -0,0 +1,3 @@
+{
+    "run_cargo": false
+}
diff --git a/src/alias.rs b/src/alias.rs
new file mode 100644
index 0000000..82ca68e
--- /dev/null
+++ b/src/alias.rs
@@ -0,0 +1,61 @@
+use crate::container::*;
+use proc_macro2::Span;
+use quote::quote;
+use syn::{Data, Ident};
+
+pub fn derive_ber_alias(s: synstructure::Structure) -> proc_macro2::TokenStream {
+    let ast = s.ast();
+
+    let container = match &ast.data {
+        Data::Struct(ds) => Container::from_datastruct(ds, ast, ContainerType::Alias),
+        _ => panic!("Unsupported type, cannot derive"),
+    };
+
+    let debug_derive = ast.attrs.iter().any(|attr| {
+        attr.path
+            .is_ident(&Ident::new("debug_derive", Span::call_site()))
+    });
+
+    let impl_tryfrom = container.gen_tryfrom();
+    let impl_tagged = container.gen_tagged();
+    let ts = s.gen_impl(quote! {
+        extern crate asn1_rs;
+
+        #impl_tryfrom
+        #impl_tagged
+    });
+    if debug_derive {
+        eprintln!("{}", ts);
+    }
+    ts
+}
+
+pub fn derive_der_alias(s: synstructure::Structure) -> proc_macro2::TokenStream {
+    let ast = s.ast();
+
+    let container = match &ast.data {
+        Data::Struct(ds) => Container::from_datastruct(ds, ast, ContainerType::Alias),
+        _ => panic!("Unsupported type, cannot derive"),
+    };
+
+    let debug_derive = ast.attrs.iter().any(|attr| {
+        attr.path
+            .is_ident(&Ident::new("debug_derive", Span::call_site()))
+    });
+    let impl_tryfrom = container.gen_tryfrom();
+    let impl_tagged = container.gen_tagged();
+    let impl_checkconstraints = container.gen_checkconstraints();
+    let impl_fromder = container.gen_fromder();
+    let ts = s.gen_impl(quote! {
+        extern crate asn1_rs;
+
+        #impl_tryfrom
+        #impl_tagged
+        #impl_checkconstraints
+        #impl_fromder
+    });
+    if debug_derive {
+        eprintln!("{}", ts);
+    }
+    ts
+}
diff --git a/src/container.rs b/src/container.rs
new file mode 100644
index 0000000..667992c
--- /dev/null
+++ b/src/container.rs
@@ -0,0 +1,488 @@
+use proc_macro2::{Literal, Span, TokenStream};
+use quote::{quote, ToTokens};
+use syn::{
+    parse::ParseStream, parse_quote, spanned::Spanned, Attribute, DataStruct, DeriveInput, Field,
+    Fields, Ident, Lifetime, LitInt, Meta, Type, WherePredicate,
+};
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum ContainerType {
+    Alias,
+    Sequence,
+    Set,
+}
+
+impl ToTokens for ContainerType {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let s = match self {
+            ContainerType::Alias => quote! {},
+            ContainerType::Sequence => quote! { asn1_rs::Tag::Sequence },
+            ContainerType::Set => quote! { asn1_rs::Tag::Set },
+        };
+        s.to_tokens(tokens)
+    }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum Asn1Type {
+    Ber,
+    Der,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum Asn1TagKind {
+    Explicit,
+    Implicit,
+}
+
+impl ToTokens for Asn1TagKind {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let s = match self {
+            Asn1TagKind::Explicit => quote! { asn1_rs::Explicit },
+            Asn1TagKind::Implicit => quote! { asn1_rs::Implicit },
+        };
+        s.to_tokens(tokens)
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum Asn1TagClass {
+    Universal,
+    Application,
+    ContextSpecific,
+    Private,
+}
+
+impl ToTokens for Asn1TagClass {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let s = match self {
+            Asn1TagClass::Application => quote! { asn1_rs::Class::APPLICATION },
+            Asn1TagClass::ContextSpecific => quote! { asn1_rs::Class::CONTEXT_SPECIFIC },
+            Asn1TagClass::Private => quote! { asn1_rs::Class::PRIVATE },
+            Asn1TagClass::Universal => quote! { asn1_rs::Class::UNIVERSAL },
+        };
+        s.to_tokens(tokens)
+    }
+}
+
+pub struct Container {
+    pub container_type: ContainerType,
+    pub fields: Vec<FieldInfo>,
+    pub where_predicates: Vec<WherePredicate>,
+    pub error: Option<Attribute>,
+
+    is_any: bool,
+}
+
+impl Container {
+    pub fn from_datastruct(
+        ds: &DataStruct,
+        ast: &DeriveInput,
+        container_type: ContainerType,
+    ) -> Self {
+        let mut is_any = false;
+        match (container_type, &ds.fields) {
+            (ContainerType::Alias, Fields::Unnamed(f)) => {
+                if f.unnamed.len() != 1 {
+                    panic!("Alias: only tuple fields with one element are supported");
+                }
+                match &f.unnamed[0].ty {
+                    Type::Path(type_path)
+                        if type_path
+                            .clone()
+                            .into_token_stream()
+                            .to_string()
+                            .starts_with("Any") =>
+                    {
+                        is_any = true;
+                    }
+                    _ => (),
+                }
+            }
+            (ContainerType::Alias, _) => panic!("BER/DER alias must be used with tuple strucs"),
+            (_, Fields::Unnamed(_)) => panic!("BER/DER sequence cannot be used on tuple structs"),
+            _ => (),
+        }
+
+        let fields = ds.fields.iter().map(FieldInfo::from).collect();
+
+        // get lifetimes from generics
+        let lfts: Vec<_> = ast.generics.lifetimes().collect();
+        let mut where_predicates = Vec::new();
+        if !lfts.is_empty() {
+            // input slice must outlive all lifetimes from Self
+            let lft = Lifetime::new("'ber", Span::call_site());
+            let wh: WherePredicate = parse_quote! { #lft: #(#lfts)+* };
+            where_predicates.push(wh);
+        };
+
+        // get custom attributes on container
+        let error = ast
+            .attrs
+            .iter()
+            .find(|attr| attr.path.is_ident(&Ident::new("error", Span::call_site())))
+            .cloned();
+
+        Container {
+            container_type,
+            fields,
+            where_predicates,
+            error,
+            is_any,
+        }
+    }
+
+    pub fn gen_tryfrom(&self) -> TokenStream {
+        let field_names = &self.fields.iter().map(|f| &f.name).collect::<Vec<_>>();
+        let parse_content =
+            derive_ber_sequence_content(&self.fields, Asn1Type::Ber, self.error.is_some());
+        let lifetime = Lifetime::new("'ber", Span::call_site());
+        let wh = &self.where_predicates;
+        let error = if let Some(attr) = &self.error {
+            get_attribute_meta(attr).expect("Invalid error attribute format")
+        } else {
+            quote! { asn1_rs::Error }
+        };
+
+        let fn_content = if self.container_type == ContainerType::Alias {
+            // special case: is this an alias for Any
+            if self.is_any {
+                quote! { Ok(Self(any)) }
+            } else {
+                quote! {
+                    let res = TryFrom::try_from(any)?;
+                    Ok(Self(res))
+                }
+            }
+        } else {
+            quote! {
+                use asn1_rs::nom::*;
+                any.tag().assert_eq(Self::TAG)?;
+
+                // no need to parse sequence, we already have content
+                let i = any.data;
+                //
+                #parse_content
+                //
+                let _ = i; // XXX check if empty?
+                Ok(Self{#(#field_names),*})
+            }
+        };
+        // note: `gen impl` in synstructure takes care of appending extra where clauses if any, and removing
+        // the `where` statement if there are none.
+        quote! {
+            use asn1_rs::{Any, FromBer};
+            use core::convert::TryFrom;
+
+            gen impl<#lifetime> TryFrom<Any<#lifetime>> for @Self where #(#wh)+* {
+                type Error = #error;
+
+                fn try_from(any: Any<#lifetime>) -> asn1_rs::Result<Self, #error> {
+                    #fn_content
+                }
+            }
+        }
+    }
+
+    pub fn gen_tagged(&self) -> TokenStream {
+        let tag = if self.container_type == ContainerType::Alias {
+            // special case: is this an alias for Any
+            if self.is_any {
+                return quote! {};
+            }
+            // find type of sub-item
+            let ty = &self.fields[0].type_;
+            quote! { <#ty as asn1_rs::Tagged>::TAG }
+        } else {
+            let container_type = self.container_type;
+            quote! { #container_type }
+        };
+        quote! {
+            gen impl<'ber> asn1_rs::Tagged for @Self {
+                const TAG: asn1_rs::Tag = #tag;
+            }
+        }
+    }
+
+    pub fn gen_checkconstraints(&self) -> TokenStream {
+        let lifetime = Lifetime::new("'ber", Span::call_site());
+        let wh = &self.where_predicates;
+        // let parse_content = derive_ber_sequence_content(&field_names, Asn1Type::Der);
+
+        let fn_content = if self.container_type == ContainerType::Alias {
+            // special case: is this an alias for Any
+            if self.is_any {
+                return quote! {};
+            }
+            let ty = &self.fields[0].type_;
+            quote! {
+                any.tag().assert_eq(Self::TAG)?;
+                <#ty>::check_constraints(any)
+            }
+        } else {
+            let check_fields: Vec<_> = self
+                .fields
+                .iter()
+                .map(|field| {
+                    let ty = &field.type_;
+                    quote! {
+                        let (rem, any) = Any::from_der(rem)?;
+                        <#ty as CheckDerConstraints>::check_constraints(&any)?;
+                    }
+                })
+                .collect();
+            quote! {
+                any.tag().assert_eq(Self::TAG)?;
+                let rem = &any.data;
+                #(#check_fields)*
+                Ok(())
+            }
+        };
+
+        // note: `gen impl` in synstructure takes care of appending extra where clauses if any, and removing
+        // the `where` statement if there are none.
+        quote! {
+            use asn1_rs::{CheckDerConstraints, Tagged};
+            gen impl<#lifetime> CheckDerConstraints for @Self where #(#wh)+* {
+                fn check_constraints(any: &Any) -> asn1_rs::Result<()> {
+                    #fn_content
+                }
+            }
+        }
+    }
+
+    pub fn gen_fromder(&self) -> TokenStream {
+        let lifetime = Lifetime::new("'ber", Span::call_site());
+        let wh = &self.where_predicates;
+        let field_names = &self.fields.iter().map(|f| &f.name).collect::<Vec<_>>();
+        let parse_content =
+            derive_ber_sequence_content(&self.fields, Asn1Type::Der, self.error.is_some());
+        let error = if let Some(attr) = &self.error {
+            get_attribute_meta(attr).expect("Invalid error attribute format")
+        } else {
+            quote! { asn1_rs::Error }
+        };
+
+        let fn_content = if self.container_type == ContainerType::Alias {
+            // special case: is this an alias for Any
+            if self.is_any {
+                quote! {
+                    let (rem, any) = asn1_rs::Any::from_der(bytes).map_err(asn1_rs::nom::Err::convert)?;
+                    Ok((rem,Self(any)))
+                }
+            } else {
+                quote! {
+                    let (rem, any) = asn1_rs::Any::from_der(bytes).map_err(asn1_rs::nom::Err::convert)?;
+                    any.header.assert_tag(Self::TAG).map_err(|e| asn1_rs::nom::Err::Error(e.into()))?;
+                    let res = TryFrom::try_from(any)?;
+                    Ok((rem,Self(res)))
+                }
+            }
+        } else {
+            quote! {
+                let (rem, any) = asn1_rs::Any::from_der(bytes).map_err(asn1_rs::nom::Err::convert)?;
+                any.header.assert_tag(Self::TAG).map_err(|e| asn1_rs::nom::Err::Error(e.into()))?;
+                let i = any.data;
+                //
+                #parse_content
+                //
+                // let _ = i; // XXX check if empty?
+                Ok((rem,Self{#(#field_names),*}))
+            }
+        };
+        // note: `gen impl` in synstructure takes care of appending extra where clauses if any, and removing
+        // the `where` statement if there are none.
+        quote! {
+            use asn1_rs::FromDer;
+
+            gen impl<#lifetime> asn1_rs::FromDer<#lifetime, #error> for @Self where #(#wh)+* {
+                fn from_der(bytes: &#lifetime [u8]) -> asn1_rs::ParseResult<#lifetime, Self, #error> {
+                    #fn_content
+                }
+            }
+        }
+    }
+}
+
+#[derive(Debug)]
+pub struct FieldInfo {
+    pub name: Ident,
+    pub type_: Type,
+    pub default: Option<TokenStream>,
+    pub optional: bool,
+    pub tag: Option<(Asn1TagKind, Asn1TagClass, u16)>,
+    pub map_err: Option<TokenStream>,
+}
+
+impl From<&Field> for FieldInfo {
+    fn from(field: &Field) -> Self {
+        // parse attributes and keep supported ones
+        let mut optional = false;
+        let mut tag = None;
+        let mut map_err = None;
+        let mut default = None;
+        let name = field
+            .ident
+            .as_ref()
+            .map_or_else(|| Ident::new("_", Span::call_site()), |s| s.clone());
+        for attr in &field.attrs {
+            let ident = match attr.path.get_ident() {
+                Some(ident) => ident.to_string(),
+                None => continue,
+            };
+            match ident.as_str() {
+                "map_err" => {
+                    let expr: syn::Expr = attr.parse_args().expect("could not parse map_err");
+                    map_err = Some(quote! { #expr });
+                }
+                "default" => {
+                    let expr: syn::Expr = attr.parse_args().expect("could not parse default");
+                    default = Some(quote! { #expr });
+                    optional = true;
+                }
+                "optional" => optional = true,
+                "tag_explicit" => {
+                    if tag.is_some() {
+                        panic!("tag cannot be set twice!");
+                    }
+                    let (class, value) = attr.parse_args_with(parse_tag_args).unwrap();
+                    tag = Some((Asn1TagKind::Explicit, class, value));
+                }
+                "tag_implicit" => {
+                    if tag.is_some() {
+                        panic!("tag cannot be set twice!");
+                    }
+                    let (class, value) = attr.parse_args_with(parse_tag_args).unwrap();
+                    tag = Some((Asn1TagKind::Implicit, class, value));
+                }
+                // ignore unknown attributes
+                _ => (),
+            }
+        }
+        FieldInfo {
+            name,
+            type_: field.ty.clone(),
+            default,
+            optional,
+            tag,
+            map_err,
+        }
+    }
+}
+
+fn parse_tag_args(stream: ParseStream) -> Result<(Asn1TagClass, u16), syn::Error> {
+    let tag_class: Option<Ident> = stream.parse()?;
+    let tag_class = if let Some(ident) = tag_class {
+        let s = ident.to_string().to_uppercase();
+        match s.as_str() {
+            "UNIVERSAL" => Asn1TagClass::Universal,
+            "CONTEXT-SPECIFIC" => Asn1TagClass::ContextSpecific,
+            "APPLICATION" => Asn1TagClass::Application,
+            "PRIVATE" => Asn1TagClass::Private,
+            _ => {
+                return Err(syn::Error::new(stream.span(), "Invalid tag class"));
+            }
+        }
+    } else {
+        Asn1TagClass::ContextSpecific
+    };
+    let lit: LitInt = stream.parse()?;
+    let value = lit.base10_parse::<u16>()?;
+    Ok((tag_class, value))
+}
+
+fn derive_ber_sequence_content(
+    fields: &[FieldInfo],
+    asn1_type: Asn1Type,
+    custom_errors: bool,
+) -> TokenStream {
+    let field_parsers: Vec<_> = fields
+        .iter()
+        .map(|f| get_field_parser(f, asn1_type, custom_errors))
+        .collect();
+
+    quote! {
+        #(#field_parsers)*
+    }
+}
+
+fn get_field_parser(f: &FieldInfo, asn1_type: Asn1Type, custom_errors: bool) -> TokenStream {
+    let from = match asn1_type {
+        Asn1Type::Ber => quote! {FromBer::from_ber},
+        Asn1Type::Der => quote! {FromDer::from_der},
+    };
+    let name = &f.name;
+    let default = f
+        .default
+        .as_ref()
+        // use a type hint, otherwise compiler will not know what type provides .unwrap_or
+        .map(|x| quote! {let #name: Option<_> = #name; let #name = #name.unwrap_or(#x);});
+    let map_err = if let Some(tt) = f.map_err.as_ref() {
+        if asn1_type == Asn1Type::Ber {
+            Some(quote! { .finish().map_err(#tt) })
+        } else {
+            // Some(quote! { .map_err(|err| nom::Err::convert(#tt)) })
+            Some(quote! { .map_err(|err| err.map(#tt)) })
+        }
+    } else {
+        // add mapping functions only if custom errors are used
+        if custom_errors {
+            if asn1_type == Asn1Type::Ber {
+                Some(quote! { .finish() })
+            } else {
+                Some(quote! { .map_err(nom::Err::convert) })
+            }
+        } else {
+            None
+        }
+    };
+    if let Some((tag_kind, class, n)) = f.tag {
+        let tag = Literal::u16_unsuffixed(n);
+        // test if tagged + optional
+        if f.optional {
+            return quote! {
+                let (i, #name) = {
+                    if i.is_empty() {
+                        (i, None)
+                    } else {
+                        let (_, header): (_, asn1_rs::Header) = #from(i)#map_err?;
+                        if header.tag().0 == #tag {
+                            let (i, t): (_, asn1_rs::TaggedValue::<_, _, #tag_kind, {#class}, #tag>) = #from(i)#map_err?;
+                            (i, Some(t.into_inner()))
+                        } else {
+                            (i, None)
+                        }
+                    }
+                };
+                #default
+            };
+        } else {
+            // tagged, but not OPTIONAL
+            return quote! {
+                let (i, #name) = {
+                    let (i, t): (_, asn1_rs::TaggedValue::<_, _, #tag_kind, {#class}, #tag>) = #from(i)#map_err?;
+                    (i, t.into_inner())
+                };
+                #default
+            };
+        }
+    } else {
+        // neither tagged nor optional
+        quote! {
+            let (i, #name) = #from(i)#map_err?;
+            #default
+        }
+    }
+}
+
+fn get_attribute_meta(attr: &Attribute) -> Result<TokenStream, syn::Error> {
+    if let Ok(Meta::List(meta)) = attr.parse_meta() {
+        let content = &meta.nested;
+        Ok(quote! { #content })
+    } else {
+        Err(syn::Error::new(
+            attr.span(),
+            "Invalid error attribute format",
+        ))
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..c75cf37
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,64 @@
+mod alias;
+mod container;
+mod sequence;
+mod set;
+use alias::*;
+use sequence::*;
+use set::*;
+
+synstructure::decl_derive!([BerAlias, attributes(
+    debug_derive,
+    default,
+    optional,
+    tag_explicit,
+    tag_implicit,
+    error,
+    map_err
+)] => derive_ber_alias);
+synstructure::decl_derive!([DerAlias, attributes(
+    debug_derive,
+    default,
+    optional,
+    tag_explicit,
+    tag_implicit,
+    error,
+    map_err
+)] => derive_der_alias);
+
+synstructure::decl_derive!([BerSequence, attributes(
+    debug_derive,
+    default,
+    optional,
+    tag_explicit,
+    tag_implicit,
+    error,
+    map_err
+)] => derive_ber_sequence);
+synstructure::decl_derive!([DerSequence, attributes(
+    debug_derive,
+    default,
+    optional,
+    tag_explicit,
+    tag_implicit,
+    error,
+    map_err
+)] => derive_der_sequence);
+
+synstructure::decl_derive!([BerSet, attributes(
+    debug_derive,
+    default,
+    optional,
+    tag_explicit,
+    tag_implicit,
+    error,
+    map_err
+)] => derive_ber_set);
+synstructure::decl_derive!([DerSet, attributes(
+    debug_derive,
+    default,
+    optional,
+    tag_explicit,
+    tag_implicit,
+    error,
+    map_err
+)] => derive_der_set);
diff --git a/src/sequence.rs b/src/sequence.rs
new file mode 100644
index 0000000..8a0d249
--- /dev/null
+++ b/src/sequence.rs
@@ -0,0 +1,61 @@
+use crate::container::*;
+use proc_macro2::Span;
+use quote::quote;
+use syn::{Data, Ident};
+
+pub fn derive_ber_sequence(s: synstructure::Structure) -> proc_macro2::TokenStream {
+    let ast = s.ast();
+
+    let container = match &ast.data {
+        Data::Struct(ds) => Container::from_datastruct(ds, ast, ContainerType::Sequence),
+        _ => panic!("Unsupported type, cannot derive"),
+    };
+
+    let debug_derive = ast.attrs.iter().any(|attr| {
+        attr.path
+            .is_ident(&Ident::new("debug_derive", Span::call_site()))
+    });
+
+    let impl_tryfrom = container.gen_tryfrom();
+    let impl_tagged = container.gen_tagged();
+    let ts = s.gen_impl(quote! {
+        extern crate asn1_rs;
+
+        #impl_tryfrom
+        #impl_tagged
+    });
+    if debug_derive {
+        eprintln!("{}", ts);
+    }
+    ts
+}
+
+pub fn derive_der_sequence(s: synstructure::Structure) -> proc_macro2::TokenStream {
+    let ast = s.ast();
+
+    let container = match &ast.data {
+        Data::Struct(ds) => Container::from_datastruct(ds, ast, ContainerType::Sequence),
+        _ => panic!("Unsupported type, cannot derive"),
+    };
+
+    let debug_derive = ast.attrs.iter().any(|attr| {
+        attr.path
+            .is_ident(&Ident::new("debug_derive", Span::call_site()))
+    });
+    let impl_tryfrom = container.gen_tryfrom();
+    let impl_tagged = container.gen_tagged();
+    let impl_checkconstraints = container.gen_checkconstraints();
+    let impl_fromder = container.gen_fromder();
+    let ts = s.gen_impl(quote! {
+        extern crate asn1_rs;
+
+        #impl_tryfrom
+        #impl_tagged
+        #impl_checkconstraints
+        #impl_fromder
+    });
+    if debug_derive {
+        eprintln!("{}", ts);
+    }
+    ts
+}
diff --git a/src/set.rs b/src/set.rs
new file mode 100644
index 0000000..90ea04a
--- /dev/null
+++ b/src/set.rs
@@ -0,0 +1,61 @@
+use crate::container::*;
+use proc_macro2::Span;
+use quote::quote;
+use syn::{Data, Ident};
+
+pub fn derive_ber_set(s: synstructure::Structure) -> proc_macro2::TokenStream {
+    let ast = s.ast();
+
+    let container = match &ast.data {
+        Data::Struct(ds) => Container::from_datastruct(ds, ast, ContainerType::Set),
+        _ => panic!("Unsupported type, cannot derive"),
+    };
+
+    let debug_derive = ast.attrs.iter().any(|attr| {
+        attr.path
+            .is_ident(&Ident::new("debug_derive", Span::call_site()))
+    });
+
+    let impl_tryfrom = container.gen_tryfrom();
+    let impl_tagged = container.gen_tagged();
+    let ts = s.gen_impl(quote! {
+        extern crate asn1_rs;
+
+        #impl_tryfrom
+        #impl_tagged
+    });
+    if debug_derive {
+        eprintln!("{}", ts);
+    }
+    ts
+}
+
+pub fn derive_der_set(s: synstructure::Structure) -> proc_macro2::TokenStream {
+    let ast = s.ast();
+
+    let container = match &ast.data {
+        Data::Struct(ds) => Container::from_datastruct(ds, ast, ContainerType::Set),
+        _ => panic!("Unsupported type, cannot derive"),
+    };
+
+    let debug_derive = ast.attrs.iter().any(|attr| {
+        attr.path
+            .is_ident(&Ident::new("debug_derive", Span::call_site()))
+    });
+    let impl_tryfrom = container.gen_tryfrom();
+    let impl_tagged = container.gen_tagged();
+    let impl_checkconstraints = container.gen_checkconstraints();
+    let impl_fromder = container.gen_fromder();
+    let ts = s.gen_impl(quote! {
+        extern crate asn1_rs;
+
+        #impl_tryfrom
+        #impl_tagged
+        #impl_checkconstraints
+        #impl_fromder
+    });
+    if debug_derive {
+        eprintln!("{}", ts);
+    }
+    ts
+}