Skip to content

Commit cf419da

Browse files
committed
Add stringification for image formats
1 parent ec428d2 commit cf419da

File tree

5 files changed

+137
-17
lines changed

5 files changed

+137
-17
lines changed

Sources/Overlays/_Testing_CoreGraphics/Attachments/AttachableImageFormat+UTType.swift

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,7 @@ extension AttachableImageFormat {
2424
/// @Available(Swift, introduced: 6.3)
2525
/// }
2626
public var contentType: UTType {
27-
switch kind {
28-
case .png:
29-
return .png
30-
case .jpeg:
31-
return .jpeg
32-
case let .systemValue(contentType):
33-
return contentType as! UTType
34-
}
27+
kind.contentType
3528
}
3629

3730
/// Initialize an instance of this type with the given content type and
@@ -102,4 +95,30 @@ extension AttachableImageFormat {
10295
self.init(contentType: contentType, encodingQuality: encodingQuality)
10396
}
10497
}
98+
99+
// MARK: - CustomStringConvertible, CustomDebugStringConvertible
100+
101+
@available(_uttypesAPI, *)
102+
extension AttachableImageFormat.Kind: CustomStringConvertible, CustomDebugStringConvertible {
103+
/// The content type corresponding to this image format.
104+
fileprivate var contentType: UTType {
105+
switch self {
106+
case .png:
107+
return .png
108+
case .jpeg:
109+
return .jpeg
110+
case let .systemValue(contentType):
111+
return contentType as! UTType
112+
}
113+
}
114+
115+
package var description: String {
116+
contentType.localizedDescription
117+
}
118+
119+
package var debugDescription: String {
120+
let contentType = contentType
121+
return "\(contentType.localizedDescription) (\(contentType.identifier))"
122+
}
123+
}
105124
#endif

Sources/Overlays/_Testing_WinSDK/Attachments/AttachableImageFormat+CLSID.swift

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,7 @@ extension AttachableImageFormat {
196196
@_spi(_)
197197
#endif
198198
public var encoderCLSID: CLSID {
199-
switch kind {
200-
case .png:
201-
CLSID_WICPngEncoder
202-
case .jpeg:
203-
CLSID_WICJpegEncoder
204-
case let .systemValue(clsid):
205-
(clsid as! CLSID.Wrapper).rawValue
206-
}
199+
kind.encoderCLSID
207200
}
208201

209202
/// Construct an instance of this type with the `CLSID` value of a Windows
@@ -277,4 +270,60 @@ extension AttachableImageFormat {
277270
self.init(encoderCLSID: encoderCLSID, encodingQuality: encodingQuality)
278271
}
279272
}
273+
274+
// MARK: - CustomStringConvertible, CustomDebugStringConvertible
275+
276+
extension AttachableImageFormat.Kind: CustomStringConvertible, CustomDebugStringConvertible {
277+
/// The `CLSID` value of the Windows Imaging Component (WIC) encoder class
278+
/// that corresponds to this image format.
279+
fileprivate var encoderCLSID: CLSID {
280+
switch self {
281+
case .png:
282+
CLSID_WICPngEncoder
283+
case .jpeg:
284+
CLSID_WICJpegEncoder
285+
case let .systemValue(clsid):
286+
(clsid as! CLSID.Wrapper).rawValue
287+
}
288+
}
289+
290+
/// Get a description of the given `CLSID` value.
291+
///
292+
/// - Parameters:
293+
/// - clsid: The `CLSID` value to describe.
294+
///
295+
/// - Returns: A description of `clsid`.
296+
private static func _description(of clsid: CLSID) -> String {
297+
var clsid = clsid
298+
var buffer: RPC_WSTR?
299+
if RPC_S_OK == UuidToStringW(&clsid, &buffer) {
300+
defer {
301+
RpcStringFreeW(&buffer)
302+
}
303+
if let result = String.decodeCString(buffer, as: UTF16.self)?.result {
304+
return result
305+
}
306+
}
307+
return String(describing: clsid)
308+
}
309+
310+
package var description: String {
311+
let clsid = encoderCLSID
312+
let encoderPathExtensionsByCLSID = (try? AttachableImageFormat._encoderPathExtensionsByCLSID.get()) ?? [:]
313+
if let ext = encoderPathExtensionsByCLSID[CLSID.Wrapper(clsid)]?.first {
314+
return "\(ext.uppercased()) format"
315+
}
316+
return Self._description(of: clsid)
317+
}
318+
319+
package var debugDescription: String {
320+
let clsid = encoderCLSID
321+
let clsidDescription = Self._description(of: clsid)
322+
let encoderPathExtensionsByCLSID = (try? AttachableImageFormat._encoderPathExtensionsByCLSID.get()) ?? [:]
323+
if let ext = encoderPathExtensionsByCLSID[CLSID.Wrapper(clsid)]?.first {
324+
return "\(ext.uppercased()) format (\(clsidDescription))"
325+
}
326+
return clsidDescription
327+
}
328+
}
280329
#endif

Sources/Overlays/_Testing_WinSDK/Support/Additions/GUIDAdditions.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ extension GUID {
2525
}
2626
}
2727

28-
extension GUID.Wrapper: Equatable, Hashable {
28+
// MARK: -
29+
30+
extension GUID.Wrapper: Equatable, Hashable, CustomStringConvertible {
2931
init(_ rawValue: GUID) {
3032
self.init(rawValue: rawValue)
3133
}
@@ -44,6 +46,10 @@ extension GUID.Wrapper: Equatable, Hashable {
4446
func hash(into hasher: inout Hasher) {
4547
hasher.combine(_uint128Value)
4648
}
49+
50+
var description: String {
51+
String(describing: rawValue)
52+
}
4753
#endif
4854
}
4955
#endif

Sources/Testing/Attachments/Images/AttachableImageFormat.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,28 @@ extension AttachableImageFormat.Kind: Equatable, Hashable {
118118
}
119119
}
120120

121+
// MARK: - CustomStringConvertible, CustomDebugStringConvertible
122+
123+
#if SWT_NO_IMAGE_ATTACHMENTS
124+
@_unavailableInEmbedded
125+
@available(*, unavailable, message: "Image attachments are not available on this platform.")
126+
#endif
127+
@available(_uttypesAPI, *)
128+
extension AttachableImageFormat: CustomStringConvertible, CustomDebugStringConvertible {
129+
public var description: String {
130+
let kindDescription = String(describing: kind)
131+
if encodingQuality < 1.0 {
132+
return "\(kindDescription) at \(Int(encodingQuality * 100.0))% quality"
133+
}
134+
return kindDescription
135+
}
136+
137+
public var debugDescription: String {
138+
let kindDescription = String(reflecting: kind)
139+
return "\(kindDescription) at quality \(encodingQuality)"
140+
}
141+
}
142+
121143
// MARK: -
122144

123145
#if SWT_NO_IMAGE_ATTACHMENTS

Tests/TestingTests/AttachmentTests.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,30 @@ extension AttachmentTests {
869869
#expect(format2.hashValue != format3.hashValue)
870870
#expect(format1.hashValue != format3.hashValue)
871871
}
872+
873+
@available(_uttypesAPI, *)
874+
@Test func imageFormatStringification() {
875+
let format: AttachableImageFormat = AttachableImageFormat.png
876+
#if canImport(CoreGraphics) && canImport(_Testing_CoreGraphics)
877+
#expect(String(describing: format) == UTType.png.localizedDescription)
878+
#expect(String(reflecting: format) == "\(UTType.png.localizedDescription) (\(UTType.png.identifier))")
879+
#elseif canImport(WinSDK) && canImport(_Testing_WinSDK)
880+
#expect(String(describing: format) == "PNG format")
881+
#expect(String(reflecting: format) == "PNG format (27949969-876a-41d7-9447-568f6a35a4dc) at quality 1.0")
882+
#endif
883+
}
884+
885+
@available(_uttypesAPI, *)
886+
@Test func imageFormatStringificationWithQuality() {
887+
let format: AttachableImageFormat = AttachableImageFormat.jpeg(withEncodingQuality: 0.5)
888+
#if canImport(CoreGraphics) && canImport(_Testing_CoreGraphics)
889+
#expect(String(describing: format) == "\(UTType.jpeg.localizedDescription) at 50% quality")
890+
#expect(String(reflecting: format) == "\(UTType.jpeg.localizedDescription) (\(UTType.jpeg.identifier)) at quality 0.5")
891+
#elseif canImport(WinSDK) && canImport(_Testing_WinSDK)
892+
#expect(String(describing: format) == "JPEG format at 50% quality")
893+
#expect(String(reflecting: format) == "JPEG format (1a34f5c1-4a5a-46dc-b644-1f4567e7a676) at quality 0.5")
894+
#endif
895+
}
872896
#endif
873897
}
874898
}

0 commit comments

Comments
 (0)