<div dir="ltr"><div>For context, the problem I’m trying to solve is efficiently parsing JPEG chunks. This means reading each chunk of the JPEG from a file into a raw buffer pointer, and then parsing the chunk according to its expected layout. For example, a frame header chunk looks like this:<br><span style="font-family:monospace,monospace"><br></span></div><span style="font-family:monospace,monospace">0 1 2 3 4 5 6<br>[ precision:UInt8 | height:UInt16 | width:UInt16 | Nf:UInt8 | ... ]</span><br><div><br></div><div>what I want to do is to be able to load the height and width into something I can pass into <span style="font-family:monospace,monospace">UInt16.init(bigEndian:)</span> without failing because of alignment. I’ve thought of several options but none of them seem to be great.</div><div><br></div><div>1 - bind the entire buffer to <span style="font-family:monospace,monospace">UInt8.self</span>, and then do <span style="font-family:monospace,monospace">buffer[1] << UInt8.bitWidth | buffer[2]</span>. probably most straightforward, but doesn’t generalize well at all to larger <span style="font-family:monospace,monospace">Int</span> types.</div><div><br></div><div>2 - copy <span style="font-family:monospace,monospace">MemoryLayout<UInt16>.size</span> bytes from offset 1 into the beginning of a new raw buffer, aligned to <span style="font-family:monospace,monospace">MemoryLayout<UInt16>.alignment</span>, and do <span style="font-family:monospace,monospace">load(fromByteOffset: 0, as: UInt16.self)</span> from <i>that</i>. Seems very inefficient because you have to allocate a new heap buffer copy everything over and then free it just to hold the bytes in the right alignment.</div><div><br></div><div>3 - use <span style="font-family:monospace,monospace">withUnsafeMutablePointer(to:_:)</span> on a local variable of type <span style="font-family:monospace,monospace">UInt16</span>, cast it to a raw pointer, and copy <span style="font-family:monospace,monospace">MemoryLayout<UInt16>.size</span> bytes into it. Like 2 it involves declaring a temporary variable which is annoying, and also, while the default initialization isn’t that big a problem, it’s introducing a meaningless value into the source code and can be problematic for non-integer types. Also, wasn’t Swift supposed to be designed so that <span style="font-family:monospace,monospace">Optional</span> is the only thing which has a “default” value; <span style="font-family:monospace,monospace">Bool</span> does not default to <span style="font-family:monospace,monospace">false</span> and <span style="font-family:monospace,monospace">Int</span> does not default to <span style="font-family:monospace,monospace">0</span>. Default constructors are evil.</div><div><br></div><div><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 8, 2017 at 7:49 PM, Johannes Weiß <span dir="ltr"><<a href="mailto:johannesweiss@apple.com" target="_blank">johannesweiss@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Kelvin,<br>
<span class=""><br>
> On 8 Nov 2017, at 5:40 pm, Kelvin Ma <<a href="mailto:kelvin13ma@gmail.com">kelvin13ma@gmail.com</a>> wrote:<br>
><br>
> yikes there’s no less verbose way to do that? and if the type isn’t an integer there’s no way to avoid the default initialization? Can this be done with opaques or something?<br>
<br>
</span>well, it's 5 lines for the generic case to rule all the integers. You could just put that in a function and never think about it again, right?<br>
<br>
func integerFromBuffer<T: FixedWidthInteger>(_ pointer: UnsafeRawBufferPointer, index: Int) -> T {<br>
precondition(index >= 0)<br>
precondition(index <= pointer.count - MemoryLayout<T>.size)<br>
<br>
var value = T()<br>
withUnsafeMutableBytes(of: &value) { valuePtr in<br>
valuePtr.copyBytes(from: UnsafeRawBufferPointer(start: pointer.baseAddress!.advanced(<wbr>by: index),<br>
count: MemoryLayout<T>.size))<br>
}<br>
return value<br>
}<br>
<br>
should work (untested). Also you might need to handle endianness.<br>
<br>
Regarding types that are not integers, what types are you thinking of? For normal Swift types the layout isn't guaranteed so you can't just read the bytes from somewhere. For C types where the layout is known you can just use the above code and either relax the constraint or specialise it to the very type you need. The only requirement of the type (besides that it's layout is defined) is that is has an empty constructor.</blockquote><div><br></div><div>This isn’t what I’m trying to do atm but does this mean it’s not possible to save a memory dump of a Swift struct to a file and then read it back in from the file to reconstitute it? Also the empty constructor requirement is problematic as explained before, especially when the type isn’t super simple like an <span style="font-family:monospace,monospace">Int</span>.<br></div></div></div></div>