     /// The path of coding keys taken to get to this point in encoding.
     let codingPath: [CodingKey]
     
-    /// A reference to the container we're writing to.
-    let container: PredicateEncoder.Encoder.ItemsContainer
-    
     // MARK: - Initialization
     
-    init(referencing encoder: PredicateEncoder.Encoder,
-         wrapping container: PredicateEncoder.Encoder.ItemsContainer) {
-        
+    init(referencing encoder: PredicateEncoder.Encoder) {
         self.encoder = encoder
         self.codingPath = encoder.codingPath
-        self.container = container
     }
     
     // MARK: - Methods
     
     /// The number of elements encoded into the container.
-    var count: Int {
-        return container.items.count
-    }
-    
-    func encodeNil() throws {
-        // do nothing
-    }
-    
-    func encode(_ value: Bool) throws { append(encoder.box(value)) }
-    
-    func encode(_ value: String) throws { append(encoder.box(value)) }
-    
-    func encode(_ value: Double) throws { append(encoder.boxNumeric(value.bitPattern)) }
-    
-    func encode(_ value: Float) throws { append(encoder.boxNumeric(value.bitPattern)) }
-    
-    func encode(_ value: Int) throws { append(encoder.boxNumeric(Int32(value))) }
-    
-    func encode(_ value: Int8) throws { append(encoder.box(value)) }
-    
-    func encode(_ value: Int16) throws { append(encoder.boxNumeric(value)) }
-    
-    func encode(_ value: Int32) throws { append(encoder.boxNumeric(value)) }
-    
-    func encode(_ value: Int64) throws { append(encoder.boxNumeric(value)) }
-    
-    func encode(_ value: UInt) throws { append(encoder.boxNumeric(UInt32(value))) }
-    
-    func encode(_ value: UInt8) throws { append(encoder.box(value)) }
-    
-    func encode(_ value: UInt16) throws { append(encoder.boxNumeric(value)) }
-    
-    func encode(_ value: UInt32) throws { append(encoder.boxNumeric(value)) }
-    
-    func encode(_ value: UInt64) throws { append(encoder.boxNumeric(value)) }
-    
-    func encode <T: Encodable> (_ value: T) throws { append(try encoder.boxEncodable(value)) }
+    private(set) var count: Int = 0
+    
+    func encodeNil() throws { append(.null) }
+    
+    func encode(_ value: Bool) throws { append(value) }
+    
+    func encode(_ value: String) throws { append(value) }
+    
+    func encode(_ value: Double) throws { append(value) }
+    
+    func encode(_ value: Float) throws { append(value) }
+    
+    func encode(_ value: Int) throws { append(Int64(value)) }
+    
+    func encode(_ value: Int8) throws { append(value) }
+    
+    func encode(_ value: Int16) throws { append(value) }
+    
+    func encode(_ value: Int32) throws { append(value) }
+    
+    func encode(_ value: Int64) throws { append(value) }
+    
+    func encode(_ value: UInt) throws { append(UInt64(value)) }
+    
+    func encode(_ value: UInt8) throws { append(value) }
+    
+    func encode(_ value: UInt16) throws { append(value) }
+    
+    func encode(_ value: UInt32) throws { append(value) }
+    
+    func encode(_ value: UInt64) throws { append(value) }
+    
+    func encode <T: Encodable> (_ value: T) throws {
+        let key = IndexCodingKey(index: count)
+        self.encoder.codingPath.append(key)
+        defer { self.encoder.codingPath.removeLast() }
+        try encoder.writeEncodable(value)
+        count += 1
+    }
     
     func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
-        
         fatalError()
     }
     
     func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
-        
         fatalError()
     }
     
     func superEncoder() -> Encoder {
-        
         fatalError()
     }
     
     // MARK: - Private Methods
     
-    private func append(_ data: Data) {
-        
-        let index = PredicateTypeCode(rawValue: UInt8(count)) // current index
-        let item = PredicateItem(type: index, value: data)
-        
-        // write
-        self.container.append(item) // already sorted
-    }
-}
+    private func append<T: PredicateValue>(_ value: T) {
+        append(value.predicateValue)
+    }
+    
+    private func append(_ value: Value) {
+        let key = IndexCodingKey(index: count)
+        self.encoder.codingPath.append(key)
+        defer { self.encoder.codingPath.removeLast() }
+        encoder.write(value)
+        count += 1
+    }
+}
+
+internal struct IndexCodingKey: CodingKey, Equatable, Hashable {
+    
+    let index: Int
+    
+    init(index: Int) {
+        self.index = index
+    }
+    
+    var stringValue: String {
+        return index.description
+    }
+    
+    init?(stringValue: String) {
+        guard let index = UInt(stringValue)
+            else { return nil }
+        self.init(index: Int(index))
+    }
+    
+    var intValue: Int? {
+        return index
+    }
+    
+    init?(intValue: Int) {
+        self.init(index: intValue)
+    }
+}

    public func encode <T: Encodable> (_ value: T) throws -> PredicateContext {
    
        log?("Will encode \(String(reflecting: T.self))")
        
        fatalError()
    }
}


        
        self.encoder.codingPath.append(key)
        defer { self.encoder.codingPath.removeLast() }
        try encoder.writeEncodable(value)
    }
    
    func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: K) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
