It also requires a userInfo property. We don't support that either, so it returns an empty dictionary:. Unlike the encoder, the decoder's data is loaded into the object when it's created. The caller provides the data that the decoder will decode from:. The decoder also needs to keep track of where it is inside the data it's decoding.
It does that with a cursor property, which starts out at the beginning of the data:. The decoder has its own errors it can throw during the decoding process.
Decoding can fail in many more ways than encoding, so BinaryDecoder 's Error type has a lot more cases:. Now we can get on to actual decoding. The lowest level method reads a certain number of bytes out of data into a pointer, advancing cursor , or throwing prematureEndOfData if data doesn't have enough bytes in it:. There's also a small generic wrapper which takes an inout T and reads into that value, using MemoryLayout to figure out how many bytes to read.
Like BinaryEncoder , BinaryDecoder has methods for decoding floating-point types. For these, it creates an empty CFSwappedFloat value, reads into it, and then calls the appropriate CF function to convert it to the floating-point type in question:.
The method for decoding Bool decodes a UInt8 and then returns false if it's 0 , true if it's 1 , and otherwise throws an error:. The general decode method for Decodable uses a big switch statement to decode various specific types:. The compiler doesn't realize that T 's type must match the values being produced, so the as!
T convinces it to compile this code. Float , Double , and Bool all call their type-specific decoding methods:. BinaryDecodable types use the initializer defined in that protocol, passing self:. The FixedWidthInteger method uses Self. BinaryDecoder Decoder Implementation As before, we implement the three container protocols. We'll start with the keyed container:. It also requires allKeys , which returns all keys that the container knows about.
Since we don't really support keys in the first place, this returns an empty array:. There's also a method to see if the container contains a given key. We'll just blindly say "yes" to all such questions:.
As before, KeyedDecodingContainerProtocol has a ton of different decode methods which can all be satisfied with a single generic method for Decodable:. Now BinaryDecoder itself can provide dummy implementations of the properties required by Decoder and implement methods to return instances of the containers:.
In theory I could call through to their Codable implementation, but I can't count on that implementation to work with the limitations of the binary coders, and I wouldn't have control over the serialized representation. Instead, I manually implemented it. The plan is to have Array encode its count, and then encode its elements. To decode, it can decode the count, then decode that many elements.
String will convert itself to UTF-8 in the form of Array and then use Array 's implementation to do the real work. Someday, when Swift gets conditional conformances , we'll be able to write extension Array: BinaryCodable to indicate that Array is is only codable when its contents are. For now, Swift can't express that notion.
Instead, we have to say that Array is always BinaryCodable , and then do runtime type checks to ensure the content is suitable. Encoding is a matter of checking the type of Element , encoding self. String can then encode itself by creating an Array from its utf8 property and encoding that:. This will fail if the decoded Array isn't valid UTF-8, so there's a little extra code here to check for that and throw an error:.
Example Use That takes care of binary encoding and decoding. Conclusion Swift's new Codable protocols are a welcome addition to the language to eliminate a lot of boilerplate code.
Unsophisticated binary formats such as this are not often called for, but they have their uses, and it's interesting to see how Codable can be used for something so different from the built-in facilities.
The Encoder and Decoder protocols are large, but judicious use of generics can cut down a lot of the repetitive code, and implementation is relatively simple in the end. BinaryCoder was written for exploratory and educational purposes, and it's probably not what you want to use in your own programs. However, there are cases where it could be suitable, as long as you understand the tradeoffs involved.
That's it for today! Come back again for more exciting byte-related adventures. Getting Answers Ten simple points to follow to get good answers on IRC, mailing lists, and other places.
Miscellaneous Pages Miscellaneous old, rarely-updated content. Posted at This article is also available in Hungarian translation by Zsolt Boros. Bool , forKey key: Int , forKey key: Int8 , forKey key: Int16 , forKey key: Int32 , forKey key: Int64 , forKey key: UInt , forKey key: UInt8 , forKey key: UInt16 , forKey key: UInt32 , forKey key: UInt64 , forKey key: Float , forKey key: Double , forKey key: String , forKey key: T , forKey key: Key throws where T: Type , forKey key: T throws where T: T case is Double.
T case is Bool. Did you enjoy this article? I'm selling whole books full of them! Click here for more information. Svetoslav at Alan W at Thanks, I fixed that too. Who would have thought that the one piece of code in this post that I just wrote for the article and didn't test would be full of errors.
If only there was some sort of lesson in here for me. David Waite at I guess I may be publicly humiliated at your sole discretion now. I give you minus two points for missing the part of the article where I mention that, but plus five points for figuring out the problem and a solution, so good job overall! Colin at Len for determining the length of a binary object. The following example reads a GIF file as binary data, converts it to a binary-encoded string, converts the binary-encoded data back to binary data, and writes the result to a file.
It displays the encoded string and the image in the output file. Description Converts binary data to a string.
Returns An encoded string representing the binary data. Category Conversion functions , String functions. Function syntax BinaryEncode binarydata , encoding.
History ColdFusion MX 7: Parameters Parameter Description binarydata A variable containing the binary data to encode. Usage Binary objects and, in some cases, 8-bit characters, cannot be transported over many Internet protocols, such as HTTP and SMTP, and might not be supported by some database systems. See the following pages for additional information on handling binary data: