@@ -31,13 +31,16 @@ enum Metadata {
3131 /// for complex types (such as arrays and dictionaries), describing the type information of sub-elements (such as an
3232 /// array's element, or each of a dictionary's properties).
3333 ///
34- /// Note: this is used for the Plist and YAML Stencil contexts
34+ /// Note: this is used for the JSON, Plist and YAML Stencil contexts
3535 ///
3636 /// - Parameter data: The value to describe
3737 /// - Returns: Dictionary with type information about the value (for Stencil context)
3838 static func generate( for data: Any ) -> [ String : Any ] {
3939 let dataType = type ( of: data)
4040
41+ // We want to use toll-free briding using `data is X`, to for example easily check if something is a `String` (or
42+ // `String`-like). In other cases we actually want to avoid it, and use `dataType == X.self`. TFB to `NSNumber` for
43+ // example leads to confusion for ambiguous values (0, 1, true, false, ...).
4144 if data is String {
4245 return [ Key . type: ValueType . string]
4346 } else if dataType == Bool . self {
@@ -46,9 +49,9 @@ enum Metadata {
4649 return [ Key . type: ValueType . int]
4750 } else if dataType == Double . self {
4851 return [ Key . type: ValueType . double]
49- } else if dataType == Date . self {
52+ } else if data is Date {
5053 return [ Key . type: ValueType . date]
51- } else if dataType == Data . self {
54+ } else if data is Data {
5255 return [ Key . type: ValueType . data]
5356 } else if let data = data as? NSNumber {
5457 return [ Key . type: valueType ( for: data) ]
@@ -104,6 +107,13 @@ enum Metadata {
104107 }
105108 }
106109
110+ /// Get the value type of a number if possible.
111+ ///
112+ /// `NSNumber` does not provide an easy way for checking the internal value type. Therefore we first have to check if
113+ /// it's a boolean, and if not try to match the CF type to something Swift-y.
114+ ///
115+ /// - Parameter number: The value to describe
116+ /// - Returns: `ValueType` case (may be `any` if no match is found)
107117 private static func valueType( for number: NSNumber ) -> String {
108118 if CFGetTypeID ( number) == CFBooleanGetTypeID ( ) {
109119 return ValueType . bool
@@ -120,6 +130,13 @@ enum Metadata {
120130 }
121131 }
122132
133+ /// Returns the element value type, if all elements have the same type.
134+ ///
135+ /// The problem with `NSNumber` arrays is that they can contain mixed content, such as `[0.1, 2, true]`. Therefore,
136+ /// we have to check the type of each element.
137+ ///
138+ /// - Parameter array: The value to describe
139+ /// - Returns: `ValueType` case if array is uniform (`nil` otherwise)
123140 private static func elementValueType( for array: [ NSNumber ] ) -> String ? {
124141 let valueTypes = Set ( array. map ( valueType ( for: ) ) )
125142
0 commit comments