Noze.io 0.3.1 `http_parser_settings`

Noze.io 0.3.1 is a minor release which just adds two things: a) compatibility with Swift 3 Preview 4 on both macOS & tuxOS and b) use of the new protocol based http_parser port.

Swift 3 Preview 4

Swift 3 Preview 4 changes quite a few things. As usual we try to alias most of the differences in the core module. For example you can use Error or ExpressibleByIntegerLiteral in Swift 2 (instead of the Swift 2 native ErrorType / ArrayLiteralConvertible).

Due to global renames in Preview 4 (e.g. ErrorProtocol to Error) a lot of files are affected in Noze.io, but be afraid not: most are just naming changes.

Protocol based http_parser

The other ‘feature’ in 0.3.1 is the protocol based http_parser. The previous version of the Noze.io Node/Nginx Swift parser-port used closures to report parsing events, like so:

parser.onHeadersComplete { parser in
  print("did parse HTTP request head: \(parser.method)")
}

While this is kinda nice, (escaping) closures are actually relatively slow to capture and call. This doesn’t matter so much for regular application code, but it does matter a lot for the performance of such a low level component.

To fix this, http_parser_settings is now a protocol. (Note that the old, closure-style, way of using the parser is still available using the http_parser_settings_cb struct, see the tests for an example)

To use the parser with a protocol just implement it, e.g.:

class MyParsingObject: http_parser_settings {
  func onHeadersComplete(parser p: http_parser ) -> Int {
    print("did parse HTTP request head: \(p.method)")
  }
}

As it turns out, this way of implementing the callbacks is actually much more in line in what the original http_parser is doing (its http_parser_settings struct is pretty much the same like a protocol/vtable).

The IncomingMessageParser in the http module has been changed to work as a protocol based parser.

Changes in 0.3.1 (from 0.3.0)

  • global changes
    • compat with Swift 3 Preview 4 on tuxOS & macOS
      • ErrorProtocol is now Error (2.x alias provided in core)
      • UnsafePointer changes
      • xyzLiteralConvertible is now ExpressibleByXYZLiteral (2.x alias provided in core)
      • enum cases must be accessed via .
      • operator funcs are static
      • a few more Objective-GCD changes
      • new POSIXErrorCode vs POSIXError
  • http_parser module
    • switched from closure based http_parser to a protocol based http_parser (faster, more consistent with original)
  • http module
    • use protocol based http_parser
  • tests
    • renamed to match what Swift 3 Preview 6 is expecting (still works with older versions)

Swift 3 Preview 6

What?! You release a Swift 3 Preview 4 version? Don’t you know that Swift 3 Preview 6 is out for quite a while!!

Yes, yes. There are two issues with Swift 3 Preview 6:

  1. We can’t get libdispatch to build with Swift 3 Preview 6 on Ubuntu Trusty. In fact, there isn’t even a preview6 branch of that.
  2. Preview 6 has pretty massive changes which can’t just be typealias‘ed away.

Help wanted: If you got a version of libdispatch working on Trusty, please let us know.

It feels a little like everyone is racing towards the Swift 3 release, including the libdispatch Swift people, which is a good thing. And as part of that race “preview stability” (…) seems to have decreased.

The other issue are two changes in the Swift language in Preview 6:

  1. closures are now @nonescaping by default
  2. public classes cannot be subclassed anymore by other modules, open needs to be used for such

Change 1 is an issue in Noze.io because all the event handlers are naturally @escaping. Which means all of them need to be modified with the @escaping marker - but only for Swift 3 - as Swift 2 doesn’t know that. One way around that is using typealiases for the closure types (and Swift-version those), but that is pretty ugly.

Change 2 is even worse. A public class of a module cannot be subclassed anymore. Instead it needs to be marked open. Tiny change, big consequence: the whole class declaration needs to be copied. Code could be moved to extensions, but again this is ugly.

Anywayz, there is a Swift 3 Preview 6 branch for the port to the new language version. As of today: work-in-progress.

Our recommendation is still the same: Stay with Swift 2.2/2.3 until Swift 3 - particularily Swift 3 libdispatch on Linux - is sufficiently stable.

Swift 3 Release Plan

Looks like we are nearing a Swift 3 final, but it’s still the same old plan:

  • as long as Swift 3 is not released, Swift 2.x is the recommended version and we build with Swift 2 and Swift 3-preview.
  • once Swift 3 is released, we remove Swift 2 support and consolidate the codebase

There is one caveat: Even when Swift 3 is released, Xcode 8 is not supposed to support Swift Package Manager. Since we want to make it easy for the audience, this means that we are going to stick to the “single package with multiple modules” setup (aka Rechargables Included).

That way one only needs to pull a single Noze.io package from GitHub to get going. Note that though that will fetch the full sources, we still build small and focused modules you can selectively link to. You are not required to carry all the cows in your binary!

Getting the stuff

Well, as usual, head over to GitHub and checkout the master branch or fetch the 0.3.1 tag.

Help Wanted

libdispatch on Trusty

If you got a version of libdispatch working on Trusty, please let us know.

Incremental MD5 hasher

A thing we need is an incremental MD5 hasher. Yes we heard about CryptoSwift which looks pretty good. But it seems to lack an incremental MD5 hasher but requires the full input (and we wanna stream!). If you know another (pure Swift) MD5 hasher, please let us know.

hh

Written on August 25, 2016