Skip to content

Commit 437c26a

Browse files
authored
Merge pull request #333 from mattpolzin/feature/331/meta-type-and-encoding
Media Type and Encoding on JSONSchema
2 parents 5a937cb + a05fd35 commit 437c26a

File tree

8 files changed

+317
-61
lines changed

8 files changed

+317
-61
lines changed

Sources/OpenAPIKit/Schema Object/JSONSchemaContext.swift

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,54 @@ extension JSONSchema {
653653
self._minProperties = minProperties
654654
}
655655
}
656+
657+
/// The context that only applies to `.string` schemas.
658+
public struct StringContext: Equatable {
659+
public let maxLength: Int?
660+
let _minLength: Int?
661+
662+
public let contentMediaType: OpenAPI.ContentType?
663+
public let contentEncoding: OpenAPI.ContentEncoding?
664+
665+
public var minLength: Int {
666+
return _minLength ?? 0
667+
}
668+
669+
/// Regular expression
670+
public let pattern: String?
671+
672+
public init(
673+
maxLength: Int? = nil,
674+
minLength: Int? = nil,
675+
pattern: String? = nil,
676+
contentMediaType: OpenAPI.ContentType? = nil,
677+
contentEncoding: OpenAPI.ContentEncoding? = nil
678+
) {
679+
self.maxLength = maxLength
680+
self._minLength = minLength
681+
self.pattern = pattern
682+
self.contentMediaType = contentMediaType
683+
self.contentEncoding = contentEncoding
684+
}
685+
686+
// we make the following a static function so it doesn't muddy the namespace while auto-completing on a value.
687+
public static func _minLength(_ context: StringContext) -> Int? {
688+
return context._minLength
689+
}
690+
}
691+
}
692+
693+
extension OpenAPI {
694+
/// An encoding, as specified in RFC 2054, part 6.1 and RFC 4648.
695+
public enum ContentEncoding: String, Codable {
696+
case _7bit = "7bit"
697+
case _8bit = "8bit"
698+
case binary
699+
case quoted_printable = "quoted-printable"
700+
case base16
701+
case base32
702+
case base64
703+
}
656704
}
657705

658706
// MARK: - Codable
@@ -1068,3 +1116,37 @@ extension JSONSchema.ObjectContext: Decodable {
10681116
return properties
10691117
}
10701118
}
1119+
1120+
extension JSONSchema.StringContext {
1121+
public enum CodingKeys: String, CodingKey {
1122+
case maxLength
1123+
case minLength
1124+
case pattern
1125+
case contentMediaType
1126+
case contentEncoding
1127+
}
1128+
}
1129+
1130+
extension JSONSchema.StringContext: Encodable {
1131+
public func encode(to encoder: Encoder) throws {
1132+
var container = encoder.container(keyedBy: CodingKeys.self)
1133+
1134+
try container.encodeIfPresent(maxLength, forKey: .maxLength)
1135+
try container.encodeIfPresent(_minLength, forKey: .minLength)
1136+
try container.encodeIfPresent(pattern, forKey: .pattern)
1137+
try container.encodeIfPresent(contentMediaType, forKey: .contentMediaType)
1138+
try container.encodeIfPresent(contentEncoding, forKey: .contentEncoding)
1139+
}
1140+
}
1141+
1142+
extension JSONSchema.StringContext: Decodable {
1143+
public init(from decoder: Decoder) throws {
1144+
let container = try decoder.container(keyedBy: CodingKeys.self)
1145+
1146+
maxLength = try container.decodeIfPresent(Int.self, forKey: .maxLength)
1147+
_minLength = try container.decodeIfPresent(Int.self, forKey: .minLength)
1148+
pattern = try container.decodeIfPresent(String.self, forKey: .pattern)
1149+
contentMediaType = try container.decodeIfPresent(OpenAPI.ContentType.self, forKey: .contentMediaType)
1150+
contentEncoding = try container.decodeIfPresent(OpenAPI.ContentEncoding.self, forKey: .contentEncoding)
1151+
}
1152+
}

Sources/OpenAPIKit/_CoreReExport.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ public extension OpenAPI.Response {
4444

4545
public extension JSONSchema {
4646
typealias Permissions = OpenAPIKitCore.Shared.JSONSchemaPermissions
47-
typealias StringContext = OpenAPIKitCore.Shared.StringContext
4847
typealias ReferenceContext = OpenAPIKitCore.Shared.ReferenceContext
4948
}
5049

Sources/OpenAPIKit30/Schema Object/JSONSchemaContext.swift

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,34 @@ extension JSONSchema {
573573
self._minProperties = minProperties
574574
}
575575
}
576+
577+
/// The context that only applies to `.string` schemas.
578+
public struct StringContext: Equatable {
579+
public let maxLength: Int?
580+
let _minLength: Int?
581+
582+
public var minLength: Int {
583+
return _minLength ?? 0
584+
}
585+
586+
/// Regular expression
587+
public let pattern: String?
588+
589+
public init(
590+
maxLength: Int? = nil,
591+
minLength: Int? = nil,
592+
pattern: String? = nil
593+
) {
594+
self.maxLength = maxLength
595+
self._minLength = minLength
596+
self.pattern = pattern
597+
}
598+
599+
// we make the following a static function so it doesn't muddy the namespace while auto-completing on a value.
600+
public static func _minLength(_ context: StringContext) -> Int? {
601+
return context._minLength
602+
}
603+
}
576604
}
577605

578606
// MARK: - Codable
@@ -930,3 +958,31 @@ extension JSONSchema.ObjectContext: Decodable {
930958
return properties
931959
}
932960
}
961+
962+
extension JSONSchema.StringContext {
963+
public enum CodingKeys: String, CodingKey {
964+
case maxLength
965+
case minLength
966+
case pattern
967+
}
968+
}
969+
970+
extension JSONSchema.StringContext: Encodable {
971+
public func encode(to encoder: Encoder) throws {
972+
var container = encoder.container(keyedBy: CodingKeys.self)
973+
974+
try container.encodeIfPresent(maxLength, forKey: .maxLength)
975+
try container.encodeIfPresent(_minLength, forKey: .minLength)
976+
try container.encodeIfPresent(pattern, forKey: .pattern)
977+
}
978+
}
979+
980+
extension JSONSchema.StringContext: Decodable {
981+
public init(from decoder: Decoder) throws {
982+
let container = try decoder.container(keyedBy: CodingKeys.self)
983+
984+
maxLength = try container.decodeIfPresent(Int.self, forKey: .maxLength)
985+
_minLength = try container.decodeIfPresent(Int.self, forKey: .minLength)
986+
pattern = try container.decodeIfPresent(String.self, forKey: .pattern)
987+
}
988+
}

Sources/OpenAPIKit30/_CoreReExport.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ public extension OpenAPI.Response {
4444

4545
public extension JSONSchema {
4646
typealias Permissions = OpenAPIKitCore.Shared.JSONSchemaPermissions
47-
typealias StringContext = OpenAPIKitCore.Shared.StringContext
4847
typealias ReferenceContext = OpenAPIKitCore.Shared.ReferenceContext
4948
}
5049

Sources/OpenAPIKitCompat/Compat30To31.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,16 @@ extension OpenAPIKit30.JSONSchema.ObjectContext: To31 {
551551
}
552552
}
553553

554+
extension OpenAPIKit30.JSONSchema.StringContext: To31 {
555+
fileprivate func to31() -> OpenAPIKit.JSONSchema.StringContext {
556+
OpenAPIKit.JSONSchema.StringContext(
557+
maxLength: maxLength,
558+
minLength: OpenAPIKit30.JSONSchema.StringContext._minLength(self),
559+
pattern: pattern
560+
)
561+
}
562+
}
563+
554564
extension OpenAPIKit30.JSONSchema: To31 {
555565
fileprivate func to31() -> OpenAPIKit.JSONSchema {
556566
let schema: OpenAPIKit.JSONSchema.Schema
@@ -563,7 +573,7 @@ extension OpenAPIKit30.JSONSchema: To31 {
563573
case .integer(let core, let integral):
564574
schema = .integer(core.to31(), integral.to31())
565575
case .string(let core, let stringy):
566-
schema = .string(core.to31(), stringy)
576+
schema = .string(core.to31(), stringy.to31())
567577
case .object(let core, let objective):
568578
schema = .object(core.to31(), objective.to31())
569579
case .array(let core, let listy):

Sources/OpenAPIKitCore/Shared/JSONSchemaSimpleContexts.swift

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,6 @@
66
//
77

88
extension Shared {
9-
/// The context that only applies to `.string` schemas.
10-
public struct StringContext: Equatable {
11-
public let maxLength: Int?
12-
let _minLength: Int?
13-
14-
public var minLength: Int {
15-
return _minLength ?? 0
16-
}
17-
18-
/// Regular expression
19-
public let pattern: String?
20-
21-
public init(
22-
maxLength: Int? = nil,
23-
minLength: Int? = nil,
24-
pattern: String? = nil
25-
) {
26-
self.maxLength = maxLength
27-
self._minLength = minLength
28-
self.pattern = pattern
29-
}
30-
31-
// we make the following a static function so it doesn't muddy the namespace while auto-completing on a value.
32-
public static func _minLength(_ context: StringContext) -> Int? {
33-
return context._minLength
34-
}
35-
}
36-
37-
389
/// The context that only applies to `.reference` schemas.
3910
public struct ReferenceContext: Equatable {
4011
public let required: Bool
@@ -52,31 +23,3 @@ extension Shared {
5223
}
5324
}
5425
}
55-
56-
extension Shared.StringContext {
57-
public enum CodingKeys: String, CodingKey {
58-
case maxLength
59-
case minLength
60-
case pattern
61-
}
62-
}
63-
64-
extension Shared.StringContext: Encodable {
65-
public func encode(to encoder: Encoder) throws {
66-
var container = encoder.container(keyedBy: CodingKeys.self)
67-
68-
try container.encodeIfPresent(maxLength, forKey: .maxLength)
69-
try container.encodeIfPresent(_minLength, forKey: .minLength)
70-
try container.encodeIfPresent(pattern, forKey: .pattern)
71-
}
72-
}
73-
74-
extension Shared.StringContext: Decodable {
75-
public init(from decoder: Decoder) throws {
76-
let container = try decoder.container(keyedBy: CodingKeys.self)
77-
78-
maxLength = try container.decodeIfPresent(Int.self, forKey: .maxLength)
79-
_minLength = try container.decodeIfPresent(Int.self, forKey: .minLength)
80-
pattern = try container.decodeIfPresent(String.self, forKey: .pattern)
81-
}
82-
}

Tests/OpenAPIKitCompatTests/DocumentConversionTests.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1070,7 +1070,7 @@ fileprivate func assertEqualNewToOld(_ newSchema: OpenAPIKit.JSONSchema, _ oldSc
10701070

10711071
case .string(let coreContext, let stringContext):
10721072
let newStringContext = try XCTUnwrap(newSchema.stringContext)
1073-
// TODO: compare string contexts
1073+
assertEqualNewToOld(newStringContext, stringContext)
10741074
try assertEqualNewToOld(newCoreContext, coreContext)
10751075

10761076
case .object(let coreContext, let objectContext):
@@ -1142,6 +1142,15 @@ fileprivate func assertEqualNewToOld(_ newCoreContext: OpenAPIKit.JSONSchemaCont
11421142
XCTAssertEqual(newCoreContext.deprecated, oldCoreContext.deprecated)
11431143
}
11441144

1145+
fileprivate func assertEqualNewToOld(_ newStringContext: OpenAPIKit.JSONSchema.StringContext, _ oldStringContext: OpenAPIKit30.JSONSchema.StringContext) {
1146+
XCTAssertEqual(newStringContext.pattern, oldStringContext.pattern)
1147+
XCTAssertEqual(newStringContext.maxLength, oldStringContext.maxLength)
1148+
XCTAssertEqual(newStringContext.minLength, oldStringContext.minLength)
1149+
XCTAssertEqual(OpenAPIKit.JSONSchema.StringContext._minLength(newStringContext), OpenAPIKit30.JSONSchema.StringContext._minLength(oldStringContext))
1150+
XCTAssertNil(newStringContext.contentEncoding)
1151+
XCTAssertNil(newStringContext.contentMediaType)
1152+
}
1153+
11451154
fileprivate func assertEqualNewToOld(_ newExample: OpenAPIKit.OpenAPI.Example, _ oldExample: OpenAPIKit30.OpenAPI.Example) {
11461155
XCTAssertEqual(newExample.summary, oldExample.summary)
11471156
XCTAssertEqual(newExample.description, oldExample.description)

0 commit comments

Comments
 (0)