Variant.swift 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // Variant.swift
  2. // This file is part of KeePassKit.
  3. //
  4. // Copyright © 2019 Maxime Epain. All rights reserved.
  5. //
  6. // KeePassKit 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. // KeePassKit 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 KeePassKit. If not, see <https://www.gnu.org/licenses/>.
  18. import Binary
  19. import Foundation
  20. public enum Variant {
  21. struct Version {
  22. let major: UInt8
  23. let minor: UInt8
  24. }
  25. case End
  26. case Bool(Bool)
  27. case UInt32(UInt32)
  28. case UInt64(UInt64)
  29. case Int32(Int32)
  30. case Int64(Int64)
  31. case String(String)
  32. case Bytes(Bytes)
  33. enum ID: UInt8, Streamable {
  34. case End = 0x00
  35. case Bool = 0x08
  36. case UInt32 = 0x04
  37. case UInt64 = 0x05
  38. case Int32 = 0x0C
  39. case Int64 = 0x0D
  40. case String = 0x18
  41. case Bytes = 0x42
  42. }
  43. var id: ID {
  44. switch self {
  45. case .End:
  46. return .End
  47. case .Bool:
  48. return .Bool
  49. case .UInt32:
  50. return .UInt32
  51. case .UInt64:
  52. return .UInt64
  53. case .Int32:
  54. return .Int32
  55. case .Int64:
  56. return .Int64
  57. case .String:
  58. return .String
  59. case .Bytes:
  60. return .Bytes
  61. }
  62. }
  63. init() {
  64. self = .End
  65. }
  66. init(_ value: Bool) {
  67. self = .Bool(value)
  68. }
  69. init(_ value: UInt32) {
  70. self = .UInt32(value)
  71. }
  72. init(_ value: UInt64) {
  73. self = .UInt64(value)
  74. }
  75. init(_ value: Int32) {
  76. self = .Int32(value)
  77. }
  78. init(_ value: Int64) {
  79. self = .Int64(value)
  80. }
  81. init(_ value: String) {
  82. self = .String(value)
  83. }
  84. init(_ value: Bytes) {
  85. self = .Bytes(value)
  86. }
  87. func unwrap() throws -> Bool {
  88. guard case let .Bool(value) = self else { throw KDBXError.invalidValue }
  89. return value
  90. }
  91. func unwrap() throws -> UInt32 {
  92. guard case let .UInt32(value) = self else { throw KDBXError.invalidValue }
  93. return value
  94. }
  95. func unwrap() throws -> UInt64 {
  96. guard case let .UInt64(value) = self else { throw KDBXError.invalidValue }
  97. return value
  98. }
  99. func unwrap() throws -> Int32 {
  100. guard case let .Int32(value) = self else { throw KDBXError.invalidValue }
  101. return value
  102. }
  103. func unwrap() throws -> Int64 {
  104. guard case let .Int64(value) = self else { throw KDBXError.invalidValue }
  105. return value
  106. }
  107. func unwrap() throws -> String {
  108. guard case let .String(value) = self else { throw KDBXError.invalidValue }
  109. return value
  110. }
  111. func unwrap() throws -> Bytes {
  112. guard case let .Bytes(value) = self else { throw KDBXError.invalidValue }
  113. return value
  114. }
  115. func unwrap<T>() throws -> T where T: BytesRepresentable {
  116. guard case let .Bytes(bytes) = self else { throw KDBXError.invalidValue }
  117. return try T(bytes)
  118. }
  119. }
  120. extension Variant: Writable {
  121. init(id: ID, from input: Input) throws {
  122. let lenght: UInt32 = try input.read()
  123. switch id {
  124. case .Bool:
  125. guard lenght == MemoryLayout<Bool>.size else { throw KDBXError.invalidValue }
  126. self = .Bool(try input.read())
  127. case .UInt32:
  128. guard lenght == MemoryLayout<UInt32>.size else { throw KDBXError.invalidValue }
  129. self = .UInt32(try input.read())
  130. case .UInt64:
  131. guard lenght == MemoryLayout<UInt64>.size else { throw KDBXError.invalidValue }
  132. self = .UInt64(try input.read())
  133. case .Int32:
  134. guard lenght == MemoryLayout<Int32>.size else { throw KDBXError.invalidValue }
  135. self = .Int32(try input.read())
  136. case .Int64:
  137. guard lenght == MemoryLayout<Int64>.size else { throw KDBXError.invalidValue }
  138. self = .Int64(try input.read())
  139. case .String:
  140. self = .String(try input.read(lenght: Int(lenght)))
  141. case .Bytes:
  142. self = .Bytes(try input.read(lenght: Int(lenght)))
  143. default:
  144. throw KDBXError.invalidValue
  145. }
  146. }
  147. public func write(to output: Output) throws {
  148. switch self {
  149. case .End:
  150. try output.write(id)
  151. case let .Bool(value):
  152. try output.write(MemoryLayout<Bool>.size)
  153. try output.write(value)
  154. case let .UInt32(value):
  155. try output.write(MemoryLayout<UInt32>.size)
  156. try output.write(value)
  157. case let .UInt64(value):
  158. try output.write(MemoryLayout<UInt64>.size)
  159. try output.write(value)
  160. case let .Int32(value):
  161. try output.write(MemoryLayout<Int32>.size)
  162. try output.write(value)
  163. case let .Int64(value):
  164. try output.write(MemoryLayout<Int64>.size)
  165. try output.write(value)
  166. case let .String(value):
  167. try output.write(Swift.UInt32(value.count))
  168. try output.write(value)
  169. case let .Bytes(value):
  170. try output.write(Swift.UInt32(value.lenght))
  171. try output.write(value)
  172. }
  173. }
  174. }
  175. extension Variant.Version: Streamable {
  176. init(from input: Input) throws {
  177. minor = try input.read()
  178. major = try input.read()
  179. }
  180. func write(to output: Output) throws {
  181. try output.write(minor)
  182. try output.write(major)
  183. }
  184. }
  185. extension Dictionary: Streamable where Key == String, Value == Variant {
  186. public init(from input: Input) throws {
  187. self.init()
  188. let version: Variant.Version = try input.read()
  189. guard version.major > 0 else { throw KDBXError.invalidValue }
  190. while true {
  191. let id: Variant.ID = try input.read()
  192. if id == .End { break }
  193. let lenght: UInt32 = try input.read()
  194. let key: String = try input.read(lenght: Int(lenght))
  195. let value = try Variant(id: id, from: input)
  196. self[key] = value
  197. }
  198. }
  199. public func write(to output: Output) throws {
  200. let version = Variant.Version(major: 1, minor: 0)
  201. try output.write(version)
  202. try forEach {
  203. try output.write($0.value.id)
  204. try output.write(UInt32($0.key.count))
  205. try output.write($0.key)
  206. try output.write($0.value)
  207. }
  208. try output.write(Variant.End)
  209. }
  210. }
  211. extension Dictionary: BytesRepresentable where Key == String, Value == Variant {
  212. public init(_ bytes: Bytes) throws {
  213. let input = Input(bytes: bytes)
  214. try self.init(from: input)
  215. }
  216. public var bytes: Bytes {
  217. let output = Output()
  218. try? output.write(self)
  219. return output.bytes ?? []
  220. }
  221. }