feat(protocol): carry stream policy and gateway telemetry
This commit is contained in:
+173
-5
@@ -1,7 +1,7 @@
|
||||
// Code generated by tools/generate.py; DO NOT EDIT.
|
||||
import Foundation
|
||||
public typealias JSONObject = [String: String]
|
||||
public let schemaSHA256 = "e98c75ef81bbeac6be2b8f11202c1ffecec0aa515b48576a26756290e99d5dd8"
|
||||
public let schemaSHA256 = "fe4d6be69665f09f04e2cd89273ebc5d2dddf4cde98b94a9d8c4f726504ffe1b"
|
||||
public let currentWireVersion = "1"
|
||||
public let nMinus1WireVersion = "0"
|
||||
public let nMinus2WireVersion = "-1"
|
||||
@@ -1003,6 +1003,7 @@ public struct GatewayHeartbeat: Codable, Equatable {
|
||||
public let activeConnections: Int64
|
||||
public let egressKbps: Int64
|
||||
public let state: String
|
||||
public let telemetry: GatewayTelemetry
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case version = "version"
|
||||
case gatewayId = "gateway_id"
|
||||
@@ -1011,9 +1012,10 @@ public struct GatewayHeartbeat: Codable, Equatable {
|
||||
case activeConnections = "active_connections"
|
||||
case egressKbps = "egress_kbps"
|
||||
case state = "state"
|
||||
case telemetry = "telemetry"
|
||||
}
|
||||
|
||||
public init(version: String, gatewayId: String, sequence: Int64, observedAt: String, activeConnections: Int64, egressKbps: Int64, state: String) throws {
|
||||
public init(version: String, gatewayId: String, sequence: Int64, observedAt: String, activeConnections: Int64, egressKbps: Int64, state: String, telemetry: GatewayTelemetry) throws {
|
||||
self.version = version
|
||||
self.gatewayId = gatewayId
|
||||
self.sequence = sequence
|
||||
@@ -1021,6 +1023,7 @@ public struct GatewayHeartbeat: Codable, Equatable {
|
||||
self.activeConnections = activeConnections
|
||||
self.egressKbps = egressKbps
|
||||
self.state = state
|
||||
self.telemetry = telemetry
|
||||
try validate()
|
||||
}
|
||||
|
||||
@@ -1028,7 +1031,7 @@ public struct GatewayHeartbeat: Codable, Equatable {
|
||||
let all = try decoder.container(keyedBy: AnyCodingKey.self)
|
||||
for key in all.allKeys where CodingKeys(stringValue: key.stringValue) == nil { throw ContractValidationError(field: key.stringValue, code: "unknown_field") }
|
||||
let c = try decoder.container(keyedBy: CodingKeys.self)
|
||||
try self.init(version: try c.decode(String.self, forKey: .version), gatewayId: try c.decode(String.self, forKey: .gatewayId), sequence: try c.decode(Int64.self, forKey: .sequence), observedAt: try c.decode(String.self, forKey: .observedAt), activeConnections: try c.decode(Int64.self, forKey: .activeConnections), egressKbps: try c.decode(Int64.self, forKey: .egressKbps), state: try c.decode(String.self, forKey: .state))
|
||||
try self.init(version: try c.decode(String.self, forKey: .version), gatewayId: try c.decode(String.self, forKey: .gatewayId), sequence: try c.decode(Int64.self, forKey: .sequence), observedAt: try c.decode(String.self, forKey: .observedAt), activeConnections: try c.decode(Int64.self, forKey: .activeConnections), egressKbps: try c.decode(Int64.self, forKey: .egressKbps), state: try c.decode(String.self, forKey: .state), telemetry: try c.decode(GatewayTelemetry.self, forKey: .telemetry))
|
||||
}
|
||||
|
||||
public func validate() throws {
|
||||
@@ -1044,6 +1047,7 @@ public struct GatewayHeartbeat: Codable, Equatable {
|
||||
if self.egressKbps < 0 { throw ContractValidationError(field: "egress_kbps", code: "minimum") }
|
||||
if self.egressKbps > 1000000000 { throw ContractValidationError(field: "egress_kbps", code: "maximum") }
|
||||
if !["ready", "draining", "offline"].contains(self.state) { throw ContractValidationError(field: "state", code: "invalid_value") }
|
||||
try self.telemetry.validate()
|
||||
}
|
||||
|
||||
public static func decodeJSON(_ data: Data) throws -> Self { try JSONDecoder().decode(Self.self, from: data) }
|
||||
@@ -1141,6 +1145,117 @@ public struct GatewayRegistration: Codable, Equatable {
|
||||
public func encodeJSON() throws -> Data { try validate(); return try JSONEncoder().encode(self) }
|
||||
}
|
||||
|
||||
public struct GatewayTelemetry: Codable, Equatable {
|
||||
public let admittedSessions: Int64
|
||||
public let admissionRejects: Int64
|
||||
public let reconnects: Int64
|
||||
public let drainTransitions: Int64
|
||||
public let mediaDrops: Int64
|
||||
public let mediaPackets: Int64
|
||||
public let mediaBytes: Int64
|
||||
public let queueDelayMicros: Int64
|
||||
public let processingDelayMicros: Int64
|
||||
public let processingSamples: Int64
|
||||
public let pacingDelayMicros: Int64
|
||||
public let providerErrors: Int64
|
||||
public let inputRejected: Int64
|
||||
public let controlRttMicros: Int64
|
||||
public let controlJitterMicros: Int64
|
||||
public let controlLossPpm: Int64
|
||||
public let pendingReliable: Int64
|
||||
public let providerState: String
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case admittedSessions = "admitted_sessions"
|
||||
case admissionRejects = "admission_rejects"
|
||||
case reconnects = "reconnects"
|
||||
case drainTransitions = "drain_transitions"
|
||||
case mediaDrops = "media_drops"
|
||||
case mediaPackets = "media_packets"
|
||||
case mediaBytes = "media_bytes"
|
||||
case queueDelayMicros = "queue_delay_micros"
|
||||
case processingDelayMicros = "processing_delay_micros"
|
||||
case processingSamples = "processing_samples"
|
||||
case pacingDelayMicros = "pacing_delay_micros"
|
||||
case providerErrors = "provider_errors"
|
||||
case inputRejected = "input_rejected"
|
||||
case controlRttMicros = "control_rtt_micros"
|
||||
case controlJitterMicros = "control_jitter_micros"
|
||||
case controlLossPpm = "control_loss_ppm"
|
||||
case pendingReliable = "pending_reliable"
|
||||
case providerState = "provider_state"
|
||||
}
|
||||
|
||||
public init(admittedSessions: Int64, admissionRejects: Int64, reconnects: Int64, drainTransitions: Int64, mediaDrops: Int64, mediaPackets: Int64, mediaBytes: Int64, queueDelayMicros: Int64, processingDelayMicros: Int64, processingSamples: Int64, pacingDelayMicros: Int64, providerErrors: Int64, inputRejected: Int64, controlRttMicros: Int64, controlJitterMicros: Int64, controlLossPpm: Int64, pendingReliable: Int64, providerState: String) throws {
|
||||
self.admittedSessions = admittedSessions
|
||||
self.admissionRejects = admissionRejects
|
||||
self.reconnects = reconnects
|
||||
self.drainTransitions = drainTransitions
|
||||
self.mediaDrops = mediaDrops
|
||||
self.mediaPackets = mediaPackets
|
||||
self.mediaBytes = mediaBytes
|
||||
self.queueDelayMicros = queueDelayMicros
|
||||
self.processingDelayMicros = processingDelayMicros
|
||||
self.processingSamples = processingSamples
|
||||
self.pacingDelayMicros = pacingDelayMicros
|
||||
self.providerErrors = providerErrors
|
||||
self.inputRejected = inputRejected
|
||||
self.controlRttMicros = controlRttMicros
|
||||
self.controlJitterMicros = controlJitterMicros
|
||||
self.controlLossPpm = controlLossPpm
|
||||
self.pendingReliable = pendingReliable
|
||||
self.providerState = providerState
|
||||
try validate()
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let all = try decoder.container(keyedBy: AnyCodingKey.self)
|
||||
for key in all.allKeys where CodingKeys(stringValue: key.stringValue) == nil { throw ContractValidationError(field: key.stringValue, code: "unknown_field") }
|
||||
let c = try decoder.container(keyedBy: CodingKeys.self)
|
||||
try self.init(admittedSessions: try c.decode(Int64.self, forKey: .admittedSessions), admissionRejects: try c.decode(Int64.self, forKey: .admissionRejects), reconnects: try c.decode(Int64.self, forKey: .reconnects), drainTransitions: try c.decode(Int64.self, forKey: .drainTransitions), mediaDrops: try c.decode(Int64.self, forKey: .mediaDrops), mediaPackets: try c.decode(Int64.self, forKey: .mediaPackets), mediaBytes: try c.decode(Int64.self, forKey: .mediaBytes), queueDelayMicros: try c.decode(Int64.self, forKey: .queueDelayMicros), processingDelayMicros: try c.decode(Int64.self, forKey: .processingDelayMicros), processingSamples: try c.decode(Int64.self, forKey: .processingSamples), pacingDelayMicros: try c.decode(Int64.self, forKey: .pacingDelayMicros), providerErrors: try c.decode(Int64.self, forKey: .providerErrors), inputRejected: try c.decode(Int64.self, forKey: .inputRejected), controlRttMicros: try c.decode(Int64.self, forKey: .controlRttMicros), controlJitterMicros: try c.decode(Int64.self, forKey: .controlJitterMicros), controlLossPpm: try c.decode(Int64.self, forKey: .controlLossPpm), pendingReliable: try c.decode(Int64.self, forKey: .pendingReliable), providerState: try c.decode(String.self, forKey: .providerState))
|
||||
}
|
||||
|
||||
public func validate() throws {
|
||||
if self.admittedSessions < 0 { throw ContractValidationError(field: "admitted_sessions", code: "minimum") }
|
||||
if self.admittedSessions > 9223372036854775807 { throw ContractValidationError(field: "admitted_sessions", code: "maximum") }
|
||||
if self.admissionRejects < 0 { throw ContractValidationError(field: "admission_rejects", code: "minimum") }
|
||||
if self.admissionRejects > 9223372036854775807 { throw ContractValidationError(field: "admission_rejects", code: "maximum") }
|
||||
if self.reconnects < 0 { throw ContractValidationError(field: "reconnects", code: "minimum") }
|
||||
if self.reconnects > 9223372036854775807 { throw ContractValidationError(field: "reconnects", code: "maximum") }
|
||||
if self.drainTransitions < 0 { throw ContractValidationError(field: "drain_transitions", code: "minimum") }
|
||||
if self.drainTransitions > 9223372036854775807 { throw ContractValidationError(field: "drain_transitions", code: "maximum") }
|
||||
if self.mediaDrops < 0 { throw ContractValidationError(field: "media_drops", code: "minimum") }
|
||||
if self.mediaDrops > 9223372036854775807 { throw ContractValidationError(field: "media_drops", code: "maximum") }
|
||||
if self.mediaPackets < 0 { throw ContractValidationError(field: "media_packets", code: "minimum") }
|
||||
if self.mediaPackets > 9223372036854775807 { throw ContractValidationError(field: "media_packets", code: "maximum") }
|
||||
if self.mediaBytes < 0 { throw ContractValidationError(field: "media_bytes", code: "minimum") }
|
||||
if self.mediaBytes > 9223372036854775807 { throw ContractValidationError(field: "media_bytes", code: "maximum") }
|
||||
if self.queueDelayMicros < 0 { throw ContractValidationError(field: "queue_delay_micros", code: "minimum") }
|
||||
if self.queueDelayMicros > 9223372036854775807 { throw ContractValidationError(field: "queue_delay_micros", code: "maximum") }
|
||||
if self.processingDelayMicros < 0 { throw ContractValidationError(field: "processing_delay_micros", code: "minimum") }
|
||||
if self.processingDelayMicros > 9223372036854775807 { throw ContractValidationError(field: "processing_delay_micros", code: "maximum") }
|
||||
if self.processingSamples < 0 { throw ContractValidationError(field: "processing_samples", code: "minimum") }
|
||||
if self.processingSamples > 9223372036854775807 { throw ContractValidationError(field: "processing_samples", code: "maximum") }
|
||||
if self.pacingDelayMicros < 0 { throw ContractValidationError(field: "pacing_delay_micros", code: "minimum") }
|
||||
if self.pacingDelayMicros > 9223372036854775807 { throw ContractValidationError(field: "pacing_delay_micros", code: "maximum") }
|
||||
if self.providerErrors < 0 { throw ContractValidationError(field: "provider_errors", code: "minimum") }
|
||||
if self.providerErrors > 9223372036854775807 { throw ContractValidationError(field: "provider_errors", code: "maximum") }
|
||||
if self.inputRejected < 0 { throw ContractValidationError(field: "input_rejected", code: "minimum") }
|
||||
if self.inputRejected > 9223372036854775807 { throw ContractValidationError(field: "input_rejected", code: "maximum") }
|
||||
if self.controlRttMicros < 0 { throw ContractValidationError(field: "control_rtt_micros", code: "minimum") }
|
||||
if self.controlRttMicros > 9223372036854775807 { throw ContractValidationError(field: "control_rtt_micros", code: "maximum") }
|
||||
if self.controlJitterMicros < 0 { throw ContractValidationError(field: "control_jitter_micros", code: "minimum") }
|
||||
if self.controlJitterMicros > 9223372036854775807 { throw ContractValidationError(field: "control_jitter_micros", code: "maximum") }
|
||||
if self.controlLossPpm < 0 { throw ContractValidationError(field: "control_loss_ppm", code: "minimum") }
|
||||
if self.controlLossPpm > 1000000 { throw ContractValidationError(field: "control_loss_ppm", code: "maximum") }
|
||||
if self.pendingReliable < 0 { throw ContractValidationError(field: "pending_reliable", code: "minimum") }
|
||||
if self.pendingReliable > 9223372036854775807 { throw ContractValidationError(field: "pending_reliable", code: "maximum") }
|
||||
if !["unknown", "starting", "ready", "disconnected", "terminating", "terminated", "cleanup_pending", "failed"].contains(self.providerState) { throw ContractValidationError(field: "provider_state", code: "invalid_value") }
|
||||
}
|
||||
|
||||
public static func decodeJSON(_ data: Data) throws -> Self { try JSONDecoder().decode(Self.self, from: data) }
|
||||
public func encodeJSON() throws -> Data { try validate(); return try JSONEncoder().encode(self) }
|
||||
}
|
||||
|
||||
public struct GrantReference: Codable, Equatable {
|
||||
public let opaqueValue: String
|
||||
public let expiresAt: String
|
||||
@@ -1458,6 +1573,7 @@ public struct ProviderSessionWork: Codable, Equatable {
|
||||
public let providerProfile: String
|
||||
public let providerIdentity: String
|
||||
public let policyVersionId: String
|
||||
public let streamPolicy: ProviderStreamPolicy
|
||||
public let applicationId: String
|
||||
public let clientId: String
|
||||
public let managementHost: String
|
||||
@@ -1478,6 +1594,7 @@ public struct ProviderSessionWork: Codable, Equatable {
|
||||
case providerProfile = "provider_profile"
|
||||
case providerIdentity = "provider_identity"
|
||||
case policyVersionId = "policy_version_id"
|
||||
case streamPolicy = "stream_policy"
|
||||
case applicationId = "application_id"
|
||||
case clientId = "client_id"
|
||||
case managementHost = "management_host"
|
||||
@@ -1491,7 +1608,7 @@ public struct ProviderSessionWork: Codable, Equatable {
|
||||
case providerApplicationTerminationAllowed = "provider_application_termination_allowed"
|
||||
}
|
||||
|
||||
public init(version: String, sessionId: String, gatewayId: String, reconnectSequence: Int64, expiresAt: String, providerProfile: String, providerIdentity: String, policyVersionId: String, applicationId: String, clientId: String, managementHost: String, managementPort: Int64, streamHost: String, streamPort: Int64, clientCertificatePem: String, clientPrivateKeyPem: String, serverCertificatePem: String, clipboardPolicy: ClipboardPolicy, providerApplicationTerminationAllowed: Bool) throws {
|
||||
public init(version: String, sessionId: String, gatewayId: String, reconnectSequence: Int64, expiresAt: String, providerProfile: String, providerIdentity: String, policyVersionId: String, streamPolicy: ProviderStreamPolicy, applicationId: String, clientId: String, managementHost: String, managementPort: Int64, streamHost: String, streamPort: Int64, clientCertificatePem: String, clientPrivateKeyPem: String, serverCertificatePem: String, clipboardPolicy: ClipboardPolicy, providerApplicationTerminationAllowed: Bool) throws {
|
||||
self.version = version
|
||||
self.sessionId = sessionId
|
||||
self.gatewayId = gatewayId
|
||||
@@ -1500,6 +1617,7 @@ public struct ProviderSessionWork: Codable, Equatable {
|
||||
self.providerProfile = providerProfile
|
||||
self.providerIdentity = providerIdentity
|
||||
self.policyVersionId = policyVersionId
|
||||
self.streamPolicy = streamPolicy
|
||||
self.applicationId = applicationId
|
||||
self.clientId = clientId
|
||||
self.managementHost = managementHost
|
||||
@@ -1518,7 +1636,7 @@ public struct ProviderSessionWork: Codable, Equatable {
|
||||
let all = try decoder.container(keyedBy: AnyCodingKey.self)
|
||||
for key in all.allKeys where CodingKeys(stringValue: key.stringValue) == nil { throw ContractValidationError(field: key.stringValue, code: "unknown_field") }
|
||||
let c = try decoder.container(keyedBy: CodingKeys.self)
|
||||
try self.init(version: try c.decode(String.self, forKey: .version), sessionId: try c.decode(String.self, forKey: .sessionId), gatewayId: try c.decode(String.self, forKey: .gatewayId), reconnectSequence: try c.decode(Int64.self, forKey: .reconnectSequence), expiresAt: try c.decode(String.self, forKey: .expiresAt), providerProfile: try c.decode(String.self, forKey: .providerProfile), providerIdentity: try c.decode(String.self, forKey: .providerIdentity), policyVersionId: try c.decode(String.self, forKey: .policyVersionId), applicationId: try c.decode(String.self, forKey: .applicationId), clientId: try c.decode(String.self, forKey: .clientId), managementHost: try c.decode(String.self, forKey: .managementHost), managementPort: try c.decode(Int64.self, forKey: .managementPort), streamHost: try c.decode(String.self, forKey: .streamHost), streamPort: try c.decode(Int64.self, forKey: .streamPort), clientCertificatePem: try c.decode(String.self, forKey: .clientCertificatePem), clientPrivateKeyPem: try c.decode(String.self, forKey: .clientPrivateKeyPem), serverCertificatePem: try c.decode(String.self, forKey: .serverCertificatePem), clipboardPolicy: try c.decode(ClipboardPolicy.self, forKey: .clipboardPolicy), providerApplicationTerminationAllowed: try c.decode(Bool.self, forKey: .providerApplicationTerminationAllowed))
|
||||
try self.init(version: try c.decode(String.self, forKey: .version), sessionId: try c.decode(String.self, forKey: .sessionId), gatewayId: try c.decode(String.self, forKey: .gatewayId), reconnectSequence: try c.decode(Int64.self, forKey: .reconnectSequence), expiresAt: try c.decode(String.self, forKey: .expiresAt), providerProfile: try c.decode(String.self, forKey: .providerProfile), providerIdentity: try c.decode(String.self, forKey: .providerIdentity), policyVersionId: try c.decode(String.self, forKey: .policyVersionId), streamPolicy: try c.decode(ProviderStreamPolicy.self, forKey: .streamPolicy), applicationId: try c.decode(String.self, forKey: .applicationId), clientId: try c.decode(String.self, forKey: .clientId), managementHost: try c.decode(String.self, forKey: .managementHost), managementPort: try c.decode(Int64.self, forKey: .managementPort), streamHost: try c.decode(String.self, forKey: .streamHost), streamPort: try c.decode(Int64.self, forKey: .streamPort), clientCertificatePem: try c.decode(String.self, forKey: .clientCertificatePem), clientPrivateKeyPem: try c.decode(String.self, forKey: .clientPrivateKeyPem), serverCertificatePem: try c.decode(String.self, forKey: .serverCertificatePem), clipboardPolicy: try c.decode(ClipboardPolicy.self, forKey: .clipboardPolicy), providerApplicationTerminationAllowed: try c.decode(Bool.self, forKey: .providerApplicationTerminationAllowed))
|
||||
}
|
||||
|
||||
public func validate() throws {
|
||||
@@ -1539,6 +1657,7 @@ public struct ProviderSessionWork: Codable, Equatable {
|
||||
if self.policyVersionId.isEmpty { throw ContractValidationError(field: "policy_version_id", code: "required") }
|
||||
if !self.policyVersionId.isEmpty && self.policyVersionId.utf8.count < 1 { throw ContractValidationError(field: "policy_version_id", code: "min_length") }
|
||||
if self.policyVersionId.utf8.count > 128 { throw ContractValidationError(field: "policy_version_id", code: "max_length") }
|
||||
try self.streamPolicy.validate()
|
||||
if self.applicationId.isEmpty { throw ContractValidationError(field: "application_id", code: "required") }
|
||||
if !self.applicationId.isEmpty && self.applicationId.utf8.count < 1 { throw ContractValidationError(field: "application_id", code: "min_length") }
|
||||
if self.applicationId.utf8.count > 128 { throw ContractValidationError(field: "application_id", code: "max_length") }
|
||||
@@ -1614,6 +1733,55 @@ public struct ProviderState: Codable, Equatable {
|
||||
public func encodeJSON() throws -> Data { try validate(); return try JSONEncoder().encode(self) }
|
||||
}
|
||||
|
||||
public struct ProviderStreamPolicy: Codable, Equatable {
|
||||
public let resolutionWidth: Int64
|
||||
public let resolutionHeight: Int64
|
||||
public let fps: Int64
|
||||
public let codec: String
|
||||
public let bitrateKbps: Int64
|
||||
public let audioEnabled: Bool
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case resolutionWidth = "resolution_width"
|
||||
case resolutionHeight = "resolution_height"
|
||||
case fps = "fps"
|
||||
case codec = "codec"
|
||||
case bitrateKbps = "bitrate_kbps"
|
||||
case audioEnabled = "audio_enabled"
|
||||
}
|
||||
|
||||
public init(resolutionWidth: Int64, resolutionHeight: Int64, fps: Int64, codec: String, bitrateKbps: Int64, audioEnabled: Bool) throws {
|
||||
self.resolutionWidth = resolutionWidth
|
||||
self.resolutionHeight = resolutionHeight
|
||||
self.fps = fps
|
||||
self.codec = codec
|
||||
self.bitrateKbps = bitrateKbps
|
||||
self.audioEnabled = audioEnabled
|
||||
try validate()
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let all = try decoder.container(keyedBy: AnyCodingKey.self)
|
||||
for key in all.allKeys where CodingKeys(stringValue: key.stringValue) == nil { throw ContractValidationError(field: key.stringValue, code: "unknown_field") }
|
||||
let c = try decoder.container(keyedBy: CodingKeys.self)
|
||||
try self.init(resolutionWidth: try c.decode(Int64.self, forKey: .resolutionWidth), resolutionHeight: try c.decode(Int64.self, forKey: .resolutionHeight), fps: try c.decode(Int64.self, forKey: .fps), codec: try c.decode(String.self, forKey: .codec), bitrateKbps: try c.decode(Int64.self, forKey: .bitrateKbps), audioEnabled: try c.decode(Bool.self, forKey: .audioEnabled))
|
||||
}
|
||||
|
||||
public func validate() throws {
|
||||
if self.resolutionWidth < 320 { throw ContractValidationError(field: "resolution_width", code: "minimum") }
|
||||
if self.resolutionWidth > 16384 { throw ContractValidationError(field: "resolution_width", code: "maximum") }
|
||||
if self.resolutionHeight < 200 { throw ContractValidationError(field: "resolution_height", code: "minimum") }
|
||||
if self.resolutionHeight > 8640 { throw ContractValidationError(field: "resolution_height", code: "maximum") }
|
||||
if self.fps < 1 { throw ContractValidationError(field: "fps", code: "minimum") }
|
||||
if self.fps > 240 { throw ContractValidationError(field: "fps", code: "maximum") }
|
||||
if !["H264", "HEVC", "AV1"].contains(self.codec) { throw ContractValidationError(field: "codec", code: "invalid_value") }
|
||||
if self.bitrateKbps < 100 { throw ContractValidationError(field: "bitrate_kbps", code: "minimum") }
|
||||
if self.bitrateKbps > 1000000 { throw ContractValidationError(field: "bitrate_kbps", code: "maximum") }
|
||||
}
|
||||
|
||||
public static func decodeJSON(_ data: Data) throws -> Self { try JSONDecoder().decode(Self.self, from: data) }
|
||||
public func encodeJSON() throws -> Data { try validate(); return try JSONEncoder().encode(self) }
|
||||
}
|
||||
|
||||
public struct ReauthGrant: Codable, Equatable {
|
||||
public let token: String
|
||||
public let purpose: String
|
||||
|
||||
Reference in New Issue
Block a user