import Foundation public struct RDEPUBCFI: Codable, Equatable, Hashable { public var packagePath: RDEPUBCFIPath public var contentPath: RDEPUBCFIPath public var characterOffset: Int? public var sideBias: RDEPUBCFISideBias? public var textAssertion: RDEPUBCFITextAssertion? /// Always computed from components — no stale cached value risk. public var rawValue: String { RDEPUBCFISerializer.serialize(self) } /// Initialize from components. The `rawValue` parameter is ignored — rawValue is always /// computed from the components. To parse a CFI string, use `RDEPUBCFIParser.parse(_:)`. public init( rawValue: String = "", packagePath: RDEPUBCFIPath = RDEPUBCFIPath(), contentPath: RDEPUBCFIPath = RDEPUBCFIPath(), characterOffset: Int? = nil, sideBias: RDEPUBCFISideBias? = nil, textAssertion: RDEPUBCFITextAssertion? = nil ) { self.packagePath = packagePath self.contentPath = contentPath self.characterOffset = characterOffset self.sideBias = sideBias self.textAssertion = textAssertion } public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let rawValue = try container.decode(String.self) let parsed = try RDEPUBCFIParser.parse(rawValue) self.packagePath = parsed.packagePath self.contentPath = parsed.contentPath self.characterOffset = parsed.characterOffset self.sideBias = parsed.sideBias self.textAssertion = parsed.textAssertion } public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(rawValue) } } public enum RDEPUBCFISideBias: String, Codable, Equatable, Hashable { case before = "b" case after = "a" }