Repository: vapor/vapor
File: Sources/Vapor/HTTP/HTTPHeaderCacheControl.swift (Swift)

Code before:
    /// Indicates to not retrieve new data. This being the case, the server wishes the client to obtain a response only once and then cache. From this moment the
    /// client should keep releasing a cached copy and avoid contacting the origin-server to see if a newer copy exists.
    public static let onlyIfCached = Self(rawValue: 1 << 7)

    /// Indicates the client will accept a stale response.  If the `maxStale` property is set, indicates the upper limit of staleness the client will accept.
    public static let maxStale = Self(rawValue: 1 << 8)

    /// Indicates that the response body **will not change** over time.
    ///
    /// The resource, if *unexpired*, is unchanged on the server and therefore the client should
    /// not send a conditional revalidation for it (e.g. `If-None-Match` or `If-Modified-Since`) to check for updates, even when the user explicitly refreshes
    /// the page. Clients that aren't aware of this extension must ignore them as per the HTTP specification. In Firefox, immutable is only honored on https:// transactions.
    /// For more information, see also this [blog post](https://bitsup.blogspot.de/2016/05/cache-control-immutable.html).
    public static let immutable = Self(rawValue: 1 << 9)

    // MARK: - Properties
    public var rawValue = 0

    /// The maximum amount of time a resource is considered fresh. Unlike the`Expires` header, this directive is relative to the time of the request.
    public var maxAge: Int?

    /// Overrides max-age or the Expires header, but only for shared caches (e.g., proxies). Ignored by private caches.
    public var sMaxAge: Int?

    /// Indicates the client will accept a stale response. An optional value in seconds indicates the upper limit of staleness the client will accept.
    public var maxStale: Int?

    /// Indicates the client wants a response that will still be fresh for at least the specified number of seconds.
    public var minFresh: Int?

    /// Indicates the client will accept a stale response, while asynchronously checking in the background for a fresh one. The value indicates how long the client will accept a stale response.
    public var staleWhileRevalidate: Int?

    /// Indicates the client will accept a stale response if the check for a fresh one fails. The value indicates how many *seconds* long the client will accept the stale response after the initial expiration.
    public var staleIfError: Int?

    /// Initializes the class
    /// - Parameter rawValue: The initial value.
    public init(rawValue: Int) {
        self.rawValue = rawValue
    }

    private static let exactMatch: [String: Self] = [
        "must-revalidate": Self.mustRevalidate,
        "no-cache": Self.noCache,
        "no-store": Self.noStore,
        "no-transform": Self.noTransform,
        "public": Self.isPublic,
        "private": Self.isPrivate,
        "proxy-revalidate": Self.proxyRevalidate,
        "only-if-cached": Self.onlyIfCached,

Review comment (performance):
Maybe instead of using an option set here and then having these separate variables, cache control could be an array of an enum representing these different values:

```swift
enum CacheControl.Value {
    case maxAge(seconds: Int)
    case maxStale(seconds: Int?)
    case noCache
    ...
}
```

Code after:
        /// The response is for a single user and **must not** be stored by a shared cache. A private cache (like the user's browser cache) may store the response.
        public var isPrivate: Bool

        /// Like `must-revalidate`, but only for shared caches (e.g., proxies). Ignored by private caches.
        public var proxyRevalidate: Bool

        /// Indicates to not retrieve new data. This being the case, the server wishes the client to obtain a response only once and then cache. From this moment the
        /// client should keep releasing a cached copy and avoid contacting the origin-server to see if a newer copy exists.
        public var onlyIfCached: Bool

        /// Indicates that the response body **will not change** over time.
        ///
        /// The resource, if *unexpired*, is unchanged on the server and therefore the client should
        /// not send a conditional revalidation for it (e.g. `If-None-Match` or `If-Modified-Since`) to check for updates, even when the user explicitly refreshes
        /// the page. Clients that aren't aware of this extension must ignore them as per the HTTP specification. In Firefox, immutable is only honored on https:// transactions.
        /// For more information, see also this [blog post](https://bitsup.blogspot.de/2016/05/cache-control-immutable.html).
        public var immutable: Bool

        /// The maximum amount of time a resource is considered fresh. Unlike the`Expires` header, this directive is relative to the time of the request.
        public var maxAge: Int?

        /// Overrides max-age or the Expires header, but only for shared caches (e.g., proxies). Ignored by private caches.
        public var sMaxAge: Int?

        /// Indicates the client will accept a stale response. An optional value in seconds indicates the upper limit of staleness the client will accept.
        public var maxStale: MaxStale?

        /// Indicates the client wants a response that will still be fresh for at least the specified number of seconds.
        public var minFresh: Int?

        /// Indicates the client will accept a stale response, while asynchronously checking in the background for a fresh one. The value indicates how long the client will accept a stale response.
        public var staleWhileRevalidate: Int?

        /// Indicates the client will accept a stale response if the check for a fresh one fails. The value indicates how many *seconds* long the client will accept the stale response after the initial expiration.
        public var staleIfError: Int?

        public init() {
            self.mustRevalidate = false
            self.noCache = false
            self.noStore = false
            self.noTransform = false
            self.isPublic = false
            self.isPrivate = false
            self.proxyRevalidate = false
            self.onlyIfCached = false
            self.immutable = false
        }

        private static let exactMatch: [String: WritableKeyPath<Self, Bool>] = [
            "must-revalidate": \.mustRevalidate,
            "no-cache": \.noCache,