diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2022-12-09 21:51:06 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-12-09 21:51:06 +0000 |
commit | c72e9f07a9dc9940b306c511fd91be6f707e6be6 (patch) | |
tree | c0affd3a2a6ff5a102d41969ff042dd497b7b3bb | |
parent | fc7a3870f7ac371af7ff47be9b6299201edea5d9 (diff) | |
parent | 5307b41af8dcf634fdfdf7954b90458026cb1208 (diff) | |
download | der-c72e9f07a9dc9940b306c511fd91be6f707e6be6.tar.gz |
Merge "Upgrade der to 0.6.1"main-16k-with-phones
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | Android.bp | 4 | ||||
-rw-r--r-- | CHANGELOG.md | 12 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | Cargo.toml.orig | 2 | ||||
-rw-r--r-- | LICENSE-MIT | 25 | ||||
-rw-r--r-- | METADATA | 13 | ||||
-rw-r--r-- | src/asn1.rs | 4 | ||||
-rw-r--r-- | src/asn1/any.rs | 10 | ||||
-rw-r--r-- | src/asn1/bit_string.rs | 11 | ||||
-rw-r--r-- | src/asn1/ia5_string.rs | 30 | ||||
-rw-r--r-- | src/asn1/integer/bigint.rs | 8 | ||||
-rw-r--r-- | src/asn1/octet_string.rs | 3 | ||||
-rw-r--r-- | src/asn1/printable_string.rs | 34 | ||||
-rw-r--r-- | src/asn1/teletex_string.rs | 144 | ||||
-rw-r--r-- | src/asn1/utf8_string.rs | 30 | ||||
-rw-r--r-- | src/asn1/videotex_string.rs | 143 | ||||
-rw-r--r-- | src/lib.rs | 14 | ||||
-rw-r--r-- | src/str_slice.rs | 2 | ||||
-rw-r--r-- | src/tag.rs | 14 |
20 files changed, 413 insertions, 95 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index fd618ae..db1ff23 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "00f6c926a7aaed60441e17b93cd3e3fe5b93650e" + "sha1": "14164f9dccd1ba4ceed9938f792b4e99874ef8e0" }, "path_in_vcs": "der" }
\ No newline at end of file @@ -1,8 +1,6 @@ // This file is generated by cargo2android.py --config cargo2android.json. // Do not modify this file as changes will be overridden on upgrade. - - package { default_applicable_licenses: ["external_rust_crates_der_license"], } @@ -37,7 +35,7 @@ rust_library_host { name: "libder", crate_name: "der", cargo_env_compat: true, - cargo_pkg_version: "0.6.0", + cargo_pkg_version: "0.6.1", srcs: ["src/lib.rs"], edition: "2021", features: [ diff --git a/CHANGELOG.md b/CHANGELOG.md index 451056d..0472850 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ 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.6.1 (2022-12-05) +### Added +- Rudimentary implementation of `TeletexString` and `VideotexString` ([#691]) +- Impl `ValueOrd` for `FlagSet<T>` and `UIntRef` ([#723]) + +### Changed +- Eliminate some boilerplate code by using `Deref` ([#697]) + +[#691]: https://github.com/RustCrypto/formats/pull/691 +[#697]: https://github.com/RustCrypto/formats/pull/697 +[#723]: https://github.com/RustCrypto/formats/pull/723 + ## 0.6.0 (2022-05-08) ### Added - Impl `ValueOrd` for `SetOf` and `SetOfVec` ([#362]) @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.57" name = "der" -version = "0.6.0" +version = "0.6.1" authors = ["RustCrypto Developers"] description = """ Pure Rust embedded-friendly implementation of the Distinguished Encoding Rules @@ -36,7 +36,6 @@ categories = [ ] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/formats/tree/master/der" -resolver = "2" [package.metadata.docs.rs] all-features = true diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 7c34417..f8c7dfe 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "der" -version = "0.6.0" +version = "0.6.1" description = """ Pure Rust embedded-friendly implementation of the Distinguished Encoding Rules (DER) for Abstract Syntax Notation One (ASN.1) as described in ITU X.690 with diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..1b78809 --- /dev/null +++ b/LICENSE-MIT @@ -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. @@ -1,3 +1,7 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update rust/crates/der +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md + name: "der" description: "Pure Rust embedded-friendly implementation of the Distinguished Encoding Rules (DER) for Abstract Syntax Notation One (ASN.1) as described in ITU X.690." third_party { @@ -7,14 +11,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/der/der-0.6.0.crate" + value: "https://static.crates.io/crates/der/der-0.6.1.crate" } - version: "0.6.0" - # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same. + version: "0.6.1" license_type: NOTICE last_upgrade_date { year: 2022 - month: 8 - day: 31 + month: 12 + day: 9 } } diff --git a/src/asn1.rs b/src/asn1.rs index 0f7290c..34d692b 100644 --- a/src/asn1.rs +++ b/src/asn1.rs @@ -20,8 +20,10 @@ mod real; mod sequence; mod sequence_of; mod set_of; +mod teletex_string; mod utc_time; mod utf8_string; +mod videotex_string; pub use self::{ any::AnyRef, @@ -37,8 +39,10 @@ pub use self::{ sequence::{Sequence, SequenceRef}, sequence_of::{SequenceOf, SequenceOfIter}, set_of::{SetOf, SetOfIter}, + teletex_string::TeletexStringRef, utc_time::UtcTime, utf8_string::Utf8StringRef, + videotex_string::VideotexStringRef, }; #[cfg(feature = "alloc")] diff --git a/src/asn1/any.rs b/src/asn1/any.rs index 717d666..cb65f23 100644 --- a/src/asn1/any.rs +++ b/src/asn1/any.rs @@ -128,6 +128,16 @@ impl<'a> AnyRef<'a> { self.try_into() } + /// Attempt to decode an ASN.1 `TeletexString`. + pub fn teletex_string(self) -> Result<TeletexStringRef<'a>> { + self.try_into() + } + + /// Attempt to decode an ASN.1 `VideotexString`. + pub fn videotex_string(self) -> Result<VideotexStringRef<'a>> { + self.try_into() + } + /// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new /// nested reader and calling the provided argument with it. pub fn sequence<F, T>(self, f: F) -> Result<T> diff --git a/src/asn1/bit_string.rs b/src/asn1/bit_string.rs index 7eea5a5..eed14e4 100644 --- a/src/asn1/bit_string.rs +++ b/src/asn1/bit_string.rs @@ -376,6 +376,17 @@ impl<T: flagset::Flags> FixedTag for flagset::FlagSet<T> { } #[cfg(feature = "flagset")] +impl<T> ValueOrd for flagset::FlagSet<T> +where + T: flagset::Flags, + T::Type: Ord, +{ + fn value_cmp(&self, other: &Self) -> Result<Ordering> { + Ok(self.bits().cmp(&other.bits())) + } +} + +#[cfg(feature = "flagset")] #[allow(clippy::integer_arithmetic)] impl<'a, T> DecodeValue<'a> for flagset::FlagSet<T> where diff --git a/src/asn1/ia5_string.rs b/src/asn1/ia5_string.rs index c1dbfaa..3971270 100644 --- a/src/asn1/ia5_string.rs +++ b/src/asn1/ia5_string.rs @@ -4,7 +4,7 @@ use crate::{ asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, Result, StrSlice, Tag, Writer, }; -use core::{fmt, str}; +use core::{fmt, ops::Deref, str}; /// ASN.1 `IA5String` type. /// @@ -41,25 +41,13 @@ impl<'a> Ia5StringRef<'a> { .map(|inner| Self { inner }) .map_err(|_| Self::TAG.value_error()) } +} - /// Borrow the string as a `str`. - pub fn as_str(&self) -> &'a str { - self.inner.as_str() - } +impl<'a> Deref for Ia5StringRef<'a> { + type Target = StrSlice<'a>; - /// Borrow the string as bytes. - pub fn as_bytes(&self) -> &'a [u8] { - self.inner.as_bytes() - } - - /// Get the length of the inner byte slice. - pub fn len(&self) -> Length { - self.inner.len() - } - - /// Is the inner string empty? - pub fn is_empty(&self) -> bool { - self.inner.is_empty() + fn deref(&self) -> &Self::Target { + &self.inner } } @@ -117,12 +105,6 @@ impl<'a> From<Ia5StringRef<'a>> for AnyRef<'a> { } } -impl<'a> From<Ia5StringRef<'a>> for &'a [u8] { - fn from(printable_string: Ia5StringRef<'a>) -> &'a [u8] { - printable_string.as_bytes() - } -} - impl<'a> fmt::Display for Ia5StringRef<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) diff --git a/src/asn1/integer/bigint.rs b/src/asn1/integer/bigint.rs index 7a73c48..f896406 100644 --- a/src/asn1/integer/bigint.rs +++ b/src/asn1/integer/bigint.rs @@ -2,8 +2,8 @@ use super::uint; use crate::{ - asn1::AnyRef, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, - Reader, Result, Tag, Writer, + asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, ErrorKind, + FixedTag, Header, Length, Reader, Result, Tag, Writer, }; /// "Big" unsigned ASN.1 `INTEGER` type. @@ -13,7 +13,7 @@ use crate::{ /// /// Intended for use cases like very large integers that are used in /// cryptographic applications (e.g. keys, signatures). -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct UIntRef<'a> { /// Inner value inner: ByteSlice<'a>, @@ -92,6 +92,8 @@ impl<'a> FixedTag for UIntRef<'a> { const TAG: Tag = Tag::Integer; } +impl<'a> OrdIsValueOrd for UIntRef<'a> {} + #[cfg(test)] mod tests { use super::UIntRef; diff --git a/src/asn1/octet_string.rs b/src/asn1/octet_string.rs index 9f78c96..6f5b91a 100644 --- a/src/asn1/octet_string.rs +++ b/src/asn1/octet_string.rs @@ -177,3 +177,6 @@ impl<'a> From<&'a OctetString> for OctetStringRef<'a> { OctetStringRef::new(&octet_string.inner).expect("invalid OCTET STRING") } } + +#[cfg(feature = "alloc")] +impl OrdIsValueOrd for OctetString {} diff --git a/src/asn1/printable_string.rs b/src/asn1/printable_string.rs index c5560a0..d48f90f 100644 --- a/src/asn1/printable_string.rs +++ b/src/asn1/printable_string.rs @@ -4,11 +4,11 @@ use crate::{ asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, Result, StrSlice, Tag, Writer, }; -use core::{fmt, str}; +use core::{fmt, ops::Deref, str}; /// ASN.1 `PrintableString` type. /// -/// Supports a subset the ASCII character set (desribed below). +/// Supports a subset the ASCII character set (described below). /// /// For UTF-8, use [`Utf8StringRef`][`crate::asn1::Utf8StringRef`] instead. /// For the full ASCII character set, use @@ -49,7 +49,7 @@ impl<'a> PrintableStringRef<'a> { { let input = input.as_ref(); - // Validate all characters are within PrintedString's allowed set + // Validate all characters are within PrintableString's allowed set for &c in input.iter() { match c { b'A'..=b'Z' @@ -75,25 +75,13 @@ impl<'a> PrintableStringRef<'a> { .map(|inner| Self { inner }) .map_err(|_| Self::TAG.value_error()) } +} - /// Borrow the string as a `str`. - pub fn as_str(&self) -> &'a str { - self.inner.as_str() - } +impl<'a> Deref for PrintableStringRef<'a> { + type Target = StrSlice<'a>; - /// Borrow the string as bytes. - pub fn as_bytes(&self) -> &'a [u8] { - self.inner.as_bytes() - } - - /// Get the length of the inner byte slice. - pub fn len(&self) -> Length { - self.inner.len() - } - - /// Is the inner string empty? - pub fn is_empty(&self) -> bool { - self.inner.is_empty() + fn deref(&self) -> &Self::Target { + &self.inner } } @@ -151,12 +139,6 @@ impl<'a> From<PrintableStringRef<'a>> for AnyRef<'a> { } } -impl<'a> From<PrintableStringRef<'a>> for &'a [u8] { - fn from(printable_string: PrintableStringRef<'a>) -> &'a [u8] { - printable_string.as_bytes() - } -} - impl<'a> fmt::Display for PrintableStringRef<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) diff --git a/src/asn1/teletex_string.rs b/src/asn1/teletex_string.rs new file mode 100644 index 0000000..7d6621d --- /dev/null +++ b/src/asn1/teletex_string.rs @@ -0,0 +1,144 @@ +//! ASN.1 `TeletexString` support. + +use crate::{ + asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, + Length, Reader, Result, StrSlice, Tag, Writer, +}; +use core::{fmt, ops::Deref, str}; + +/// ASN.1 `TeletexString` type. +/// +/// Supports a subset the ASCII character set (described below). +/// +/// For UTF-8, use [`Utf8StringRef`][`crate::asn1::Utf8StringRef`] instead. +/// For the full ASCII character set, use +/// [`Ia5StringRef`][`crate::asn1::Ia5StringRef`]. +/// +/// This is a zero-copy reference type which borrows from the input data. +/// +/// # Supported characters +/// +/// The standard defines a complex character set allowed in this type. However, quoting the ASN.1 +/// mailing list, "a sizable volume of software in the world treats TeletexString (T61String) as a +/// simple 8-bit string with mostly Windows Latin 1 (superset of iso-8859-1) encoding". +/// +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] +pub struct TeletexStringRef<'a> { + /// Inner value + inner: StrSlice<'a>, +} + +impl<'a> TeletexStringRef<'a> { + /// Create a new ASN.1 `TeletexString`. + pub fn new<T>(input: &'a T) -> Result<Self> + where + T: AsRef<[u8]> + ?Sized, + { + let input = input.as_ref(); + + // FIXME: support higher part of the charset + if input.iter().any(|&c| c > 0x7F) { + return Err(Self::TAG.value_error()); + } + + StrSlice::from_bytes(input) + .map(|inner| Self { inner }) + .map_err(|_| Self::TAG.value_error()) + } +} + +impl<'a> Deref for TeletexStringRef<'a> { + type Target = StrSlice<'a>; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl AsRef<str> for TeletexStringRef<'_> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<[u8]> for TeletexStringRef<'_> { + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +impl<'a> DecodeValue<'a> for TeletexStringRef<'a> { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + Self::new(ByteSlice::decode_value(reader, header)?.as_slice()) + } +} + +impl<'a> EncodeValue for TeletexStringRef<'a> { + fn value_len(&self) -> Result<Length> { + self.inner.value_len() + } + + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + self.inner.encode_value(writer) + } +} + +impl FixedTag for TeletexStringRef<'_> { + const TAG: Tag = Tag::TeletexString; +} + +impl OrdIsValueOrd for TeletexStringRef<'_> {} + +impl<'a> From<&TeletexStringRef<'a>> for TeletexStringRef<'a> { + fn from(value: &TeletexStringRef<'a>) -> TeletexStringRef<'a> { + *value + } +} + +impl<'a> TryFrom<AnyRef<'a>> for TeletexStringRef<'a> { + type Error = Error; + + fn try_from(any: AnyRef<'a>) -> Result<TeletexStringRef<'a>> { + any.decode_into() + } +} + +impl<'a> From<TeletexStringRef<'a>> for AnyRef<'a> { + fn from(teletex_string: TeletexStringRef<'a>) -> AnyRef<'a> { + AnyRef::from_tag_and_value(Tag::TeletexString, teletex_string.inner.into()) + } +} + +impl<'a> fmt::Display for TeletexStringRef<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + +impl<'a> fmt::Debug for TeletexStringRef<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "TeletexString({:?})", self.as_str()) + } +} + +#[cfg(test)] +mod tests { + use super::TeletexStringRef; + use crate::Decode; + use crate::SliceWriter; + + #[test] + fn parse_bytes() { + let example_bytes = &[ + 0x14, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31, + ]; + + let teletex_string = TeletexStringRef::from_der(example_bytes).unwrap(); + assert_eq!(teletex_string.as_str(), "Test User 1"); + let mut out = [0_u8; 30]; + let mut writer = SliceWriter::new(&mut out); + writer.encode(&teletex_string).unwrap(); + let encoded = writer.finish().unwrap(); + assert_eq!(encoded, example_bytes); + } +} diff --git a/src/asn1/utf8_string.rs b/src/asn1/utf8_string.rs index 9f7a1bc..1a06411 100644 --- a/src/asn1/utf8_string.rs +++ b/src/asn1/utf8_string.rs @@ -4,7 +4,7 @@ use crate::{ asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, Result, StrSlice, Tag, Writer, }; -use core::{fmt, str}; +use core::{fmt, ops::Deref, str}; #[cfg(feature = "alloc")] use alloc::{borrow::ToOwned, string::String}; @@ -37,25 +37,13 @@ impl<'a> Utf8StringRef<'a> { { StrSlice::from_bytes(input.as_ref()).map(|inner| Self { inner }) } +} - /// Borrow the string as a `str`. - pub fn as_str(&self) -> &'a str { - self.inner.as_str() - } +impl<'a> Deref for Utf8StringRef<'a> { + type Target = StrSlice<'a>; - /// Borrow the string as bytes. - pub fn as_bytes(&self) -> &'a [u8] { - self.inner.as_bytes() - } - - /// Get the length of the inner byte slice. - pub fn len(&self) -> Length { - self.inner.len() - } - - /// Is the inner string empty? - pub fn is_empty(&self) -> bool { - self.inner.is_empty() + fn deref(&self) -> &Self::Target { + &self.inner } } @@ -113,12 +101,6 @@ impl<'a> From<Utf8StringRef<'a>> for AnyRef<'a> { } } -impl<'a> From<Utf8StringRef<'a>> for &'a [u8] { - fn from(utf8_string: Utf8StringRef<'a>) -> &'a [u8] { - utf8_string.as_bytes() - } -} - impl<'a> fmt::Display for Utf8StringRef<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(self.as_str()) diff --git a/src/asn1/videotex_string.rs b/src/asn1/videotex_string.rs new file mode 100644 index 0000000..b758a22 --- /dev/null +++ b/src/asn1/videotex_string.rs @@ -0,0 +1,143 @@ +//! ASN.1 `VideotexString` support. + +use crate::{ + asn1::AnyRef, ord::OrdIsValueOrd, ByteSlice, DecodeValue, EncodeValue, Error, FixedTag, Header, + Length, Reader, Result, StrSlice, Tag, Writer, +}; +use core::{fmt, ops::Deref, str}; + +/// ASN.1 `VideotexString` type. +/// +/// Supports a subset the ASCII character set (described below). +/// +/// For UTF-8, use [`Utf8StringRef`][`crate::asn1::Utf8StringRef`] instead. +/// For the full ASCII character set, use +/// [`Ia5StringRef`][`crate::asn1::Ia5StringRef`]. +/// +/// This is a zero-copy reference type which borrows from the input data. +/// +/// # Supported characters +/// +/// For the practical purposes VideotexString is treated as IA5string, disallowing non-ASCII chars. +/// +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] +pub struct VideotexStringRef<'a> { + /// Inner value + inner: StrSlice<'a>, +} + +impl<'a> VideotexStringRef<'a> { + /// Create a new ASN.1 `VideotexString`. + pub fn new<T>(input: &'a T) -> Result<Self> + where + T: AsRef<[u8]> + ?Sized, + { + let input = input.as_ref(); + + // Validate all characters are within VideotexString's allowed set + // FIXME: treat as if it were IA5String + if input.iter().any(|&c| c > 0x7F) { + return Err(Self::TAG.value_error()); + } + + StrSlice::from_bytes(input) + .map(|inner| Self { inner }) + .map_err(|_| Self::TAG.value_error()) + } +} + +impl<'a> Deref for VideotexStringRef<'a> { + type Target = StrSlice<'a>; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl AsRef<str> for VideotexStringRef<'_> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<[u8]> for VideotexStringRef<'_> { + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +impl<'a> DecodeValue<'a> for VideotexStringRef<'a> { + fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> { + Self::new(ByteSlice::decode_value(reader, header)?.as_slice()) + } +} + +impl<'a> EncodeValue for VideotexStringRef<'a> { + fn value_len(&self) -> Result<Length> { + self.inner.value_len() + } + + fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> { + self.inner.encode_value(writer) + } +} + +impl FixedTag for VideotexStringRef<'_> { + const TAG: Tag = Tag::VideotexString; +} + +impl OrdIsValueOrd for VideotexStringRef<'_> {} + +impl<'a> From<&VideotexStringRef<'a>> for VideotexStringRef<'a> { + fn from(value: &VideotexStringRef<'a>) -> VideotexStringRef<'a> { + *value + } +} + +impl<'a> TryFrom<AnyRef<'a>> for VideotexStringRef<'a> { + type Error = Error; + + fn try_from(any: AnyRef<'a>) -> Result<VideotexStringRef<'a>> { + any.decode_into() + } +} + +impl<'a> From<VideotexStringRef<'a>> for AnyRef<'a> { + fn from(printable_string: VideotexStringRef<'a>) -> AnyRef<'a> { + AnyRef::from_tag_and_value(Tag::VideotexString, printable_string.inner.into()) + } +} + +impl<'a> From<VideotexStringRef<'a>> for &'a [u8] { + fn from(printable_string: VideotexStringRef<'a>) -> &'a [u8] { + printable_string.as_bytes() + } +} + +impl<'a> fmt::Display for VideotexStringRef<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + +impl<'a> fmt::Debug for VideotexStringRef<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "VideotexString({:?})", self.as_str()) + } +} + +#[cfg(test)] +mod tests { + use super::VideotexStringRef; + use crate::Decode; + + #[test] + fn parse_bytes() { + let example_bytes = &[ + 0x15, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x31, + ]; + + let printable_string = VideotexStringRef::from_der(example_bytes).unwrap(); + assert_eq!(printable_string.as_str(), "Test User 1"); + } +} @@ -2,8 +2,8 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![doc = include_str!("../README.md")] #![doc( - html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" + 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( @@ -52,6 +52,8 @@ //! - [`ObjectIdentifier`]: ASN.1 `OBJECT IDENTIFIER`. //! - [`OctetString`], [`OctetStringRef`]: ASN.1 `OCTET STRING`. //! - [`PrintableStringRef`]: ASN.1 `PrintableString` (ASCII subset). +//! - [`TeletexStringRef`]: ASN.1 `TeletexString`. +//! - [`VideotexStringRef`]: ASN.1 `VideotexString`. //! - [`SequenceOf`]: ASN.1 `SEQUENCE OF`. //! - [`SetOf`], [`SetOfVec`]: ASN.1 `SET OF`. //! - [`UIntRef`]: ASN.1 unsigned `INTEGER` with raw access to encoded bytes. @@ -308,19 +310,21 @@ //! [A Layman's Guide to a Subset of ASN.1, BER, and DER]: https://luca.ntop.org/Teaching/Appunti/asn1.html //! [A Warm Welcome to ASN.1 and DER]: https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/ //! -//! [`Any`]: asn1::AnyRef +//! [`Any`]: asn1::Any //! [`AnyRef`]: asn1::AnyRef //! [`ContextSpecific`]: asn1::ContextSpecific //! [`ContextSpecificRef`]: asn1::ContextSpecificRef -//! [`BitString`]: asn1::BitStringRef +//! [`BitString`]: asn1::BitString //! [`BitStringRef`]: asn1::BitStringRef //! [`GeneralizedTime`]: asn1::GeneralizedTime //! [`Ia5StringRef`]: asn1::Ia5StringRef //! [`Null`]: asn1::Null //! [`ObjectIdentifier`]: asn1::ObjectIdentifier -//! [`OctetString`]: asn1::OctetStringRef +//! [`OctetString`]: asn1::OctetString //! [`OctetStringRef`]: asn1::OctetStringRef //! [`PrintableStringRef`]: asn1::PrintableStringRef +//! [`TeletexStringRef`]: asn1::TeletexStringRef +//! [`VideotexStringRef`]: asn1::VideotexStringRef //! [`SequenceOf`]: asn1::SequenceOf //! [`SetOf`]: asn1::SetOf //! [`SetOfVec`]: asn1::SetOfVec diff --git a/src/str_slice.rs b/src/str_slice.rs index 0016e95..8c94528 100644 --- a/src/str_slice.rs +++ b/src/str_slice.rs @@ -6,7 +6,7 @@ use core::str; /// String slice newtype which respects the [`Length::max`] limit. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub(crate) struct StrSlice<'a> { +pub struct StrSlice<'a> { /// Inner value pub(crate) inner: &'a str, @@ -88,6 +88,12 @@ pub enum Tag { /// `PrintableString` tag: `19`. PrintableString, + /// `TeletexString` tag: `20`. + TeletexString, + + /// `VideotexString` tag: `21`. + VideotexString, + /// `IA5String` tag: `22`. Ia5String, @@ -199,6 +205,8 @@ impl Tag { Tag::Set => 0x11 | CONSTRUCTED_FLAG, Tag::NumericString => 0x12, Tag::PrintableString => 0x13, + Tag::TeletexString => 0x14, + Tag::VideotexString => 0x15, Tag::Ia5String => 0x16, Tag::UtcTime => 0x17, Tag::GeneralizedTime => 0x18, @@ -266,6 +274,8 @@ impl TryFrom<u8> for Tag { 0x0C => Ok(Tag::Utf8String), 0x12 => Ok(Tag::NumericString), 0x13 => Ok(Tag::PrintableString), + 0x14 => Ok(Tag::TeletexString), + 0x15 => Ok(Tag::VideotexString), 0x16 => Ok(Tag::Ia5String), 0x17 => Ok(Tag::UtcTime), 0x18 => Ok(Tag::GeneralizedTime), @@ -341,6 +351,8 @@ impl fmt::Display for Tag { Tag::Set => f.write_str("SET"), Tag::NumericString => f.write_str("NumericString"), Tag::PrintableString => f.write_str("PrintableString"), + Tag::TeletexString => f.write_str("TeletexString"), + Tag::VideotexString => f.write_str("VideotexString"), Tag::Ia5String => f.write_str("IA5String"), Tag::UtcTime => f.write_str("UTCTime"), Tag::GeneralizedTime => f.write_str("GeneralizedTime"), @@ -403,6 +415,8 @@ mod tests { assert_eq!(Tag::Set.class(), Class::Universal); assert_eq!(Tag::NumericString.class(), Class::Universal); assert_eq!(Tag::PrintableString.class(), Class::Universal); + assert_eq!(Tag::TeletexString.class(), Class::Universal); + assert_eq!(Tag::VideotexString.class(), Class::Universal); assert_eq!(Tag::Ia5String.class(), Class::Universal); assert_eq!(Tag::UtcTime.class(), Class::Universal); assert_eq!(Tag::GeneralizedTime.class(), Class::Universal); |