TypeErasure.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // TypeErasure.swift
  2. // This file is part of KeePass.
  3. //
  4. // Copyright © 2021 Maxime Epain. All rights reserved.
  5. //
  6. // KeePass is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // KeePass is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with KeePass. If not, see <https://www.gnu.org/licenses/>.
  18. import Binary
  19. import Foundation
  20. @inline(never)
  21. func _abstract(file: StaticString = #file, line: UInt = #line) -> Never {
  22. fatalError("Method must be overridden", file: file, line: line)
  23. }
  24. // MARK: - Database
  25. class _AnyDatabaseBoxBase: Database {
  26. var root: AnyGroup { _abstract() }
  27. func write(to output: Output, compositeKey: CompositeKey) throws { _abstract() }
  28. }
  29. final class _AnyDatabaseBox<Base>: _AnyDatabaseBoxBase where Base: Database {
  30. override var root: AnyGroup { AnyGroup(_base.root) }
  31. var _base: Base
  32. init(_ base: Base) { _base = base }
  33. override func write(to output: Output, compositeKey: CompositeKey) throws {
  34. try _base.write(to: output, compositeKey: compositeKey)
  35. }
  36. }
  37. class AnyDatabase: Database {
  38. var root: AnyGroup { _box.root }
  39. let _box: _AnyDatabaseBoxBase
  40. init<T>(_ base: T) where T: Database {
  41. _box = _AnyDatabaseBox(base)
  42. }
  43. func write(to output: Output, compositeKey: CompositeKey) throws {
  44. try _box.write(to: output, compositeKey: compositeKey)
  45. }
  46. }
  47. // MARK: - Group
  48. class _AnyGroupBoxBase: Group {
  49. var title: String {
  50. get { _abstract() }
  51. set { _abstract() }
  52. }
  53. var icon: Int {
  54. get { _abstract() }
  55. set { _abstract() }
  56. }
  57. var entries: AnyRandomAccessCollection<AnyEntry> { _abstract() }
  58. var groups: AnyRandomAccessCollection<AnyGroup> { _abstract() }
  59. }
  60. final class _AnyGroupBox<Base>: _AnyGroupBoxBase where Base: Group {
  61. override var title: String {
  62. get { _base.title }
  63. set { _base.title = newValue }
  64. }
  65. override var icon: Int {
  66. get { _base.icon }
  67. set { _base.icon = newValue }
  68. }
  69. override var entries: AnyRandomAccessCollection<AnyEntry> {
  70. AnyRandomAccessCollection<AnyEntry>(_base.entries.map { AnyEntry($0) })
  71. }
  72. override var groups: AnyRandomAccessCollection<AnyGroup> {
  73. AnyRandomAccessCollection<AnyGroup>(_base.groups.map { AnyGroup($0) })
  74. }
  75. var _base: Base
  76. init(_ base: Base) { _base = base }
  77. }
  78. class AnyGroup: Group {
  79. public var title: String {
  80. get { _box.title }
  81. set { _box.title = newValue }
  82. }
  83. public var icon: Int {
  84. get { _box.icon }
  85. set { _box.icon = newValue }
  86. }
  87. var entries: AnyRandomAccessCollection<AnyEntry> { _box.entries }
  88. var groups: AnyRandomAccessCollection<AnyGroup> { _box.groups }
  89. let _box: _AnyGroupBoxBase
  90. init<T>(_ base: T) where T: Group {
  91. _box = _AnyGroupBox(base)
  92. }
  93. }
  94. // MARK: - Entry
  95. class _AnyEntryBoxBase: Entry {
  96. var times: Timestamp { _abstract() }
  97. var fields: AnyRandomAccessCollection<Field> { _abstract() }
  98. func set(_ field: Field) { _abstract() }
  99. }
  100. final class _AnyEntryBox<Base>: _AnyEntryBoxBase where Base: Entry {
  101. override var times: Timestamp { _base.times }
  102. override var fields: AnyRandomAccessCollection<Field> { AnyRandomAccessCollection<Field>(_base.fields) }
  103. override func set(_ field: Field) { _base.set(field) }
  104. var _base: Base
  105. init(_ base: Base) { _base = base }
  106. }
  107. final class AnyEntry: Entry {
  108. public var times: Timestamp { _box.times }
  109. public var fields: AnyRandomAccessCollection<Field> { _box.fields }
  110. public func set(_ field: Field) { _box.set(field) }
  111. let _box: _AnyEntryBoxBase
  112. init<T>(_ base: T) where T: Entry {
  113. _box = _AnyEntryBox(base)
  114. }
  115. }