TypeErasure.swift 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // TypeErasure.swift
  2. // This file is part of KeePass.
  3. //
  4. // Copyright © 2019 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 Foundation
  19. import Binary
  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> { AnyRandomAccessCollection<AnyEntry>(_base.entries.map { AnyEntry($0) }) }
  70. override var groups: AnyRandomAccessCollection<AnyGroup> { AnyRandomAccessCollection<AnyGroup>(_base.groups.map { AnyGroup($0) }) }
  71. var _base: Base
  72. init(_ base: Base) { _base = base }
  73. }
  74. class AnyGroup: Group {
  75. public var title: String {
  76. get { _box.title }
  77. set { _box.title = newValue }
  78. }
  79. public var icon: Int {
  80. get { _box.icon }
  81. set { _box.icon = newValue }
  82. }
  83. var entries: AnyRandomAccessCollection<AnyEntry> { _box.entries }
  84. var groups: AnyRandomAccessCollection<AnyGroup> { _box.groups }
  85. let _box: _AnyGroupBoxBase
  86. init<T>(_ base: T) where T: Group {
  87. _box = _AnyGroupBox(base)
  88. }
  89. }
  90. // MARK: - Entry
  91. class _AnyEntryBoxBase: Entry {
  92. var times: Timestamp { _abstract() }
  93. var fields: AnyRandomAccessCollection<Field> { _abstract() }
  94. func set(_ field: Field) { _abstract() }
  95. }
  96. final class _AnyEntryBox<Base>: _AnyEntryBoxBase where Base: Entry {
  97. override var times: Timestamp { _base.times }
  98. override var fields: AnyRandomAccessCollection<Field> { AnyRandomAccessCollection<Field>(_base.fields) }
  99. override func set(_ field: Field) { _base.set(field) }
  100. var _base: Base
  101. init(_ base: Base) { _base = base }
  102. }
  103. final class AnyEntry: Entry {
  104. public var times: Timestamp { _box.times }
  105. public var fields: AnyRandomAccessCollection<Field> { _box.fields }
  106. public func set(_ field: Field) { _box.set(field) }
  107. let _box: _AnyEntryBoxBase
  108. init<T>(_ base: T) where T: Entry {
  109. _box = _AnyEntryBox(base)
  110. }
  111. }