// TypeErasure.swift
// This file is part of KeePass.
//
// Copyright © 2021 Maxime Epain. All rights reserved.
//
// KeePass is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// KeePass is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with KeePass. If not, see .
import Binary
import Foundation
@inline(never)
func _abstract(file: StaticString = #file, line: UInt = #line) -> Never {
fatalError("Method must be overridden", file: file, line: line)
}
// MARK: - Database
class _AnyDatabaseBoxBase: Database {
var root: AnyGroup { _abstract() }
func write(to output: Output, compositeKey: CompositeKey) throws { _abstract() }
}
final class _AnyDatabaseBox: _AnyDatabaseBoxBase where Base: Database {
override var root: AnyGroup { AnyGroup(_base.root) }
var _base: Base
init(_ base: Base) { _base = base }
override func write(to output: Output, compositeKey: CompositeKey) throws {
try _base.write(to: output, compositeKey: compositeKey)
}
}
class AnyDatabase: Database {
var root: AnyGroup { _box.root }
let _box: _AnyDatabaseBoxBase
init(_ base: T) where T: Database {
_box = _AnyDatabaseBox(base)
}
func write(to output: Output, compositeKey: CompositeKey) throws {
try _box.write(to: output, compositeKey: compositeKey)
}
}
// MARK: - Group
class _AnyGroupBoxBase: Group {
var title: String {
get { _abstract() }
set { _abstract() }
}
var icon: Int {
get { _abstract() }
set { _abstract() }
}
var entries: AnyRandomAccessCollection { _abstract() }
var groups: AnyRandomAccessCollection { _abstract() }
}
final class _AnyGroupBox: _AnyGroupBoxBase where Base: Group {
override var title: String {
get { _base.title }
set { _base.title = newValue }
}
override var icon: Int {
get { _base.icon }
set { _base.icon = newValue }
}
override var entries: AnyRandomAccessCollection {
AnyRandomAccessCollection(_base.entries.map { AnyEntry($0) })
}
override var groups: AnyRandomAccessCollection {
AnyRandomAccessCollection(_base.groups.map { AnyGroup($0) })
}
var _base: Base
init(_ base: Base) { _base = base }
}
class AnyGroup: Group {
public var title: String {
get { _box.title }
set { _box.title = newValue }
}
public var icon: Int {
get { _box.icon }
set { _box.icon = newValue }
}
var entries: AnyRandomAccessCollection { _box.entries }
var groups: AnyRandomAccessCollection { _box.groups }
let _box: _AnyGroupBoxBase
init(_ base: T) where T: Group {
_box = _AnyGroupBox(base)
}
}
// MARK: - Entry
class _AnyEntryBoxBase: Entry {
var times: Timestamp { _abstract() }
var fields: AnyRandomAccessCollection { _abstract() }
func set(_ field: Field) { _abstract() }
}
final class _AnyEntryBox: _AnyEntryBoxBase where Base: Entry {
override var times: Timestamp { _base.times }
override var fields: AnyRandomAccessCollection { AnyRandomAccessCollection(_base.fields) }
override func set(_ field: Field) { _base.set(field) }
var _base: Base
init(_ base: Base) { _base = base }
}
final class AnyEntry: Entry {
public var times: Timestamp { _box.times }
public var fields: AnyRandomAccessCollection { _box.fields }
public func set(_ field: Field) { _box.set(field) }
let _box: _AnyEntryBoxBase
init(_ base: T) where T: Entry {
_box = _AnyEntryBox(base)
}
}