     // MARK: - Bytes
     /// Copies a number of bytes from the start of the data object into a given buffer.
     open func getBytes(_ buffer: UnsafeMutableRawPointer, length: Int) {
-        let bytePtr = buffer.bindMemory(to: UInt8.self, capacity: length)
-        CFDataGetBytes(_cfObject, CFRangeMake(0, length), bytePtr)
+        if funnelsAreAbstract {
+            let actualCount = Swift.min(length, self.length)
+            let sourceBuffer = UnsafeRawBufferPointer(start: bytes, count: actualCount)
+            let destinationBuffer = UnsafeMutableRawBufferPointer(start: buffer, count: actualCount)
+            sourceBuffer.copyBytes(to: destinationBuffer)
+        } else {
+            let bytePtr = buffer.bindMemory(to: UInt8.self, capacity: length)
+            CFDataGetBytes(_cfObject, CFRangeMake(0, length), bytePtr)
+        }
     }
 
     /// Copies a range of bytes from the data object into a given buffer.
     open func getBytes(_ buffer: UnsafeMutableRawPointer, range: NSRange) {
-        let bytePtr = buffer.bindMemory(to: UInt8.self, capacity: range.length)
-        CFDataGetBytes(_cfObject, CFRangeMake(range.location, range.length), bytePtr)
+        if funnelsAreAbstract {
+            precondition(range.location >= 0 && range.length >= 0)
+            let actualCount = Swift.min(range.length, self.length - range.location)
+            let sourceBuffer = UnsafeRawBufferPointer(start: bytes.advanced(by: range.location), count: actualCount)
+            let destinationBuffer = UnsafeMutableRawBufferPointer(start: buffer, count: actualCount)
+            sourceBuffer.copyBytes(to: destinationBuffer)
+        } else {
+            let bytePtr = buffer.bindMemory(to: UInt8.self, capacity: range.length)
+            CFDataGetBytes(_cfObject, CFRangeMake(range.location, range.length), bytePtr)
+        }
     }
 
     /// Returns a new data object containing the data object's bytes that fall within the limits specified by a given range.


    /// Replaces with a given set of bytes a given range within the contents of the data object.
    open func replaceBytes(in range: NSRange, withBytes replacementBytes: UnsafeRawPointer?, length replacementLength: Int) {
        let bytePtr = replacementBytes?.bindMemory(to: UInt8.self, capacity: replacementLength)
        CFDataReplaceBytes(_cfMutableObject, CFRangeMake(range.location, range.length), bytePtr, replacementLength)
    }
}



    /// Increases the length of the data object by a given number of bytes.
    open func increaseLength(by extraLength: Int) {
        if funnelsAreAbstract {
            self.length += extraLength
        } else {
            CFDataSetLength(_cfMutableObject, CFDataGetLength(_cfObject) + extraLength)
        }
    }

    /// Replaces with a given set of bytes a given range within the contents of the data object.
    open func replaceBytes(in range: NSRange, withBytes bytes: UnsafeRawPointer) {
        if funnelsAreAbstract {
            replaceBytes(in: range, withBytes: bytes, length: range.length)
        } else {
            let bytePtr = bytes.bindMemory(to: UInt8.self, capacity: length)
            CFDataReplaceBytes(_cfMutableObject, CFRangeMake(range.location, range.length), bytePtr, length)
        }
    }

    /// Replaces with zeroes the contents of the data object in a given range.
