File: VideoReference.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (156 lines) | stat: -rw-r--r-- 6,331 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
 Licensed under Apache License v2.0 with Runtime Library Exception

 See https://swift.org/LICENSE.txt for license information
 See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Foundation

/// A reference to a video.
public struct VideoReference: MediaReference, URLReference, Equatable {
    /// The type of this video reference.
    ///
    /// This value is always `.video`.
    public var type: RenderReferenceType = .video
    
    /// The identifier of this reference.
    public var identifier: RenderReferenceIdentifier
    
    /// Alternate text for the video.
    ///
    /// This text helps screen readers describe the video.
    public var altText: String?
    
    /// The data associated with this asset, including its variants.
    public var asset: DataAsset
    
    /// The reference to a poster image for this video.
    public var poster: RenderReferenceIdentifier?
    
    /// Creates a new video reference.
    ///
    /// - Parameters:
    ///   - identifier: The identifier for this video reference.
    ///   - altText: Alternate text for the video.
    ///   - asset: The data associated with this asset, including its variants.
    ///   - poster: The reference to a poster image for this video.
    public init(identifier: RenderReferenceIdentifier, altText: String? = nil, videoAsset asset: DataAsset, poster: RenderReferenceIdentifier?) {
        self.identifier = identifier
        self.asset = asset
        self.altText = altText
        self.poster = poster
    }
    
    enum CodingKeys: String, CodingKey {
        case type
        case identifier
        case alt
        case variants
        case poster
    }
    
    public init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        type = try values.decode(RenderReferenceType.self, forKey: .type)
        identifier = try values.decode(RenderReferenceIdentifier.self, forKey: .identifier)
        altText = try values.decodeIfPresent(String.self, forKey: .alt)
        
        // rebuild the data asset
        asset = DataAsset()
        let variants = try values.decode([VariantProxy].self, forKey: .variants)
        variants.forEach { (variant) in
            asset.register(variant.url, with: DataTraitCollection(from: variant.traits))
        }
        
        poster = try values.decodeIfPresent(RenderReferenceIdentifier.self, forKey: .poster)
    }
    
    /// The relative URL to the folder that contains all images in the built documentation output.
    public static let baseURL = URL(string: "/videos/")!
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(type.rawValue, forKey: .type)
        try container.encode(identifier, forKey: .identifier)
        try container.encode(altText, forKey: .alt)
        
        // convert the data asset to a serializable object
        var result = [VariantProxy]()
        asset.variants.sorted(by: \.value.path).forEach { (key, value) in
            let url = value.isAbsoluteWebURL ? value : destinationURL(for: value.lastPathComponent, prefixComponent: encoder.assetPrefixComponent)
            result.append(VariantProxy(url: url, traits: key))
        }
        try container.encode(result, forKey: .variants)
        
        try container.encode(poster, forKey: .poster)
    }
    
    /// A codable proxy value that the video reference uses to serialize information about its asset variants.
    public struct VariantProxy: Codable, Equatable {
        /// The URL to the file for this video variant.
        public var url: URL
        /// The traits of this video reference.
        public var traits: [String]
        
        /// Creates a new proxy value with the given information about a video variant.
        ///
        /// - Parameters:
        ///   - url: The URL to the file for this video variant.
        ///   - traits: The traits of this video reference.
        init(url: URL, traits: DataTraitCollection) {
            self.url = url
            self.traits = traits.toArray()
        }
        
        enum CodingKeys: String, CodingKey {
            case size
            case url
            case traits
        }
        
        public init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            url = try values.decode(URL.self, forKey: .url)
            traits = try values.decode([String].self, forKey: .traits)
        }
        
        public func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(url, forKey: .url)
            try container.encode(traits, forKey: .traits)
        }
    }
}

// Diffable conformance
extension VideoReference: RenderJSONDiffable {
    /// Returns the difference between this VideoReference and the given one.
    func difference(from other: VideoReference, at path: CodablePath) -> JSONPatchDifferences {
        var diffBuilder = DifferenceBuilder(current: self, other: other, basePath: path)

        diffBuilder.addDifferences(atKeyPath: \.type, forKey: CodingKeys.type)
        diffBuilder.addDifferences(atKeyPath: \.identifier, forKey: CodingKeys.identifier)
        diffBuilder.addDifferences(atKeyPath: \.altText, forKey: CodingKeys.alt)
        diffBuilder.addDifferences(atKeyPath: \.asset, forKey: CodingKeys.variants)
        diffBuilder.addDifferences(atKeyPath: \.poster, forKey: CodingKeys.poster)

        return diffBuilder.differences
    }
}

// Diffable conformance
extension VideoReference.VariantProxy: RenderJSONDiffable {
    /// Returns the difference between this VariantProxy and the given one.
    func difference(from other: VideoReference.VariantProxy, at path: CodablePath) -> JSONPatchDifferences {
        var diffBuilder = DifferenceBuilder(current: self, other: other, basePath: path)

        diffBuilder.addDifferences(atKeyPath: \.url, forKey: CodingKeys.url)
        diffBuilder.addDifferences(atKeyPath: \.traits, forKey: CodingKeys.traits)

        return diffBuilder.differences
    }
}