     }
 
     init(protobuf: Data) throws {
-        self.init()
-        if !protobuf.isEmpty {
-            try protobuf.withUnsafeBytes { (pointer: UnsafePointer<UInt8>) in
-                let bufferPointer = UnsafeBufferPointer<UInt8>(start: pointer, count: protobuf.count)
-                try decodeIntoSelf(protobuf: bufferPointer, extensions: nil)
-            }
-        }
+        try self.init(protobuf: protobuf, extensions: nil)
     }
 
     init(protobufBuffer: UnsafeBufferPointer<UInt8>) throws {
-        self.init()
-        try decodeIntoSelf(protobuf: protobufBuffer, extensions: nil)
-    }
-}
-
-/// Proto2 messages preserve unknown fields and support extensions
-public extension Proto2Message {
-    init(protobuf: Data, extensions: ExtensionSet? = nil) throws {
+        try self.init(protobufBuffer: protobufBuffer, extensions: nil)
+    }
+
+    init(protobuf: Data, extensions: ExtensionSet?) throws {
         self.init()
         if !protobuf.isEmpty {
             try protobuf.withUnsafeBytes { (pointer: UnsafePointer<UInt8>) in

        }
    }

    init(protobufBuffer: UnsafeBufferPointer<UInt8>, extensions: ExtensionSet? = nil) throws {
        self.init()
        try decodeIntoSelf(protobuf: protobufBuffer, extensions: extensions)
    }

    public mutating func decodeIntoSelf(protobuf bufferPointer: UnsafeBufferPointer<UInt8>, extensions: ExtensionSet?) throws {
        var protobufDecoder = ProtobufDecoder(protobufPointer: bufferPointer, extensions: extensions)
        try protobufDecoder.decodeFullObject(message: &self)

    }
}

// Proto3 messages ignore unknown fields
public extension Proto3Message {
    public mutating func decodeIntoSelf(protobuf bufferPointer: UnsafeBufferPointer<UInt8>, extensions: ExtensionSet?) throws {
        var protobufDecoder = ProtobufDecoder(protobufPointer: bufferPointer, extensions: extensions)
