   }
 }
 
+//===----------------------------------------------------------------------===//
+//===--- UTF-16 Decoders --------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+public protocol _UTF16Decoder : _UTFDecoder where CodeUnit == UTF16.CodeUnit {
+  var buffer: Buffer { get set }
+  static var _surrogatePattern : UInt32 { get }
+}
+
+extension _UTF16Decoder {
+  public static var replacement : EncodedScalar {
+    return EncodedScalar(_storage: 0xFFFD, _bitCount: 16)
+  }
+  public static func _isScalar(_ x: CodeUnit) -> Bool {
+    return x & 0xf800 != 0xd800
+  }
+  public // @testable
+  func _parseMultipleCodeUnits() -> (isValid: Bool, bitCount: UInt8) {
+    _sanityCheck(  // this case handled elsewhere
+      !Self._isScalar(UInt16(extendingOrTruncating: buffer._storage)))
+    
+    if _fastPath(buffer._storage & 0xFC00_FC00 == Self._surrogatePattern) {
+      return (true, 2*16)
+    }
+    return (false, 1*16)
+  }
+}
+
+extension Unicode.UTF16 : UnicodeEncoding {
+  public struct ForwardDecoder {
+    public typealias Buffer = _UIntBuffer<UInt32, UInt16>
+    public init() { buffer = Buffer() }
+    public var buffer: Buffer
+  }
+  
+  public struct ReverseDecoder {
+    public typealias Buffer = _UIntBuffer<UInt32, UInt16>
+    public init() { buffer = Buffer() }
+    public var buffer: Buffer
+  }
+}
+
+extension UTF16.ReverseDecoder : _UTF16Decoder {
+  public typealias CodeUnit = UInt16
+  public typealias EncodedScalar = Buffer
+
+  public static var _surrogatePattern : UInt32 { return 0xD800_DC00 }
+  
+  public static func decodeOne(_ source: EncodedScalar) -> UnicodeScalar {
+    let bits = source._storage
+    if _fastPath(source._bitCount == 16) {
+      return UnicodeScalar(_unchecked: bits & 0xffff)
+    }
+    _sanityCheck(source._bitCount == 32)
+    let value = 0x10000 + ((bits & 0x03ff0000) &>> 6 | (bits & 0x03ff))
+    return UnicodeScalar(_unchecked: value)
+  }  
+}
+
+extension Unicode.UTF16.ForwardDecoder : _UTF16Decoder {
+  public typealias CodeUnit = UInt16
+  public typealias EncodedScalar = Buffer
+  
+  public static var _surrogatePattern : UInt32 { return 0xDC00_D800 }
+  
+  public static func decodeOne(_ source: EncodedScalar) -> UnicodeScalar {
+    let bits = source._storage
+    if _fastPath(source._bitCount == 16) {
+      return UnicodeScalar(_unchecked: bits & 0xffff)
+    }
+    _sanityCheck(source._bitCount == 32)
+    let value = 0x10000 + (bits >> 16 & 0x03ff | (bits & 0x03ff) << 10)
+    return UnicodeScalar(_unchecked: value)
+  }  
+}
+
 #if !BENCHMARK
 //===--- testing ----------------------------------------------------------===//
 import StdlibUnittest

  var buffer: Buffer { get set }
}

public protocol _UTF8Decoder : _UTFDecoder {
  var buffer: Buffer { get set }
}

extension _UTF8Decoder {
  public static func _isScalar(_ x: CodeUnit) -> Bool { return x & 0x80 == 0 }
}

extension _UTFDecoder {
  public mutating func parseOne<I : IteratorProtocol>(
    _ input: inout I
  ) -> Unicode.ParseResult<EncodedScalar>
    where I.Element == CodeUnit {

    // Bufferless ASCII fastpath.
    if _fastPath(buffer.isEmpty) {
      guard let codeUnit = input.next() else { return .emptyInput }
      // ASCII, return immediately.

      }
      // Non-ASCII, proceed to buffering mode.
      buffer.append(codeUnit)
    } else if Self._isScalar(CodeUnit(extendingOrTruncating: buffer._storage)) {
      // ASCII in buffer.  We don't refill the buffer so we can return
      // to bufferless mode once we've exhausted it.
      let codeUnit = CodeUnit(extendingOrTruncating: buffer._storage)
