Parsed.swift 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the Swift Argument Parser open source project
  4. //
  5. // Copyright (c) 2020 Apple Inc. and the Swift project authors
  6. // Licensed under Apache License v2.0 with Runtime Library Exception
  7. //
  8. // See https://swift.org/LICENSE.txt for license information
  9. //
  10. //===----------------------------------------------------------------------===//
  11. enum Parsed<Value> {
  12. /// The definition of how this value is to be parsed from command-line arguments.
  13. ///
  14. /// Internally, this wraps an `ArgumentSet`, but that’s not `public` since it’s
  15. /// an implementation detail.
  16. case value(Value)
  17. case definition((InputKey) -> ArgumentSet)
  18. internal init(_ makeSet: @escaping (InputKey) -> ArgumentSet) {
  19. self = .definition(makeSet)
  20. }
  21. }
  22. // Note: This type uses `@unchecked Sendable` to work around a sendability
  23. // warning that would otherwise arise:
  24. //
  25. // Initial values (that are only conditionally `Sendable`) are captured in
  26. // what would otherwise need to be an always-`@Sendable` closure.
  27. // This isn't actually an issue, since the only time the wrapper type is
  28. // actually sendable is when the value is.
  29. extension Parsed: @unchecked Sendable where Value: Sendable {}
  30. /// A type that wraps a `Parsed` instance to act as a property wrapper.
  31. ///
  32. /// This protocol simplifies the implementations of property wrappers that
  33. /// wrap the `Parsed` type.
  34. internal protocol ParsedWrapper: Decodable, ArgumentSetProvider {
  35. associatedtype Value
  36. var _parsedValue: Parsed<Value> { get }
  37. init(_parsedValue: Parsed<Value>)
  38. }
  39. /// A `Parsed`-wrapper whose value type knows how to decode itself.
  40. ///
  41. /// Types that conform to this protocol can initialize their values directly
  42. /// from a `Decoder`.
  43. internal protocol DecodableParsedWrapper: ParsedWrapper
  44. where Value: Decodable {
  45. init(_parsedValue: Parsed<Value>)
  46. }
  47. extension ParsedWrapper {
  48. init(_decoder: Decoder) throws {
  49. guard let d = _decoder as? SingleValueDecoder else {
  50. throw ParserError.invalidState
  51. }
  52. guard let value = d.parsedElement?.value as? Value else {
  53. throw ParserError.noValue(forKey: d.parsedElement?.key ?? d.key)
  54. }
  55. self.init(_parsedValue: .value(value))
  56. }
  57. func argumentSet(for key: InputKey) -> ArgumentSet {
  58. switch _parsedValue {
  59. case .value:
  60. fatalError(
  61. "Trying to get the argument set from a resolved/parsed property.")
  62. case .definition(let a):
  63. return a(key)
  64. }
  65. }
  66. }
  67. extension ParsedWrapper where Value: Decodable {
  68. init(_decoder: Decoder) throws {
  69. var value: Value
  70. do {
  71. value = try Value.init(from: _decoder)
  72. } catch {
  73. if let d = _decoder as? SingleValueDecoder,
  74. let v = d.parsedElement?.value as? Value
  75. {
  76. value = v
  77. } else {
  78. throw error
  79. }
  80. }
  81. self.init(_parsedValue: .value(value))
  82. }
  83. }