chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

1
vendor/const-oid/.cargo-checksum.json vendored Normal file
View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"73e3732a3fd321c9719e28bfe76d9d00dd3eab86e351b7ee0c48a9a16973824e","CHANGELOG.md":"803e097b5076f9f1131fccdb4a43ee7905b6252236e4751a161c4bd430faf349","Cargo.toml":"c646206dd9067b48ca550efcedd9eed7fd2ed230e7d05757a569bbe18f01081c","Cargo.toml.orig":"3a7d36171ab486a6c8e9d1481b1e8d5288653cc8b63b92ed90bfe0ac6d069906","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"bada9e7ed8dc00d63502053c455d7c8d7575dfb7e8277a2a832531844d900682","README.md":"4a5cdde312d22ca0e6f8c6d4786af313e2a34c06fb572b7ccaef2f1ad19d781d","src/arcs.rs":"997f319f8ff5a3ffc448900993f2bf056c05f1092d48a6a592760bf261468e3d","src/checked.rs":"c3de8e43c638de4766550accb1b73cc7f37765f1779d3e572bfbd908bdb1003f","src/db.rs":"75567c122e9f236b02dcaad1b266efcffa452206877c35e2d343aa8eb3b53fad","src/db/gen.rs":"d80825bd0a307979354f522a1cd9ff4d7f83a65833792fdfb56e5f90acf4500d","src/encoder.rs":"cd799ff208a8a7a7a128c422ad3a5535e6ee6b800ad5e7087da55e27e23e84b3","src/error.rs":"0101b991fe689fd2b20c3144e3cfcca3a6628c6892f1ced4c2ba84d6788d72c9","src/lib.rs":"7476a1feb706595867f6e01e16113e167e03420344708c1a0b3a455549c5f82c","src/parser.rs":"9fe5c4114dad22631e63fd1afa832b2c0ed3b4b28f04587dd2148956ced98768","tests/lib.rs":"d7881ad1388e4c907d5392429927d299042dbd5eaaacfd27cef9e1d692fd5aee"},"package":"c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"}

6
vendor/const-oid/.cargo_vcs_info.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "4432bcc0b2b721865740517e609e166e01726ccc"
},
"path_in_vcs": "const-oid"
}

197
vendor/const-oid/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,197 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 0.9.6 (2023-12-14)
### Added
- RFC 6962 OID ([#1282])
[#1282]: https://github.com/RustCrypto/formats/pull/1282
## 0.9.5 (2023-08-02)
### Added
- rfc8410 (curve25519) OIDS. ([#867])
[#867]: https://github.com/RustCrypto/formats/pull/867
## 0.9.4 (2023-07-10)
### Added
- rfc8894 (SCEP) OIDs. ([#1114])
[#1114]: https://github.com/RustCrypto/formats/pull/1114
## 0.9.3 (2023-06-29)
### Added
- `Database::find_names_for_oid` ([#1129])
[#1129]: https://github.com/RustCrypto/formats/pull/1129
## 0.9.2 (2023-02-26)
### Added
- Implement `Arbitrary` trait ([#761])
[#761]: https://github.com/RustCrypto/formats/pull/761
## 0.9.1 (2022-11-12)
### Added
- clippy lints for checked arithmetic and panics ([#561])
- `DynAssociatedOid` trait ([#758])
[#561]: https://github.com/RustCrypto/formats/pull/561
[#758]: https://github.com/RustCrypto/formats/pull/758
## 0.9.0 (2022-03-11)
### Added
- Fallible `const fn` parser + `::new_unwrap` ([#458], [#459])
- OID database gated under the `db` feature ([#451], [#453], [#456], [#488])
- `AssociatedOid` trait ([#479])
- `ObjectIdentifier::push_arc` ([#504])
- `ObjectIdentifier::parent` ([#505])
### Changed
- `ObjectIdentifier::new` now returns a `Result` ([#458])
[#451]: https://github.com/RustCrypto/formats/pull/451
[#453]: https://github.com/RustCrypto/formats/pull/453
[#456]: https://github.com/RustCrypto/formats/pull/456
[#458]: https://github.com/RustCrypto/formats/pull/458
[#459]: https://github.com/RustCrypto/formats/pull/459
[#479]: https://github.com/RustCrypto/formats/pull/479
[#488]: https://github.com/RustCrypto/formats/pull/488
[#504]: https://github.com/RustCrypto/formats/pull/504
[#505]: https://github.com/RustCrypto/formats/pull/505
## 0.8.0 (2022-01-17)
### Changed
- Leverage `const_panic`; MSRV 1.57 ([#341])
[#341]: https://github.com/RustCrypto/formats/pull/341
## 0.7.1 (2021-11-30)
### Changed
- Increase `MAX_SIZE` to 39 ([#258])
[#258]: https://github.com/RustCrypto/formats/pull/258
## 0.7.0 (2021-11-14) [YANKED]
### Changed
- Rust 2021 edition upgrade; MSRV 1.56 ([#136])
- Rename `MAX_LENGTH` to `MAX_SIZE`; bump to `31` ([#174])
- Make `length` the first field of `ObjectIdentifier` ([#178])
### Fixed
- `debug_assert!` false positive on large arc ([#180])
[#136]: https://github.com/RustCrypto/formats/pull/136
[#174]: https://github.com/RustCrypto/formats/pull/174
[#178]: https://github.com/RustCrypto/formats/pull/178
[#180]: https://github.com/RustCrypto/formats/pull/180
## 0.6.2 (2021-10-14)
### Fixed
- Off-by-one error parsing large BER arcs ([#84])
[#84]: https://github.com/RustCrypto/formats/pull/84
## 0.6.1 (2021-09-14) [YANKED]
### Changed
- Moved to `formats` repo ([#2])
[#2]: https://github.com/RustCrypto/formats/pull/2
## 0.6.0 (2021-06-03) [YANKED]
### Changed
- Modernize and remove deprecations; MSRV 1.51+
## 0.5.2 (2021-04-20)
### Added
- Expand README.md
## 0.5.1 (2021-04-15)
### Added
- `ObjectIdentifier::MAX_LENGTH` constant
### Changed
- Deprecate `ObjectIdentifier::max_len()` function
## 0.5.0 (2021-03-21)
### Added
- `TryFrom<&[u8]>` impl on `ObjectIdentifier`
## Changed
- MSRV 1.47+
- Renamed the following methods:
- `ObjectIdentifier::new` => `ObjectIdentifier::from_arcs`
- `ObjectIdentifier::parse` => `ObjectIdentifier::new`
- `ObjectIdentifier::from_ber` => `ObjectIdentifier::from_bytes`
### Removed
- Deprecated methods
- `alloc` feature - only used by aforementioned deprecated methods
- `TryFrom<&[Arc]>` impl on `ObjectIdentifier` - use `::from_arcs`
## 0.4.5 (2021-03-04)
### Added
- `Hash` and `Ord` impls on `ObjectIdentifier`
## 0.4.4 (2021-02-28)
### Added
- `ObjectIdentifier::as_bytes` method
### Changed
- Internal representation changed to BER/DER
- Deprecated `ObjectIdentifier::ber_len`, `::write_ber`, and `::to_ber`
## 0.4.3 (2021-02-24)
### Added
- Const-friendly OID string parser
## 0.4.2 (2021-02-19)
### Fixed
- Bug in root arc calculation
## 0.4.1 (2020-12-21)
### Fixed
- Bug in const initializer
## 0.4.0 (2020-12-16)
### Added
- `Arcs` iterator
### Changed
- Rename "nodes" to "arcs"
- Layout optimization
- Refactor and improve length limits
## 0.3.5 (2020-12-12)
### Added
- `ObjectIdentifier::{write_ber, to_ber}` methods
## 0.3.4 (2020-12-06)
### Changed
- Documentation improvements
## 0.3.3 (2020-12-05)
### Changed
- Improve description in Cargo.toml/README.md
## 0.3.2 (2020-12-05)
### Changed
- Documentation improvements
## 0.3.1 (2020-12-05)
### Added
- Impl `TryFrom<&[u32]>` for ObjectIdentifier
## 0.3.0 (2020-12-05) [YANKED]
### Added
- Byte and string parsers
## 0.2.0 (2020-09-05)
### Changed
- Validate OIDs are well-formed; MSRV 1.46+
## 0.1.0 (2020-08-04)
- Initial release

58
vendor/const-oid/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,58 @@
# 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 = "2021"
rust-version = "1.57"
name = "const-oid"
version = "0.9.6"
authors = ["RustCrypto Developers"]
description = """
Const-friendly implementation of the ISO/IEC Object Identifier (OID) standard
as defined in ITU X.660, with support for BER/DER encoding/decoding as well as
heapless no_std (i.e. embedded) support
"""
documentation = "https://docs.rs/const-oid"
readme = "README.md"
keywords = [
"iso",
"iec",
"itu",
"oid",
]
categories = [
"cryptography",
"data-structures",
"encoding",
"no-std",
"parser-implementations",
]
license = "Apache-2.0 OR MIT"
repository = "https://github.com/RustCrypto/formats/tree/master/const-oid"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = [
"--cfg",
"docsrs",
]
[dependencies.arbitrary]
version = "1.2"
features = ["derive"]
optional = true
[dev-dependencies.hex-literal]
version = "0.3"
[features]
db = []
std = []

201
vendor/const-oid/LICENSE-APACHE vendored Normal file
View File

@@ -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.

25
vendor/const-oid/LICENSE-MIT vendored Normal file
View File

@@ -0,0 +1,25 @@
Copyright (c) 2020-2022 The RustCrypto Project Developers
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.

96
vendor/const-oid/README.md vendored Normal file
View File

@@ -0,0 +1,96 @@
# [RustCrypto]: Object Identifiers (OIDs)
[![crate][crate-image]][crate-link]
[![Docs][docs-image]][docs-link]
[![Build Status][build-image]][build-link]
![Apache2/MIT licensed][license-image]
![Rust Version][rustc-image]
[![Project Chat][chat-image]][chat-link]
Const-friendly implementation of the ISO/IEC Object Identifier (OID) standard
as defined in ITU [X.660], with support for BER/DER encoding/decoding as well
as heapless `no_std` (i.e. embedded) environments.
[Documentation][docs-link]
## About OIDs
Object Identifiers, a.k.a. OIDs, are an International Telecommunications
Union (ITU) and ISO/IEC standard for naming any object, concept, or "thing"
with a globally unambiguous persistent name.
The ITU's [X.660] standard provides the OID specification. Every OID is part of
a hierarchical namespace which begins with a *root OID*, which is either the
ITU's root OID (0), the ISO's root OID (1), or the joint ISO/ITU root OID (2).
The following is an example of an OID, in this case identifying the
`rsaEncryption` algorithm:
```text
1.2.840.113549.1.1.1
```
For more information, see: <https://en.wikipedia.org/wiki/Object_identifier>
## Implementation
This library supports parsing OIDs in const contexts, e.g.:
```rust
use const_oid::ObjectIdentifier;
pub const MY_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1");
```
The OID parser is implemented entirely in terms of `const fn` and without the
use of proc macros.
Additionally, it also includes a `const fn` OID serializer, and stores the OIDs
parsed from const contexts encoded using the BER/DER serialization
(sans header).
This allows `ObjectIdentifier` to impl `AsRef<[u8]>` which can be used to
obtain the BER/DER serialization of an OID, even one declared `const`.
Additionally, it impls `FromStr` and `TryFrom<&[u8]>` and functions just as
well as a runtime OID library.
## Minimum Supported Rust Version
This crate requires **Rust 1.57** at a minimum.
We may change the MSRV in the future, but it will be accompanied by a minor
version bump.
## License
Licensed under either of:
* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
* [MIT license](http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
[//]: # (badges)
[crate-image]: https://buildstats.info/crate/const-oid
[crate-link]: https://crates.io/crates/const-oid
[docs-image]: https://docs.rs/const-oid/badge.svg
[docs-link]: https://docs.rs/const-oid/
[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.57+-blue.svg
[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg
[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/300570-formats
[build-image]: https://github.com/RustCrypto/formats/workflows/const-oid/badge.svg?branch=master&event=push
[build-link]: https://github.com/RustCrypto/formats/actions
[//]: # (links)
[RustCrypto]: https://github.com/rustcrypto
[X.660]: https://www.itu.int/rec/T-REC-X.660

170
vendor/const-oid/src/arcs.rs vendored Normal file
View File

@@ -0,0 +1,170 @@
//! Arcs are integer values which exist within an OID's hierarchy.
use crate::{Error, ObjectIdentifier, Result};
use core::mem;
/// Type alias used to represent an "arc" (i.e. integer identifier value).
///
/// X.660 does not define a maximum size of an arc.
///
/// The current representation is `u32`, which has been selected as being
/// sufficient to cover the current PKCS/PKIX use cases this library has been
/// used in conjunction with.
///
/// Future versions may potentially make it larger if a sufficiently important
/// use case is discovered.
pub type Arc = u32;
/// Maximum value of the first arc in an OID.
pub(crate) const ARC_MAX_FIRST: Arc = 2;
/// Maximum value of the second arc in an OID.
pub(crate) const ARC_MAX_SECOND: Arc = 39;
/// Maximum number of bytes supported in an arc.
const ARC_MAX_BYTES: usize = mem::size_of::<Arc>();
/// Maximum value of the last byte in an arc.
const ARC_MAX_LAST_OCTET: u8 = 0b11110000; // Max bytes of leading 1-bits
/// [`Iterator`] over [`Arc`] values (a.k.a. nodes) in an [`ObjectIdentifier`].
///
/// This iterates over all arcs in an OID, including the root.
pub struct Arcs<'a> {
/// OID we're iterating over
oid: &'a ObjectIdentifier,
/// Current position within the serialized DER bytes of this OID
cursor: Option<usize>,
}
impl<'a> Arcs<'a> {
/// Create a new iterator over the arcs of this OID
pub(crate) fn new(oid: &'a ObjectIdentifier) -> Self {
Self { oid, cursor: None }
}
/// Try to parse the next arc in this OID.
///
/// This method is fallible so it can be used as a first pass to determine
/// that the arcs in the OID are well-formed.
pub(crate) fn try_next(&mut self) -> Result<Option<Arc>> {
match self.cursor {
// Indicates we're on the root OID
None => {
let root = RootArcs::try_from(self.oid.as_bytes()[0])?;
self.cursor = Some(0);
Ok(Some(root.first_arc()))
}
Some(0) => {
let root = RootArcs::try_from(self.oid.as_bytes()[0])?;
self.cursor = Some(1);
Ok(Some(root.second_arc()))
}
Some(offset) => {
let mut result = 0;
let mut arc_bytes = 0;
loop {
let len = checked_add!(offset, arc_bytes);
match self.oid.as_bytes().get(len).cloned() {
// The arithmetic below includes advance checks
// against `ARC_MAX_BYTES` and `ARC_MAX_LAST_OCTET`
// which ensure the operations will not overflow.
#[allow(clippy::integer_arithmetic)]
Some(byte) => {
arc_bytes = checked_add!(arc_bytes, 1);
if (arc_bytes > ARC_MAX_BYTES) && (byte & ARC_MAX_LAST_OCTET != 0) {
return Err(Error::ArcTooBig);
}
result = result << 7 | (byte & 0b1111111) as Arc;
if byte & 0b10000000 == 0 {
self.cursor = Some(checked_add!(offset, arc_bytes));
return Ok(Some(result));
}
}
None => {
if arc_bytes == 0 {
return Ok(None);
} else {
return Err(Error::Base128);
}
}
}
}
}
}
}
}
impl<'a> Iterator for Arcs<'a> {
type Item = Arc;
fn next(&mut self) -> Option<Arc> {
// ObjectIdentifier constructors should ensure the OID is well-formed
self.try_next().expect("OID malformed")
}
}
/// Byte containing the first and second arcs of an OID.
///
/// This is represented this way in order to reduce the overall size of the
/// [`ObjectIdentifier`] struct.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct RootArcs(u8);
impl RootArcs {
/// Create [`RootArcs`] from the first and second arc values represented
/// as `Arc` integers.
pub(crate) const fn new(first_arc: Arc, second_arc: Arc) -> Result<Self> {
if first_arc > ARC_MAX_FIRST {
return Err(Error::ArcInvalid { arc: first_arc });
}
if second_arc > ARC_MAX_SECOND {
return Err(Error::ArcInvalid { arc: second_arc });
}
// The checks above ensure this operation will not overflow
#[allow(clippy::integer_arithmetic)]
let byte = (first_arc * (ARC_MAX_SECOND + 1)) as u8 + second_arc as u8;
Ok(Self(byte))
}
/// Get the value of the first arc
#[allow(clippy::integer_arithmetic)]
pub(crate) const fn first_arc(self) -> Arc {
self.0 as Arc / (ARC_MAX_SECOND + 1)
}
/// Get the value of the second arc
#[allow(clippy::integer_arithmetic)]
pub(crate) const fn second_arc(self) -> Arc {
self.0 as Arc % (ARC_MAX_SECOND + 1)
}
}
impl TryFrom<u8> for RootArcs {
type Error = Error;
// Ensured not to overflow by constructor invariants
#[allow(clippy::integer_arithmetic)]
fn try_from(octet: u8) -> Result<Self> {
let first = octet as Arc / (ARC_MAX_SECOND + 1);
let second = octet as Arc % (ARC_MAX_SECOND + 1);
let result = Self::new(first, second)?;
debug_assert_eq!(octet, result.0);
Ok(result)
}
}
impl From<RootArcs> for u8 {
fn from(root_arcs: RootArcs) -> u8 {
root_arcs.0
}
}

11
vendor/const-oid/src/checked.rs vendored Normal file
View File

@@ -0,0 +1,11 @@
//! Checked arithmetic helpers.
/// `const fn`-friendly checked addition helper.
macro_rules! checked_add {
($a:expr, $b:expr) => {
match $a.checked_add($b) {
Some(n) => n,
None => return Err(Error::Length),
}
};
}

164
vendor/const-oid/src/db.rs vendored Normal file
View File

@@ -0,0 +1,164 @@
//! OID Names Database
//!
//! The contents of this database are generated from the official IANA
//! [Object Identifier Descriptors] Registry CSV file and from [RFC 5280].
//! If we are missing values you care about, please contribute a patch to
//! `oiddbgen` (a subcrate in the source code) to generate the values from
//! the relevant standard.
//!
//! [RFC 5280]: https://datatracker.ietf.org/doc/html/rfc5280
//! [Object Identifier Descriptors]: https://www.iana.org/assignments/ldap-parameters/ldap-parameters.xhtml#ldap-parameters-3
#![allow(clippy::integer_arithmetic, missing_docs)]
mod gen;
pub use gen::*;
use crate::{Error, ObjectIdentifier};
/// A const implementation of byte equals.
const fn eq(lhs: &[u8], rhs: &[u8]) -> bool {
if lhs.len() != rhs.len() {
return false;
}
let mut i = 0usize;
while i < lhs.len() {
if lhs[i] != rhs[i] {
return false;
}
i += 1;
}
true
}
/// A const implementation of case-insensitive ASCII equals.
const fn eq_case(lhs: &[u8], rhs: &[u8]) -> bool {
if lhs.len() != rhs.len() {
return false;
}
let mut i = 0usize;
while i < lhs.len() {
if !lhs[i].eq_ignore_ascii_case(&rhs[i]) {
return false;
}
i += 1;
}
true
}
/// A query interface for OIDs/Names.
#[derive(Copy, Clone)]
pub struct Database<'a>(&'a [(&'a ObjectIdentifier, &'a str)]);
impl<'a> Database<'a> {
/// Looks up a name for an OID.
///
/// Errors if the input is not a valid OID.
/// Returns the input if no name is found.
pub fn resolve<'b>(&self, oid: &'b str) -> Result<&'b str, Error>
where
'a: 'b,
{
Ok(self.by_oid(&oid.parse()?).unwrap_or(oid))
}
/// Finds a named oid by its associated OID.
pub const fn by_oid(&self, oid: &ObjectIdentifier) -> Option<&'a str> {
let mut i = 0;
while i < self.0.len() {
let lhs = self.0[i].0;
if lhs.length == oid.length && eq(&lhs.bytes, &oid.bytes) {
return Some(self.0[i].1);
}
i += 1;
}
None
}
/// Finds a named oid by its associated name.
pub const fn by_name(&self, name: &str) -> Option<&'a ObjectIdentifier> {
let mut i = 0;
while i < self.0.len() {
let lhs = self.0[i].1;
if eq_case(lhs.as_bytes(), name.as_bytes()) {
return Some(self.0[i].0);
}
i += 1;
}
None
}
/// Return the list of matched name for the OID.
pub const fn find_names_for_oid(&self, oid: ObjectIdentifier) -> Names<'a> {
Names {
database: *self,
oid,
position: 0,
}
}
}
/// Iterator returning the multiple names that may be associated with an OID.
pub struct Names<'a> {
database: Database<'a>,
oid: ObjectIdentifier,
position: usize,
}
impl<'a> Iterator for Names<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
let mut i = self.position;
while i < self.database.0.len() {
let lhs = self.database.0[i].0;
if lhs.as_bytes().eq(self.oid.as_bytes()) {
self.position = i + 1;
return Some(self.database.0[i].1);
}
i += 1;
}
None
}
}
#[cfg(test)]
mod tests {
use crate::ObjectIdentifier;
use super::rfc4519::CN;
#[test]
fn by_oid() {
let cn = super::DB.by_oid(&CN).expect("cn not found");
assert_eq!("cn", cn);
let none = ObjectIdentifier::new_unwrap("0.1.2.3.4.5.6.7.8.9");
assert_eq!(None, super::DB.by_oid(&none));
}
#[test]
fn by_name() {
let cn = super::DB.by_name("CN").expect("cn not found");
assert_eq!(&CN, cn);
assert_eq!(None, super::DB.by_name("purplePeopleEater"));
}
}

4248
vendor/const-oid/src/db/gen.rs vendored Normal file

File diff suppressed because it is too large Load Diff

165
vendor/const-oid/src/encoder.rs vendored Normal file
View File

@@ -0,0 +1,165 @@
//! OID encoder with `const` support.
use crate::{
arcs::{ARC_MAX_FIRST, ARC_MAX_SECOND},
Arc, Error, ObjectIdentifier, Result,
};
/// BER/DER encoder
#[derive(Debug)]
pub(crate) struct Encoder {
/// Current state
state: State,
/// Bytes of the OID being encoded in-progress
bytes: [u8; ObjectIdentifier::MAX_SIZE],
/// Current position within the byte buffer
cursor: usize,
}
/// Current state of the encoder
#[derive(Debug)]
enum State {
/// Initial state - no arcs yet encoded
Initial,
/// First arc parsed
FirstArc(Arc),
/// Encoding base 128 body of the OID
Body,
}
impl Encoder {
/// Create a new encoder initialized to an empty default state.
pub(crate) const fn new() -> Self {
Self {
state: State::Initial,
bytes: [0u8; ObjectIdentifier::MAX_SIZE],
cursor: 0,
}
}
/// Extend an existing OID.
pub(crate) const fn extend(oid: ObjectIdentifier) -> Self {
Self {
state: State::Body,
bytes: oid.bytes,
cursor: oid.length as usize,
}
}
/// Encode an [`Arc`] as base 128 into the internal buffer.
pub(crate) const fn arc(mut self, arc: Arc) -> Result<Self> {
match self.state {
State::Initial => {
if arc > ARC_MAX_FIRST {
return Err(Error::ArcInvalid { arc });
}
self.state = State::FirstArc(arc);
Ok(self)
}
// Ensured not to overflow by `ARC_MAX_SECOND` check
#[allow(clippy::integer_arithmetic)]
State::FirstArc(first_arc) => {
if arc > ARC_MAX_SECOND {
return Err(Error::ArcInvalid { arc });
}
self.state = State::Body;
self.bytes[0] = (first_arc * (ARC_MAX_SECOND + 1)) as u8 + arc as u8;
self.cursor = 1;
Ok(self)
}
// TODO(tarcieri): finer-grained overflow safety / checked arithmetic
#[allow(clippy::integer_arithmetic)]
State::Body => {
// Total number of bytes in encoded arc - 1
let nbytes = base128_len(arc);
// Shouldn't overflow on any 16-bit+ architectures
if self.cursor + nbytes + 1 >= ObjectIdentifier::MAX_SIZE {
return Err(Error::Length);
}
let new_cursor = self.cursor + nbytes + 1;
// TODO(tarcieri): use `?` when stable in `const fn`
match self.encode_base128_byte(arc, nbytes, false) {
Ok(mut encoder) => {
encoder.cursor = new_cursor;
Ok(encoder)
}
Err(err) => Err(err),
}
}
}
}
/// Finish encoding an OID.
pub(crate) const fn finish(self) -> Result<ObjectIdentifier> {
if self.cursor >= 2 {
Ok(ObjectIdentifier {
bytes: self.bytes,
length: self.cursor as u8,
})
} else {
Err(Error::NotEnoughArcs)
}
}
/// Encode a single byte of a Base 128 value.
const fn encode_base128_byte(mut self, mut n: u32, i: usize, continued: bool) -> Result<Self> {
let mask = if continued { 0b10000000 } else { 0 };
// Underflow checked by branch
#[allow(clippy::integer_arithmetic)]
if n > 0x80 {
self.bytes[checked_add!(self.cursor, i)] = (n & 0b1111111) as u8 | mask;
n >>= 7;
if i > 0 {
self.encode_base128_byte(n, i.saturating_sub(1), true)
} else {
Err(Error::Base128)
}
} else {
self.bytes[self.cursor] = n as u8 | mask;
Ok(self)
}
}
}
/// Compute the length - 1 of an arc when encoded in base 128.
const fn base128_len(arc: Arc) -> usize {
match arc {
0..=0x7f => 0,
0x80..=0x3fff => 1,
0x4000..=0x1fffff => 2,
0x200000..=0x1fffffff => 3,
_ => 4,
}
}
#[cfg(test)]
mod tests {
use super::Encoder;
use hex_literal::hex;
/// OID `1.2.840.10045.2.1` encoded as ASN.1 BER/DER
const EXAMPLE_OID_BER: &[u8] = &hex!("2A8648CE3D0201");
#[test]
fn encode() {
let encoder = Encoder::new();
let encoder = encoder.arc(1).unwrap();
let encoder = encoder.arc(2).unwrap();
let encoder = encoder.arc(840).unwrap();
let encoder = encoder.arc(10045).unwrap();
let encoder = encoder.arc(2).unwrap();
let encoder = encoder.arc(1).unwrap();
assert_eq!(&encoder.bytes[..encoder.cursor], EXAMPLE_OID_BER);
}
}

83
vendor/const-oid/src/error.rs vendored Normal file
View File

@@ -0,0 +1,83 @@
//! Error types
use crate::Arc;
use core::fmt;
/// Result type
pub type Result<T> = core::result::Result<T, Error>;
/// OID errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Error {
/// Arc exceeds allowed range (i.e. for first or second OID)
ArcInvalid {
/// Arc value that is erroneous.
arc: Arc,
},
/// Arc is too big (exceeds 32-bit limits of this library).
///
/// Technically the size of an arc is not constrained by X.660, however
/// this library has elected to use `u32` as the arc representation as
/// sufficient for PKIX/PKCS usages.
ArcTooBig,
/// Base 128 encoding error (used in BER/DER serialization of arcs).
Base128,
/// Expected a digit, but was provided something else.
DigitExpected {
/// What was found instead of a digit
actual: u8,
},
/// Input data is empty.
Empty,
/// OID length is invalid (too short or too long).
Length,
/// Minimum 3 arcs required.
NotEnoughArcs,
/// Trailing `.` character at end of input.
TrailingDot,
}
impl Error {
/// Escalate this error into a panic.
///
/// This is a workaround until `Result::unwrap` is allowed in `const fn`.
#[allow(clippy::panic)]
pub(crate) const fn panic(self) -> ! {
match self {
Error::ArcInvalid { .. } | Error::ArcTooBig => panic!("OID contains invalid arc"),
Error::Base128 => panic!("OID contains arc with invalid base 128 encoding"),
Error::DigitExpected { .. } => panic!("OID expected to start with digit"),
Error::Empty => panic!("OID value is empty"),
Error::Length => panic!("OID length invalid"),
Error::NotEnoughArcs => panic!("OID requires minimum of 3 arcs"),
Error::TrailingDot => panic!("OID ends with invalid trailing '.'"),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Error::ArcInvalid { arc } => write!(f, "OID contains out-of-range arc: {}", arc),
Error::ArcTooBig => f.write_str("OID contains arc which is larger than 32-bits"),
Error::Base128 => f.write_str("OID contains arc with invalid base 128 encoding"),
Error::DigitExpected { actual } => {
write!(f, "expected digit, got '{}'", char::from(actual))
}
Error::Empty => f.write_str("OID value is empty"),
Error::Length => f.write_str("OID length invalid"),
Error::NotEnoughArcs => f.write_str("OID requires minimum of 3 arcs"),
Error::TrailingDot => f.write_str("OID ends with invalid trailing '.'"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}

280
vendor/const-oid/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,280 @@
#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
)]
#![forbid(unsafe_code)]
#![warn(
clippy::integer_arithmetic,
clippy::panic,
clippy::panic_in_result_fn,
clippy::unwrap_used,
missing_docs,
rust_2018_idioms,
unused_lifetimes,
unused_qualifications
)]
#[cfg(feature = "std")]
extern crate std;
#[macro_use]
mod checked;
mod arcs;
mod encoder;
mod error;
mod parser;
#[cfg(feature = "db")]
#[cfg_attr(docsrs, doc(cfg(feature = "db")))]
pub mod db;
pub use crate::{
arcs::{Arc, Arcs},
error::{Error, Result},
};
use crate::encoder::Encoder;
use core::{fmt, str::FromStr};
/// A trait which associates an OID with a type.
pub trait AssociatedOid {
/// The OID associated with this type.
const OID: ObjectIdentifier;
}
/// A trait which associates a dynamic, `&self`-dependent OID with a type,
/// which may change depending on the type's value.
///
/// This trait is object safe and auto-impl'd for any types which impl
/// [`AssociatedOid`].
pub trait DynAssociatedOid {
/// Get the OID associated with this value.
fn oid(&self) -> ObjectIdentifier;
}
impl<T: AssociatedOid> DynAssociatedOid for T {
fn oid(&self) -> ObjectIdentifier {
T::OID
}
}
/// Object identifier (OID).
///
/// OIDs are hierarchical structures consisting of "arcs", i.e. integer
/// identifiers.
///
/// # Validity
///
/// In order for an OID to be considered valid by this library, it must meet
/// the following criteria:
///
/// - The OID MUST have at least 3 arcs
/// - The first arc MUST be within the range 0-2
/// - The second arc MUST be within the range 0-39
/// - The BER/DER encoding of the OID MUST be shorter than
/// [`ObjectIdentifier::MAX_SIZE`]
#[derive(Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ObjectIdentifier {
/// Length in bytes
length: u8,
/// Array containing BER/DER-serialized bytes (no header)
bytes: [u8; Self::MAX_SIZE],
}
#[allow(clippy::len_without_is_empty)]
impl ObjectIdentifier {
/// Maximum size of a BER/DER-encoded OID in bytes.
pub const MAX_SIZE: usize = 39; // makes `ObjectIdentifier` 40-bytes total w\ 1-byte length
/// Parse an [`ObjectIdentifier`] from the dot-delimited string form,
/// panicking on parse errors.
///
/// This function exists as a workaround for `unwrap` not yet being
/// stable in `const fn` contexts, and is intended to allow the result to
/// be bound to a constant value:
///
/// ```
/// use const_oid::ObjectIdentifier;
///
/// pub const MY_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.1");
/// ```
///
/// In future versions of Rust it should be possible to replace this with
/// `ObjectIdentifier::new(...).unwrap()`.
///
/// Use [`ObjectIdentifier::new`] for fallible parsing.
// TODO(tarcieri): remove this when `Result::unwrap` is `const fn`
pub const fn new_unwrap(s: &str) -> Self {
match Self::new(s) {
Ok(oid) => oid,
Err(err) => err.panic(),
}
}
/// Parse an [`ObjectIdentifier`] from the dot-delimited string form.
pub const fn new(s: &str) -> Result<Self> {
// TODO(tarcieri): use `?` when stable in `const fn`
match parser::Parser::parse(s) {
Ok(parser) => parser.finish(),
Err(err) => Err(err),
}
}
/// Parse an OID from a slice of [`Arc`] values (i.e. integers).
pub fn from_arcs(arcs: impl IntoIterator<Item = Arc>) -> Result<Self> {
let mut encoder = Encoder::new();
for arc in arcs {
encoder = encoder.arc(arc)?;
}
encoder.finish()
}
/// Parse an OID from from its BER/DER encoding.
pub fn from_bytes(ber_bytes: &[u8]) -> Result<Self> {
let len = ber_bytes.len();
match len {
0 => return Err(Error::Empty),
3..=Self::MAX_SIZE => (),
_ => return Err(Error::NotEnoughArcs),
}
let mut bytes = [0u8; Self::MAX_SIZE];
bytes[..len].copy_from_slice(ber_bytes);
let oid = Self {
bytes,
length: len as u8,
};
// Ensure arcs are well-formed
let mut arcs = oid.arcs();
while arcs.try_next()?.is_some() {}
Ok(oid)
}
/// Get the BER/DER serialization of this OID as bytes.
///
/// Note that this encoding omits the tag/length, and only contains the
/// value portion of the encoded OID.
pub fn as_bytes(&self) -> &[u8] {
&self.bytes[..self.length as usize]
}
/// Return the arc with the given index, if it exists.
pub fn arc(&self, index: usize) -> Option<Arc> {
self.arcs().nth(index)
}
/// Iterate over the arcs (a.k.a. nodes) of an [`ObjectIdentifier`].
///
/// Returns [`Arcs`], an iterator over [`Arc`] values.
pub fn arcs(&self) -> Arcs<'_> {
Arcs::new(self)
}
/// Get the length of this [`ObjectIdentifier`] in arcs.
pub fn len(&self) -> usize {
self.arcs().count()
}
/// Get the parent OID of this one (if applicable).
pub fn parent(&self) -> Option<Self> {
let num_arcs = self.len().checked_sub(1)?;
Self::from_arcs(self.arcs().take(num_arcs)).ok()
}
/// Push an additional arc onto this OID, returning the child OID.
pub const fn push_arc(self, arc: Arc) -> Result<Self> {
// TODO(tarcieri): use `?` when stable in `const fn`
match Encoder::extend(self).arc(arc) {
Ok(encoder) => encoder.finish(),
Err(err) => Err(err),
}
}
}
impl AsRef<[u8]> for ObjectIdentifier {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl FromStr for ObjectIdentifier {
type Err = Error;
fn from_str(string: &str) -> Result<Self> {
Self::new(string)
}
}
impl TryFrom<&[u8]> for ObjectIdentifier {
type Error = Error;
fn try_from(ber_bytes: &[u8]) -> Result<Self> {
Self::from_bytes(ber_bytes)
}
}
impl From<&ObjectIdentifier> for ObjectIdentifier {
fn from(oid: &ObjectIdentifier) -> ObjectIdentifier {
*oid
}
}
impl fmt::Debug for ObjectIdentifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ObjectIdentifier({})", self)
}
}
impl fmt::Display for ObjectIdentifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let len = self.arcs().count();
for (i, arc) in self.arcs().enumerate() {
write!(f, "{}", arc)?;
if let Some(j) = i.checked_add(1) {
if j < len {
write!(f, ".")?;
}
}
}
Ok(())
}
}
// Implement by hand because the derive would create invalid values.
// Use the constructor to create a valid oid with at least 3 arcs.
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for ObjectIdentifier {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let first = u.int_in_range(0..=arcs::ARC_MAX_FIRST)?;
let second = u.int_in_range(0..=arcs::ARC_MAX_SECOND)?;
let third = u.arbitrary()?;
let mut oid = Self::from_arcs([first, second, third])
.map_err(|_| arbitrary::Error::IncorrectFormat)?;
for arc in u.arbitrary_iter()? {
oid = oid
.push_arc(arc?)
.map_err(|_| arbitrary::Error::IncorrectFormat)?;
}
Ok(oid)
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
(Arc::size_hint(depth).0.saturating_mul(3), None)
}
}

112
vendor/const-oid/src/parser.rs vendored Normal file
View File

@@ -0,0 +1,112 @@
//! OID string parser with `const` support.
use crate::{encoder::Encoder, Arc, Error, ObjectIdentifier, Result};
/// Const-friendly OID string parser.
///
/// Parses an OID from the dotted string representation.
#[derive(Debug)]
pub(crate) struct Parser {
/// Current arc in progress
current_arc: Arc,
/// BER/DER encoder
encoder: Encoder,
}
impl Parser {
/// Parse an OID from a dot-delimited string e.g. `1.2.840.113549.1.1.1`
pub(crate) const fn parse(s: &str) -> Result<Self> {
let bytes = s.as_bytes();
if bytes.is_empty() {
return Err(Error::Empty);
}
match bytes[0] {
b'0'..=b'9' => Self {
current_arc: 0,
encoder: Encoder::new(),
}
.parse_bytes(bytes),
actual => Err(Error::DigitExpected { actual }),
}
}
/// Finish parsing, returning the result
pub(crate) const fn finish(self) -> Result<ObjectIdentifier> {
self.encoder.finish()
}
/// Parse the remaining bytes
const fn parse_bytes(mut self, bytes: &[u8]) -> Result<Self> {
match bytes {
// TODO(tarcieri): use `?` when stable in `const fn`
[] => match self.encoder.arc(self.current_arc) {
Ok(encoder) => {
self.encoder = encoder;
Ok(self)
}
Err(err) => Err(err),
},
// TODO(tarcieri): checked arithmetic
#[allow(clippy::integer_arithmetic)]
[byte @ b'0'..=b'9', remaining @ ..] => {
let digit = byte.saturating_sub(b'0');
self.current_arc = self.current_arc * 10 + digit as Arc;
self.parse_bytes(remaining)
}
[b'.', remaining @ ..] => {
if remaining.is_empty() {
return Err(Error::TrailingDot);
}
// TODO(tarcieri): use `?` when stable in `const fn`
match self.encoder.arc(self.current_arc) {
Ok(encoder) => {
self.encoder = encoder;
self.current_arc = 0;
self.parse_bytes(remaining)
}
Err(err) => Err(err),
}
}
[byte, ..] => Err(Error::DigitExpected { actual: *byte }),
}
}
}
#[cfg(test)]
mod tests {
use super::Parser;
use crate::Error;
#[test]
fn parse() {
let oid = Parser::parse("1.23.456").unwrap().finish().unwrap();
assert_eq!(oid, "1.23.456".parse().unwrap());
}
#[test]
fn reject_empty_string() {
assert_eq!(Parser::parse("").err().unwrap(), Error::Empty);
}
#[test]
fn reject_non_digits() {
assert_eq!(
Parser::parse("X").err().unwrap(),
Error::DigitExpected { actual: b'X' }
);
assert_eq!(
Parser::parse("1.2.X").err().unwrap(),
Error::DigitExpected { actual: b'X' }
);
}
#[test]
fn reject_trailing_dot() {
assert_eq!(Parser::parse("1.23.").err().unwrap(), Error::TrailingDot);
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
{"name":"const-oid","vers":"0.9.6","deps":[{"name":"arbitrary","req":"^1.2","features":["derive"],"optional":true,"default_features":true,"target":null,"kind":"normal","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false},{"name":"hex-literal","req":"^0.3","features":[],"optional":false,"default_features":true,"target":null,"kind":"dev","registry":"https://github.com/rust-lang/crates.io-index","package":null,"public":null,"artifact":null,"bindep_target":null,"lib":false}],"features":{"db":[],"std":[]},"features2":null,"cksum":"4699e3b62f2ba72cae255ad5383fb46072198febad16a68aca7598b75a7d84da","yanked":null,"links":null,"rust_version":null,"v":2}

209
vendor/const-oid/tests/lib.rs vendored Normal file
View File

@@ -0,0 +1,209 @@
//! `const-oid` crate tests
// TODO(tarcieri): test full set of OID encoding constraints specified here:
// <https://misc.daniel-marschall.de/asn.1/oid_facts.html>
use const_oid::{Error, ObjectIdentifier};
use hex_literal::hex;
use std::string::ToString;
/// Example OID value with a root arc of `0` (and large arc).
const EXAMPLE_OID_0_STR: &str = "0.9.2342.19200300.100.1.1";
const EXAMPLE_OID_0_BER: &[u8] = &hex!("0992268993F22C640101");
const EXAMPLE_OID_0: ObjectIdentifier = ObjectIdentifier::new_unwrap(EXAMPLE_OID_0_STR);
/// Example OID value with a root arc of `1`.
const EXAMPLE_OID_1_STR: &str = "1.2.840.10045.2.1";
const EXAMPLE_OID_1_BER: &[u8] = &hex!("2A8648CE3D0201");
const EXAMPLE_OID_1: ObjectIdentifier = ObjectIdentifier::new_unwrap(EXAMPLE_OID_1_STR);
/// Example OID value with a root arc of `2`.
const EXAMPLE_OID_2_STR: &str = "2.16.840.1.101.3.4.1.42";
const EXAMPLE_OID_2_BER: &[u8] = &hex!("60864801650304012A");
const EXAMPLE_OID_2: ObjectIdentifier = ObjectIdentifier::new_unwrap(EXAMPLE_OID_2_STR);
/// Example OID value with a large arc
const EXAMPLE_OID_LARGE_ARC_STR: &str = "0.9.2342.19200300.100.1.1";
const EXAMPLE_OID_LARGE_ARC_BER: &[u8] = &hex!("0992268993F22C640101");
const EXAMPLE_OID_LARGE_ARC: ObjectIdentifier =
ObjectIdentifier::new_unwrap("0.9.2342.19200300.100.1.1");
#[test]
fn from_bytes() {
let oid0 = ObjectIdentifier::from_bytes(EXAMPLE_OID_0_BER).unwrap();
assert_eq!(oid0.arc(0).unwrap(), 0);
assert_eq!(oid0.arc(1).unwrap(), 9);
assert_eq!(oid0, EXAMPLE_OID_0);
let oid1 = ObjectIdentifier::from_bytes(EXAMPLE_OID_1_BER).unwrap();
assert_eq!(oid1.arc(0).unwrap(), 1);
assert_eq!(oid1.arc(1).unwrap(), 2);
assert_eq!(oid1, EXAMPLE_OID_1);
let oid2 = ObjectIdentifier::from_bytes(EXAMPLE_OID_2_BER).unwrap();
assert_eq!(oid2.arc(0).unwrap(), 2);
assert_eq!(oid2.arc(1).unwrap(), 16);
assert_eq!(oid2, EXAMPLE_OID_2);
let oid3 = ObjectIdentifier::from_bytes(EXAMPLE_OID_LARGE_ARC_BER).unwrap();
assert_eq!(oid3.arc(0).unwrap(), 0);
assert_eq!(oid3.arc(1).unwrap(), 9);
assert_eq!(oid3.arc(2).unwrap(), 2342);
assert_eq!(oid3.arc(3).unwrap(), 19200300);
assert_eq!(oid3.arc(4).unwrap(), 100);
assert_eq!(oid3.arc(5).unwrap(), 1);
assert_eq!(oid3.arc(6).unwrap(), 1);
assert_eq!(oid3, EXAMPLE_OID_LARGE_ARC);
// Empty
assert_eq!(ObjectIdentifier::from_bytes(&[]), Err(Error::Empty));
// Truncated
assert_eq!(
ObjectIdentifier::from_bytes(&[42]),
Err(Error::NotEnoughArcs)
);
assert_eq!(
ObjectIdentifier::from_bytes(&[42, 134]),
Err(Error::NotEnoughArcs)
);
}
#[test]
fn from_str() {
let oid0 = EXAMPLE_OID_0_STR.parse::<ObjectIdentifier>().unwrap();
assert_eq!(oid0.arc(0).unwrap(), 0);
assert_eq!(oid0.arc(1).unwrap(), 9);
assert_eq!(oid0, EXAMPLE_OID_0);
let oid1 = EXAMPLE_OID_1_STR.parse::<ObjectIdentifier>().unwrap();
assert_eq!(oid1.arc(0).unwrap(), 1);
assert_eq!(oid1.arc(1).unwrap(), 2);
assert_eq!(oid1, EXAMPLE_OID_1);
let oid2 = EXAMPLE_OID_2_STR.parse::<ObjectIdentifier>().unwrap();
assert_eq!(oid2.arc(0).unwrap(), 2);
assert_eq!(oid2.arc(1).unwrap(), 16);
assert_eq!(oid2, EXAMPLE_OID_2);
let oid3 = EXAMPLE_OID_LARGE_ARC_STR
.parse::<ObjectIdentifier>()
.unwrap();
assert_eq!(oid3.arc(0).unwrap(), 0);
assert_eq!(oid3.arc(1).unwrap(), 9);
assert_eq!(oid3.arc(2).unwrap(), 2342);
assert_eq!(oid3.arc(3).unwrap(), 19200300);
assert_eq!(oid3.arc(4).unwrap(), 100);
assert_eq!(oid3.arc(5).unwrap(), 1);
assert_eq!(oid3.arc(6).unwrap(), 1);
assert_eq!(oid3, EXAMPLE_OID_LARGE_ARC);
// Too short
assert_eq!("1.2".parse::<ObjectIdentifier>(), Err(Error::NotEnoughArcs));
// Truncated
assert_eq!(
"1.2.840.10045.2.".parse::<ObjectIdentifier>(),
Err(Error::TrailingDot)
);
// Invalid first arc
assert_eq!(
"3.2.840.10045.2.1".parse::<ObjectIdentifier>(),
Err(Error::ArcInvalid { arc: 3 })
);
// Invalid second arc
assert_eq!(
"1.40.840.10045.2.1".parse::<ObjectIdentifier>(),
Err(Error::ArcInvalid { arc: 40 })
);
}
#[test]
fn display() {
assert_eq!(EXAMPLE_OID_0.to_string(), EXAMPLE_OID_0_STR);
assert_eq!(EXAMPLE_OID_1.to_string(), EXAMPLE_OID_1_STR);
assert_eq!(EXAMPLE_OID_2.to_string(), EXAMPLE_OID_2_STR);
assert_eq!(EXAMPLE_OID_LARGE_ARC.to_string(), EXAMPLE_OID_LARGE_ARC_STR);
}
#[test]
fn try_from_u32_slice() {
let oid1 = ObjectIdentifier::from_arcs([1, 2, 840, 10045, 2, 1]).unwrap();
assert_eq!(oid1.arc(0).unwrap(), 1);
assert_eq!(oid1.arc(1).unwrap(), 2);
assert_eq!(EXAMPLE_OID_1, oid1);
let oid2 = ObjectIdentifier::from_arcs([2, 16, 840, 1, 101, 3, 4, 1, 42]).unwrap();
assert_eq!(oid2.arc(0).unwrap(), 2);
assert_eq!(oid2.arc(1).unwrap(), 16);
assert_eq!(EXAMPLE_OID_2, oid2);
// Too short
assert_eq!(
ObjectIdentifier::from_arcs([1, 2]),
Err(Error::NotEnoughArcs)
);
// Invalid first arc
assert_eq!(
ObjectIdentifier::from_arcs([3, 2, 840, 10045, 3, 1, 7]),
Err(Error::ArcInvalid { arc: 3 })
);
// Invalid second arc
assert_eq!(
ObjectIdentifier::from_arcs([1, 40, 840, 10045, 3, 1, 7]),
Err(Error::ArcInvalid { arc: 40 })
);
}
#[test]
fn as_bytes() {
assert_eq!(EXAMPLE_OID_1.as_bytes(), EXAMPLE_OID_1_BER);
assert_eq!(EXAMPLE_OID_2.as_bytes(), EXAMPLE_OID_2_BER);
}
#[test]
fn parse_empty() {
assert_eq!(ObjectIdentifier::new(""), Err(Error::Empty));
}
#[test]
fn parse_not_enough_arcs() {
assert_eq!(ObjectIdentifier::new("1.2"), Err(Error::NotEnoughArcs));
}
#[test]
fn parse_invalid_first_arc() {
assert_eq!(
ObjectIdentifier::new("3.2.840.10045.3.1.7"),
Err(Error::ArcInvalid { arc: 3 })
);
}
#[test]
fn parse_invalid_second_arc() {
assert_eq!(
ObjectIdentifier::new("1.40.840.10045.3.1.7"),
Err(Error::ArcInvalid { arc: 40 })
);
}
#[test]
fn parent() {
let oid = ObjectIdentifier::new("1.2.3.4").unwrap();
let parent = oid.parent().unwrap();
assert_eq!(parent, ObjectIdentifier::new("1.2.3").unwrap());
assert_eq!(parent.parent(), None);
}
#[test]
fn push_arc() {
let oid = ObjectIdentifier::new("1.2.3").unwrap();
assert_eq!(
oid.push_arc(4).unwrap(),
ObjectIdentifier::new("1.2.3.4").unwrap()
);
}