Skip to content

Commit

Permalink
Merge pull request #28 from outfoxx/task/asn1-docs
Browse files Browse the repository at this point in the history
Update ASN1 docs
  • Loading branch information
kdubb authored Jan 16, 2023
2 parents e659591 + 2c20c9d commit ab550bb
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 11 deletions.
14 changes: 7 additions & 7 deletions Sources/PotentASN1/ASN1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -300,13 +300,13 @@ public extension ASN1 {
return value
}

/// Values as ``BigInt`` or `nil` if this is not an ``integer(_:)``.
var integerValue: BigInt? {
/// Values as ``ASN1/Integer`` or `nil` if this is not an ``integer(_:)``.
var integerValue: ASN1.Integer? {
guard case .integer(let value) = absolute else { return nil }
return value
}

/// Values as ``BitString`` or `nil` if this is not a ``bitString(_:)``.
/// Values as ``BitString`` or `nil` if this is not a ``bitString(_:_:)``.
var bitStringValue: BitString? {
guard case .bitString(let length, let bytes) = absolute else { return nil }
return BitString(length: length, bytes: bytes)
Expand All @@ -318,7 +318,7 @@ public extension ASN1 {
return value
}

/// Values as ``[UInt64]`` or `nil` if this is not an ``objectIdentifier(_:)``.
/// Values as `[UInt64]` or `nil` if this is not an ``objectIdentifier(_:)``.
var objectIdentifierValue: ObjectIdentifier? {
guard case .objectIdentifier(let value) = absolute else { return nil }
return ObjectIdentifier(value)
Expand Down Expand Up @@ -378,13 +378,13 @@ public extension ASN1 {
return AnyString(value, kind: .ia5)
}

/// Value as ``AnyTime `` or `nil` if this is not a ``utcTime(_:)``.
/// Value as ``AnyTime`` or `nil` if this is not a ``utcTime(_:)``.
var utcTimeValue: AnyTime? {
guard case .utcTime(let value) = absolute else { return nil }
return AnyTime(value, kind: .utc)
}

/// Value as ``AnyTime `` or `nil` if this is not a ``generalizedTime(_:)``.
/// Value as ``AnyTime`` or `nil` if this is not a ``generalizedTime(_:)``.
var generalizedTimeValue: AnyTime? {
guard case .generalizedTime(let value) = absolute else { return nil }
return AnyTime(value, kind: .generalized)
Expand Down Expand Up @@ -454,7 +454,7 @@ public extension ASN1 {
}
}

/// Value as array of ``ASN`` or `nil` if this is not a ``sequence(_:)`` or ``set(_:)``.
/// Value as array of ``ASN1`` or `nil` if this is not a ``sequence(_:)`` or ``set(_:)``.
var collectionValue: [ASN1]? {
switch absolute {
case .set(let value): return value
Expand Down
38 changes: 37 additions & 1 deletion Sources/PotentASN1/ASN1Decoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,25 @@ import Foundation
import PotentCodables


/// Decoding of ASN.1 values into `Decodable` types.
/// Decodes `Decodable` types from ASN.1/DER data or ``ASN1`` value trees using a ``Schema``.
///
/// When decoding a `Decodable` type from ASN.1, the ``ASN1Decoder`` is initialized with a
/// ``Schema`` to direct decoding.
///
/// Decode an example `TBSCertificate` type with an associated `TBSCertificateSchema` as follows:
/// ```swift
/// ASN1Decoder(schema: TBSCertificateSchema)
/// .decode(TBSCertificate.self, from: asn1Data)
/// ```
///
/// See ``Schema`` to learn about defining ASN.1 schemas.
///
/// If the example `TBSCertificate` adopts the ``SchemaSpecified`` protocol, static utility
/// functions can be used to decode types without having to initialize the decoder with a
/// schema. This also ensures the correct schema is always provided to the decoder.
/// ```swift
/// ASN1Decoder.decode(TBSCertificate.self, from: asn1Data)
/// ```
///
public class ASN1Decoder: ValueDecoder<ASN1, ASN1DecoderTransform>, DecodesFromData {

Expand All @@ -27,15 +45,33 @@ public class ASN1Decoder: ValueDecoder<ASN1, ASN1DecoderTransform>, DecodesFromD
)
}

/// Initialize decoder with a specified ``schema``.
///
/// - Parameter schema: Schema to use for decoding.
///
public required init(schema: Schema) {
self.schema = schema
super.init()
}

/// Decode a `Decodable` & ``SchemaSpecified`` type from ASN.1/DER encoded data.
///
/// - Parameters:
/// - type: Type of value to decode.
/// - data: ASN.1/DER encoded data.
/// - Returns: Decoded value of `type`.
/// - Throws:
public static func decode<T: Decodable & SchemaSpecified>(_ type: T.Type, from data: Data) throws -> T {
return try Self(schema: T.asn1Schema).decode(type, from: data)
}

/// Decode a `Decodable` & ``SchemaSpecified`` type from an ``ASN1`` value tree.
///
/// - Parameters:
/// - type: Type of value to decode.
/// - asn1: ASN1 value tree.
/// - Returns: Decoded value of `type`.
///
public static func decodeTree<T: Decodable & SchemaSpecified>(_ type: T.Type, from asn1: ASN1) throws -> T {
return try Self(schema: T.asn1Schema).decodeTree(type, from: asn1)
}
Expand Down
33 changes: 32 additions & 1 deletion Sources/PotentASN1/ASN1Encoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,25 @@ import Foundation
import PotentCodables


/// Encoding of `Encodable` types into ``ASN1`` values.
/// Encodes `Encodable` types into ASN.1/DER data or ``ASN1`` value trees using a ``Schema``.
///
/// When encoding an `Encodable` value to ASN.1, the ``ASN1Encoder`` is initialized with a
/// ``Schema`` to direct encoding.
///
/// Encode an example `TBSCertificate` type with an associated `TBSCertificateSchema` as follows:
/// ```swift
/// ASNEncoder(schema: TBSCertificateSchema)
/// .encode(someCertificate)
/// ```
///
/// See ``Schema`` to learn about defining ASN.1 schemas.
///
/// If the example `TBSCertificate` adopts the ``SchemaSpecified`` protocol, static utility
/// functions can be used to encode values without having to initialize the encoder with a
/// schema. This also ensures the correct schema is always provided to the encoder.
/// ```swift
/// ASN1Encoder.encode(someCertificate)
/// ```
///
public class ASN1Encoder: ValueEncoder<ASN1, ASN1EncoderTransform>, EncodesToData {

Expand All @@ -28,15 +46,28 @@ public class ASN1Encoder: ValueEncoder<ASN1, ASN1EncoderTransform>, EncodesToDat
)
}

/// Initialize encoder with a specified ``Schema``.
///
/// - Parameters schema:
public required init(schema: Schema) {
self.schema = schema
super.init()
}

/// Encode an `Encodeable` & ``SchemaSpecified`` value to ASN.1/DER encoded data.
///
/// - Parameters value: Value to encode.
/// - Throws: `DecodingError` or ``ASN1DERWriter/Error``.
///
public static func encode<T: Encodable & SchemaSpecified>(_ value: T) throws -> Data {
return try Self(schema: T.asn1Schema).encode(value)
}

/// Encode an `Encodeable` & ``SchemaSpecified`` value to an ``ASN1`` value tree.
///
/// - Parameters value: Value to encode.
/// - Throws: `DecodingError` or ``ASN1DERWriter/Error``.
///
public static func encodeTree<T: Encodable & SchemaSpecified>(_ value: T) throws -> ASN1 {
return try Self(schema: T.asn1Schema).encodeTree(value)
}
Expand Down
35 changes: 33 additions & 2 deletions Sources/PotentASN1/Schema.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,39 @@ import OrderedCollections
import PotentCodables


/// ASN.1 schema specification.
///
/// ASN.1 schema specification DSL.
///
/// The most common usage of ASN.1 encoding and decoding requires following a schema.
/// ``Schema`` provides a simple DSL to specify ASN.1 schemas that provides the same
/// capabilities as the official ASN.1 syntax.
///
/// For example, the following is the ``Schema`` for RFC-5280's `TBSCertificate`:
/// ```swift
/// let TBSCertificateSchema: Schema =
/// .sequence([
/// "version": .version(.explicit(0, Version)),
/// "serialNumber": CertificateSerialNumber,
/// "signature": AlgorithmIdentifier(SignatureAlgorithms),
/// "issuer": Name,
/// "validity": Validity,
/// "subject": Name,
/// "subjectPublicKeyInfo": SubjectPublicKeyInfo,
/// "issuerUniqueID": .versioned(range: 1...2, .implicit(1, UniqueIdentifier)),
/// "subjectUniqueID": .versioned(range: 1...2, .implicit(2, UniqueIdentifier)),
/// "extensions": .versioned(range: 2...2, .explicit(3, Extensions))
/// ])
/// ```
///
/// When encoding an `Encodable` type to ASN.1, the ``ASN1Encoder`` is initialized with a
/// ``Schema`` to direct its or encoding. Likewise, when decoding a `Decodable` type from ASN.1
/// the ``ASN1Decoder`` is initialized with a ``Schema``.
///
/// Decode an example `TBSCertificate` type using the above schema as follows:
/// ```swift
/// ASNDecoder(schema: TBSCertificateSchema)
/// .decode(TBSCertificate.self, from: data)
/// ```
///
public indirect enum Schema {

public typealias DynamicMap = [ASN1: Schema]
Expand Down

0 comments on commit ab550bb

Please sign in to comment.