Skip to content

Commit 0c1383b

Browse files
committed
[ST-NNNN] Adjustments to image attachments in Swift Testing
1 parent 669c148 commit 0c1383b

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# Adjustments to image attachments in Swift Testing
2+
3+
* Proposal: [ST-NNNN](NNNN-image-attachment-adjustments.md)
4+
* Authors: [Jonathan Grynspan](https://github.com/grynspan)
5+
* Review Manager: TBD
6+
* Status: **Awaiting review**
7+
* Implementation: [swiftlang/swift-testing#1359](https://github.com/swiftlang/swift-testing/pull/1359)
8+
* Review: ([pitch](https://forums.swift.org/...))
9+
10+
## Introduction
11+
12+
This proposal includes a small number of adjustments to the API surface of Swift
13+
Testing's image attachments feature introduced in [ST-0014](0014-image-attachments-in-swift-testing-apple-platforms.md)
14+
and [ST-0015](0015-image-attachments-in-swift-testing-windows.md).
15+
16+
## Motivation
17+
18+
These changes will help to align the platform-specific interfaces of the feature
19+
more closely.
20+
21+
## Proposed solution
22+
23+
The `AttachableAsCGImage` and `AttachableAsIWICBitmapSource` protocols are
24+
combined into a single protocol, `AttachableAsImage` with adjusted protocol
25+
requirements; a change is made to `AttachableImageFormat` to more closely
26+
align its interface between Darwin and Windows; and an additional property is
27+
added to `Attachment` to query its image format.
28+
29+
## Detailed design
30+
31+
The following changes are proposed:
32+
33+
### Combining AttachableAsCGImage and AttachableAsIWICBitmapSource
34+
35+
The `AttachableAsCGImage` and `AttachableAsIWICBitmapSource` protocols are
36+
combined into a single protocol, `AttachableAsImage`.
37+
38+
These platform-specific requirements are removed:
39+
40+
```diff
41+
- var attachableCGImage: CGImage { get throws }
42+
- func copyAttachableIWICBitmapSource() throws -> UnsafeMutablePointer<IWICBitmapSource>
43+
```
44+
45+
They are replaced with a new requirement that encapsulates the image encoding
46+
operation. This requirement is implemented by the CoreGraphics and WinSDK
47+
overlays and is made publicly available for test authors who wish to declare
48+
additional conformances to this protocol for types that are not based on
49+
`CGImage` or `IWICBitmapSource`:
50+
51+
```swift
52+
public protocol AttachableAsImage {
53+
// ...
54+
55+
/// Encode a representation of this image in a given image format.
56+
///
57+
/// - Parameters:
58+
/// - imageFormat: The image format to use when encoding this image.
59+
/// - body: A function to call. A temporary buffer containing a data
60+
/// representation of this instance is passed to it.
61+
///
62+
/// - Returns: Whatever is returned by `body`.
63+
///
64+
/// - Throws: Whatever is thrown by `body`, or any error that prevented the
65+
/// creation of the buffer.
66+
///
67+
/// The testing library uses this function when saving an image as an
68+
/// attachment. The implementation should use `imageFormat` to determine what
69+
/// encoder to use.
70+
borrowing func withUnsafeBytes<R>(as imageFormat: AttachableImageFormat, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R
71+
}
72+
```
73+
74+
If a developer has an image type that should conform to `AttachableAsImage` and
75+
wraps an instance of `CGImage` or `IWICBitmapSource`, it is straightforward for
76+
them to delegate to that object. For example:
77+
78+
```swift
79+
import Testing
80+
import CoreGraphics
81+
82+
struct MyImage {
83+
var cgImage: CGImage
84+
// ...
85+
}
86+
87+
extension MyImage: AttachableAsImage {
88+
func withUnsafeBytes<R>(as imageFormat: AttachableImageFormat, _ body: (UnsafeRawBufferPointer) throws -> R) throws -> R {
89+
try cgImage.withUnsafeBytes(as: imageFormat, body)
90+
}
91+
}
92+
```
93+
94+
### Adjusting AttachableImageFormat
95+
96+
The following Apple-specific `AttachableImageFormat` initializer is renamed so
97+
that its first argument has an explicit label:
98+
99+
```diff
100+
public struct AttachableImageFormat {
101+
// ...
102+
- public init(_ contentType: UTType, encodingQuality: Float = 1.0)
103+
+ public init(contentType: UTType, encodingQuality: Float = 1.0)
104+
}
105+
```
106+
107+
This change makes the type's interface more consistent between Darwin and
108+
Windows (where it has an `init(encoderCLSID:encodingQuality:)` initializer.)
109+
110+
### Adding an imageFormat property to Attachment
111+
112+
The following property is added to `Attachment` when the attachable value is an
113+
image:
114+
115+
```swift
116+
extension Attachment where AttachableValue: AttachableWrapper,
117+
AttachableValue.Wrapped: AttachableAsImage {
118+
/// The image format to use when encoding the represented image.
119+
public var imageFormat: AttachableImageFormat? { get }
120+
}
121+
```
122+
123+
## Source compatibility
124+
125+
These changes are breaking for anyone who has created a type that conforms to
126+
either `AttachableAsCGImage` or `AttachableAsIWICBitmapSource`, or anyone who
127+
has adopted `AttachableImageFormat.init(_:encodingQuality:)`.
128+
129+
This feature is new in Swift 6.3 and has not shipped to developers outside of
130+
nightly toolchain builds. As such, we feel confident that any real-world impact
131+
to developers will be both minimal and manageable.
132+
133+
## Integration with supporting tools
134+
135+
No changes.
136+
137+
## Future directions
138+
139+
N/A
140+
141+
## Alternatives considered
142+
143+
- Leaving the two protocols separate. Combining them allows us to lower more
144+
code into the main Swift Testing library and improves our ability to generate
145+
DocC documentation, while also simplifying the story for developers who want
146+
to use this feature across platforms.
147+
148+
## Acknowledgments
149+
150+
Thanks to my colleagues for their feedback on the image attachments feature and
151+
to the Swift community for putting up with the churn!

0 commit comments

Comments
 (0)