Treata11 / SwiftMXL

Implementation of the MusicXML specification in Swift
MIT License
9 stars 0 forks source link

Time.Measured #2

Open Treata11 opened 1 year ago

Treata11 commented 1 year ago

Time fails to decode array of Time.Signature

Based on Time.Measured implementations

public struct Measured {
   // FIXME:
   var values: [Time.Signature]
   var interchangeable: Interchangeable?

   public init(_ values: [Time.Signature], interchangeable: Interchangeable? = nil) {
       self.values = values
       self.interchangeable = interchangeable
   }
}

& based on Time's elements in a common MusicXML

<time symbol="single-number">
  <beats>1</beats>
  <beat-type>8</beat-type>
  <beats>2</beats>
  <beat-type>4</beat-type>    
</time>

The array of Time.Signature is certainly an unkeyed element since no keys for this variable exist in a MusicXML file.

Unkeyed element of type [Signature] in Measured fails to be decoded

extension Time.Measured: Codable {
   enum CodingKeys: String, CodingKey {
//       case signature
       case interchangeable
   }

   public init(from decoder: Decoder) throws {
       let container = try decoder.container(keyedBy: Time.Measured.CodingKeys.self)

       self.values = try decoder.collectArray()
       self.interchangeable = try container.decodeIfPresent(Interchangeable.self, forKey: .interchangeable)
   }
}

The line self.values = try decoder.collectArray() should be able to decode the array of `[Time.Signature] but throws an error in the debugger:

error: -[SwiftMXLTests.TimeTests testDecodingMeasured] : failed: caught error:
"typeMismatch(Swift.Dictionary<Swift.String, Any>,
    Swift.DecodingError.Context(codingPath: 
    [XMLKey(stringValue: "0", intValue: 0),
    XMLKey(stringValue: "0", intValue: 0)],
    debugDescription: "Expected to decode Dictionary<String, Any> but found ChoiceBox instead.",
    underlyingError: nil)
)"

I currently don't know what is wrong, but I have two options right now:

**1. A Workaround

  1. Investigate the thrown error**

The Workaround

Currently, instead of decoding an array of Signature, I decoded an array of beats an another array for beatType. This would decode the data in the following way:

decoded:
Measured(signature: [SwiftMXL.Time.Signature(beats: ["3", "1"], beatType: ["4", "8"])], interchangeable: nil)

The workaround would be to write some logic for the decoded beats & beatTypes that would initialize an array of Time.Signature with the number of elements based on the count of beats & then return the decoded data using the created array. Though it isn't a very convenient approach, it'll work at least for the decode process.

The Investigation

Involves more debugging & more reading for me unless some one with more skills identifies the issue & makes my life easier.

Treata11 commented 1 year ago

The workaround is the current implementation.