let bufferAlignment = 32

@frozen
public struct Buffer<T>: ~Copyable {
    let buffer: UnsafeMutableBufferPointer<T>
    var count: Int { buffer.count }
    var baseAddress: UnsafeMutablePointer<T> { buffer.baseAddress! }

    public init(capacity: Int) {
        buffer = UnsafeMutableRawBufferPointer.allocate(
            byteCount: MemoryLayout<T>.stride * capacity,
            alignment: bufferAlignment
        ).bindMemory(to: T.self)
    }

    deinit {
        buffer.deallocate()
    }

    public func withUnsafeMutableBufferPointer<R>(_ body: (UnsafeMutableBufferPointer<T>) throws -> R) rethrows -> R {
        try body(buffer)
    }

    public func withUnsafeBufferPointer<R>(_ body: (UnsafeBufferPointer<T>) throws -> R) rethrows -> R {
        try body(UnsafeBufferPointer(buffer))
    }

    public func withUnsafeMutableBytes<R>(_ body: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R {
        try body(UnsafeMutableRawBufferPointer(buffer))
    }
}
