Currently OpenAPIRuntime has a lot of dependencies on methods, types etc from Foundation. So, currently its not possible to just replace all import Foundation with import FoundationEssentials as recently suggested by the ESG.
I have made a POC of what it would take to remove all dependencies from Foundation, to allow us to use openapi-generator on platforms where including the ICU is not acceptable, due to binary sizes.
The changes can be seen in:
apple/swift-openapi-runtime@main...madsodgaard:swift-openapi-runtime:foundation-essentials
Note: The above changes are just a POC and are not my final suggestion for a solution.
I am starting this issue to discuss whether this is feasible and would be something the swift-openapi-generator maintainers would be open to going forward with.
Below is a list of the issues that we need to address if this were to work out:
NSLock
Currently NSLock is used a few different places. But we should be able to just replace this with the Lock from swift-nio.
String(format:)
This function is used in Acceptable.swift to convert Double to String with 3 decimals. I think we should be able to write a simple Swift impl of this.
trimmingCharacters(in:)
This is only used to remove whitespaces and quotes. This is relatively simple to write a pure Swift impl for.
NSNull, NSNumber etc...
The OpenAPIValue supports CoreFoundation types like NSNull and NSNumber. I propose that we add a default trait FullFoundationTrait, that hides the support for these behind them.
ISO8601DateFormatter
My proposal for solving this is to hide this type behind FullFoundationSupport. Then we make a new implementation of DateTranscoder which uses the .formatted() APIs from FoundationEssentials.
Unfortunately, these APIs are only available on:
@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
So, that means that if people disable the FullFoundationSupport and run on Apple Platforms before the above, they loose access to the default iso date formatter and corresponding initializers on Client. Imo, this is fine, since the FullFoundationSupport is probably only for non-apple platforms. (but this could be source-breaking)
localizedDescription
This is used quite a few places when logging the errors. I am not sure if this is a hard requirement or if we could use "\(error)" instead?
localizedCompare and localizedCaseInsensitiveCompare
This function has been replaced by a pure < Swift comparison.
Percent-based encoding/decoding
The URISerializer and URIParser previously used addingPercentEncoding and replacingOccurrences. These have been replaced by pure Swift implementation inspired by implementations in swift-foundation.
Checklist
Currently
OpenAPIRuntimehas a lot of dependencies on methods, types etc fromFoundation. So, currently its not possible to just replace allimport Foundationwithimport FoundationEssentialsas recently suggested by the ESG.I have made a POC of what it would take to remove all dependencies from
Foundation, to allow us to useopenapi-generatoron platforms where including the ICU is not acceptable, due to binary sizes.The changes can be seen in:
apple/swift-openapi-runtime@main...madsodgaard:swift-openapi-runtime:foundation-essentials
Note: The above changes are just a POC and are not my final suggestion for a solution.
I am starting this issue to discuss whether this is feasible and would be something the
swift-openapi-generatormaintainers would be open to going forward with.Below is a list of the issues that we need to address if this were to work out:
NSLockCurrently
NSLockis used a few different places. But we should be able to just replace this with the Lock fromswift-nio.String(format:)This function is used in Acceptable.swift to convert
DoubletoStringwith 3 decimals. I think we should be able to write a simple Swift impl of this.trimmingCharacters(in:)This is only used to remove whitespaces and quotes. This is relatively simple to write a pure Swift impl for.
NSNull,NSNumberetc...The
OpenAPIValuesupports CoreFoundation types likeNSNullandNSNumber. I propose that we add a default traitFullFoundationTrait, that hides the support for these behind them.ISO8601DateFormatterMy proposal for solving this is to hide this type behind
FullFoundationSupport. Then we make a new implementation ofDateTranscoderwhich uses the.formatted()APIs fromFoundationEssentials.Unfortunately, these APIs are only available on:
So, that means that if people disable the
FullFoundationSupportand run on Apple Platforms before the above, they loose access to the defaultisodate formatter and corresponding initializers onClient. Imo, this is fine, since theFullFoundationSupportis probably only for non-apple platforms. (but this could be source-breaking)localizedDescriptionThis is used quite a few places when logging the errors. I am not sure if this is a hard requirement or if we could use
"\(error)"instead?localizedCompareandlocalizedCaseInsensitiveCompareThis function has been replaced by a pure
<Swift comparison.Percent-based encoding/decoding
The
URISerializerandURIParserpreviously usedaddingPercentEncodingandreplacingOccurrences. These have been replaced by pure Swift implementation inspired by implementations inswift-foundation.Checklist
NSLock(Use lock from NIO instead of NSLock swift-openapi-runtime#172)ISO8601DateFormatter(IntroduceFullFoundationtrait swift-openapi-runtime#177)localizedDescription(RemovelocalizedDescriptionswift-openapi-runtime#173)localizedCompareandlocalizedCaseInsensitiveCompare(Remove localized compares swift-openapi-runtime#174)replacingOccurrences(of:with:)and percent encoding swift-openapi-runtime#176)CoreFoundationtypes:NSNumber,NSNulletc... (IntroduceFullFoundationtrait swift-openapi-runtime#177)String(format:)(ReplaceString(format:)forDoubleto String conversions swift-openapi-runtime#178)trimmingCharacters(RemovetrimmingCharacters(in:)swift-openapi-runtime#175)Foundationlinkage regression swift-openapi-runtime#179)