Codable? or something else?

I'm new to swift, but have been an infra engineer for a long time so while I may not be making the next programming language or operating system, I can ruby my way out of a wet paper bag usually.

I'm trying to write an implementation of the AX.25 protocol in Swift. I recognize this is a huge undertaking, but that's fine :) The part I'm working on right now is just parsing the frames.

Very high level format:
7 bytes for "to", 7 bytes for "from", 0 or more 7 bytes fields of repeaters, 1 or 2 bytes for frame type and other metadata (depending on if it's a modulo128 or modulo8 frame, something that is not part of the frame but state in the stack and negotiated at connection time, so supplied from outside) and then some data.

There are 3 major frame types, I, S, and U, and each of those has different ways of parsing the frame type / metadata field (though the frame type itself is always in the same place in the frame type field regardless of modulo. The U frame type has several subtypes as well, and while the S frame type seems like it might, really those are just a 2 bit flag on the frame and aren't really distinct types.

So here's kinda the hierachy I'm thinking of

  • Frame
    • S frame
    • I frame
    • U frame
      • UI frame
      • TEST frame
      • etc.

So far the guidance I've found online says I should have, at least to start, 3 structs, one for each of the main types, and a protocol that defines the common parts for the frame (from, to, repeaters). But I'm trying to figure out how to take that chunk of bytes and actually parse it and return an instance of the correct frame type. I've got a handle on the actual extraction of info (github) so now I'm trying to organize things properly and try to Swift-ify things.

So, my question is: would this be a good use case for Codable? Everything I've been reading online about Codable, all the examples, mostly talk about mapping properties to and from json keys and whatnot, and don't seem very applicable to my situation. Also, and this is part of the noobness, they talk about enums with associated values for doing something something subtypes? I'm not really certain. Also I feel like generics have been in there too, and I'm not sure if I need generics for any of this but they don't make enough sense to me yet to be sure if they do or not.

I'd love some guidance to help me get on to the next step of this if anyone can help out. Even just a "here's a good doc to read about this" would be great :)

Thinking more about this, I think I might be able to layer the codables? Like start with just parts of the frame and making each part encodable / decodable. So I'm working on just the CallSignSSID bit. It's a simple struct:

struct CallSignSSID: Codable {
  let callSign: String
  let ssid: UInt8

I can successfully pull that down to JSON using JSONEncoder, hooray!

So now to encode it down to ax25 stuff, would I create like an AX25FrameEncoder that has an encode method for CallSignSSID that would then use encode methods on String and Int and return that? Or would the CallSignSSID method handle its member components directly and return the whole thing?

And then I can build up the frame doing that, have a struct for CallSignSSIDField that encapsulates the CallSignSSID and the metadata bits, and an encode method on the AX25FrameEncoder for CallSignSSIDField, and up and up?

I think that seems reasonable!

There's still then the question of how do I do the multiple sub-types here and structure all of that?

Talking to myself, sorry, but I think I'm making progress!

This post had come up previously in my searching, and it seemed like it was way more complex than I really needed and so I thought maybe it wasn't what I was looking for, but now I think it actually is very much what I'm looking for, or at least points me in all the right directions.

Between this and finding some docs regarding parsing a json into multiple subtypes, I think I might be heading the right direction. I've definitely come across a post like that before but I can't find it right now, but I'm sure I'll find it again!

Thanks for the :duck: so far!