Building structure for binary file


I really don’t know where to post stupid questions… so here we are:
I’m currently building a file parser and I’m looking for a way to represent different data structures within a datastream.

I got the basic functionality working and can parse the given file but my code is all over the place and not well maintainable. The problem that I have is, that Swift Dicts can’t have different types so I’m relying on a pattern like [String: Any] to represent different binaries like UInt32, UInt16 and Strings.

Currently using an ugly mix of switch to parse different font formats.

Is there a better way? Like using a struct, enum, class? (Unfortunately I think I need a way to iterate over the properties(?)) Maybe Pointers are the solution, but I digged not into it.

Disclosure: I’m really new to all that binary stuff and bitwise stuff (also not a pro in swift). Anyway, I hope I expressed my self in a way you can understand my problem.




I’m now looking into Decodable and a custom Decoder...


BinaryCodable seems like the right way.. maybe

You can do it in a more type-safe way, like this:

enum Number {
     case integer (Int)
     case natural (UInt)
     case real    (Double)
     case bool    (Bool)

var zeros = [String : Number] ()

zeros ["Z"] = .integer (0)
zeros ["N"] = .natural (0)
zeros ["R"] = .real (0)
zeros ["B"] = .bool(false)

for (k, v) in zeros {
    print (k, v)

// prints
Z integer(0)
N natural(0)
B bool(false)
R real(0.0)
1 Like

Looks good.
Usage would be like:

enum FileHeader {
  case signature (UInt32)
  case length (UInt32)
  case offset (UInt16)

Thats right? I’ll give it a try.

Ah sorry. You mean to represent the structure as a dict in a typesafe way...

Edit 2:
@ibex10 But accessing the value is complicated, isn't it?

I'm now doing something like this:

enum BinaryType {
    case uint32 (UInt32)
    case uint16 (UInt16)
    case uint8 (UInt8)
    case string (String)
    var string: String? {
        switch self {
        case let .string(val):
            return val
            return nil
    var uint32: UInt32? {
        switch self {
        case let .uint32(val):
            return val
        case let .uint16(val):
            return UInt32(val)
        case let .uint8(val):
            return UInt32(val)
        case .string:
            return nil

But that seems odd...

Edit 3:
Found that syntax – looks fancy..

guard case .uint32(let val) = enumVar else { return nil }

// do something with val

I think you meant this:

struct FileHeader {
    let signature : UInt32
    let length    : UInt32
    let offset    : UInt16
1 Like

I meant your idea with enum but I missed the point..

The problem with using a struct is, that I cant programatically fill the struct based on the properties, because the files are structured differently.

But maybe I miss something.. what I really looking for is the best practice to decode a binary file into structured data which I can access easily. This solutions are just my simple ideas, because I don't know anything about that, I think.

A similar topic has been discussed here.

1 Like

Got a good solution with just using structs for the structure.