//===--- ManagedBuffer.swift - variable-sized buffer of aligned memory ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import SwiftShims

/// A class whose instances contain a property of type `Header` and raw
/// storage for an array of `Element`, whose size is determined at
/// instance creation.
///
/// Note that the `Element` array is suitably-aligned **raw memory**.
/// You are expected to construct and---if necessary---destroy objects
/// there yourself, using the APIs on `UnsafeMutablePointer<Element>`.
/// Typical usage stores a count and capacity in `Header` and destroys
/// any live elements in the `deinit` of a subclass.
/// - Note: Subclasses must not have any stored properties; any storage
///   needed should be included in `Header`.
open class ManagedBuffer<Header, Element> {

  /// Create a new instance of the most-derived class, calling
  /// `factory` on the partially-constructed object to generate
  /// an initial `Header`.
  public final class func create(
    minimumCapacity: Int,
    makingHeaderWith factory: (
      ManagedBuffer<Header, Element>) throws -> Header
  ) rethrows -> ManagedBuffer<Header, Element> {

    let p = try ManagedBufferPointer<Header, Element>(
      bufferClass: self,
      minimumCapacity: minimumCapacity,
      makingHeaderWith: { buffer, _ in
        try factory(
          unsafeDowncast(buffer, to: ManagedBuffer<Header, Element>.self))
      })

    return unsafeDowncast(p.buffer, to: ManagedBuffer<Header, Element>.self)
  }

  /// Destroy the stored Header.
  deinit {
    ManagedBufferPointer(self).withUnsafeMutablePointerToHeader {
      _ = $0.deinitialize()
    }
  }

  /// The actual number of elements that can be stored in this object.
  ///
  /// This header may be nontrivial to compute; it is usually a good
  /// idea to store this information in the "header" area when
  /// an instance is created.
  public final var capacity: Int {
    let p = ManagedBufferPointer<Header, Element>(self)
    return p.capacity
  }

  /// Call `body` with an `UnsafeMutablePointer` to the stored
  /// `Header`.
  ///
  /// - Note: This pointer is only valid for the duration of the
  ///   call to `body`.
  public final func withUnsafeMutablePointerToHeader<R>(
    _ body: (UnsafeMutablePointer<Header>) throws -> R
  ) rethrows -> R {
    return try withUnsafeMutablePointers { (v, e) in return try body(v) }
  }

  /// Call `body` with an `UnsafeMutablePointer` to the `Element`
  /// storage.
  ///
  /// - Note: This pointer is only valid for the duration of the
  ///   call to `body`.
  public final func withUnsafeMutablePointerToElements<R>(
    _ body: (UnsafeMutablePointer<Element>) throws -> R
  ) rethrows -> R {
    return try withUnsafeMutablePointers { return try body($0.1) }
  }

  /// Call `body` with `UnsafeMutablePointer`s to the stored `Header`
  /// and raw `Element` storage.
  ///
  /// - Note: These pointers are only valid for the duration of the
  ///   call to `body`.
  public final func withUnsafeMutablePointers<R>(
    _ body: (UnsafeMutablePointer<Header>, UnsafeMutablePointer<Element>) throws -> R
  ) rethrows -> R {
    return try ManagedBufferPointer(self).withUnsafeMutablePointers(body)
  }

  /// The stored `Header` instance.
  ///
  /// During instance creation, in particular during
  /// `ManagedBuffer.create`'s call to initialize, `ManagedBuffer`'s
  /// `header` property is as-yet uninitialized, and therefore
  /// reading the `header` property during `ManagedBuffer.create` is undefined.
  public final var header: Header {
    addressWithNativeOwner {
      return (
        ManagedBufferPointer(self).withUnsafeMutablePointerToHeader {
          UnsafePointer($0)
        },
        Builtin.castToNativeObject(self))
    }
    mutableAddressWithNativeOwner {
      return (
        ManagedBufferPointer(self).withUnsafeMutablePointerToHeader { $0 },
        Builtin.castToNativeObject(self))
    }
  }

  //===--- internal/private API -------------------------------------------===//

  /// Make ordinary initialization unavailable
  internal init(_doNotCallMe: ()) {
    _sanityCheckFailure("Only initialize these by calling create")
  }
}

/// Contains a buffer object, and provides access to an instance of
/// `Header` and contiguous storage for an arbitrary number of
/// `Element` instances stored in that buffer.
///
/// For most purposes, the `ManagedBuffer` class works fine for this
/// purpose, and can simply be used on its own.  However, in cases
/// where objects of various different classes must serve as storage,
/// `ManagedBufferPointer` is needed.
///
/// A valid buffer class is non-`@objc`, with no declared stored
///   properties.  Its `deinit` must destroy its
///   stored `Header` and any constructed `Element`s.
///
/// Example Buffer Class
/// --------------------
///
///      class MyBuffer<Element> { // non-@objc
///        typealias Manager = ManagedBufferPointer<(Int, String), Element>
///        deinit {
///          Manager(unsafeBufferObject: self).withUnsafeMutablePointers {
///            (pointerToHeader, pointerToElements) -> Void in
///            pointerToElements.deinitialize(count: self.count)
///            pointerToHeader.deinitialize()
///          }
///        }
///
///        // All properties are *computed* based on members of the Header
///        var count: Int {
///          return Manager(unsafeBufferObject: self).header.0
///        }
///        var name: String {
///          return Manager(unsafeBufferObject: self).header.1
///        }
///      }
///
@_fixed_layout
public struct ManagedBufferPointer<Header, Element> : Equatable {

  /// Create with new storage containing an initial `Header` and space
  /// for at least `minimumCapacity` `element`s.
  ///
  /// - parameter bufferClass: The class of the object used for storage.
  /// - parameter minimumCapacity: The minimum number of `Element`s that
  ///   must be able to be stored in the new buffer.
  /// - parameter factory: A function that produces the initial
  ///   `Header` instance stored in the buffer, given the `buffer`
  ///   object and a function that can be called on it to get the actual
  ///   number of allocated elements.
  ///
  /// - Precondition: `minimumCapacity >= 0`, and the type indicated by
  ///   `bufferClass` is a non-`@objc` class with no declared stored
  ///   properties.  The `deinit` of `bufferClass` must destroy its
  ///   stored `Header` and any constructed `Element`s.
  public init(
    bufferClass: AnyClass,
    minimumCapacity: Int,
    makingHeaderWith factory:
      (_ buffer: AnyObject, _ capacity: (AnyObject) -> Int) throws -> Header
  ) rethrows {
    self = ManagedBufferPointer(
      bufferClass: bufferClass, minimumCapacity: minimumCapacity)

    // initialize the header field
    try withUnsafeMutablePointerToHeader {
      $0.initialize(to: 
        try factory(
          self.buffer,
          {
            ManagedBufferPointer(unsafeBufferObject: $0).capacity
          }))
    }
    // FIXME: workaround for <rdar://problem/18619176>.  If we don't
    // access header somewhere, its addressor gets linked away
    _ = header
  }

  /// Manage the given `buffer`.
  ///
  /// - Precondition: `buffer` is an instance of a non-`@objc` class whose
  ///   `deinit` destroys its stored `Header` and any constructed `Element`s.
  public init(unsafeBufferObject buffer: AnyObject) {
    ManagedBufferPointer._checkValidBufferClass(type(of: buffer))

    self._nativeBuffer = Builtin.castToNativeObject(buffer)
  }

  /// Internal version for use by _ContiguousArrayBuffer where we know that we
  /// have a valid buffer class.
  /// This version of the init function gets called from
  ///  _ContiguousArrayBuffer's deinit function. Since 'deinit' does not get
  /// specialized with current versions of the compiler, we can't get rid of the
  /// _debugPreconditions in _checkValidBufferClass for any array. Since we know
  /// for the _ContiguousArrayBuffer that this check must always succeed we omit
  /// it in this specialized constructor.
  @_versioned
  internal init(_uncheckedUnsafeBufferObject buffer: AnyObject) {
    ManagedBufferPointer._sanityCheckValidBufferClass(type(of: buffer))
    self._nativeBuffer = Builtin.castToNativeObject(buffer)
  }

  /// The stored `Header` instance.
  public var header: Header {
    addressWithNativeOwner {
      return (UnsafePointer(_headerPointer), _nativeBuffer)
    }
    mutableAddressWithNativeOwner {
      return (_headerPointer, _nativeBuffer)
    }
  }

  /// Returns the object instance being used for storage.
  public var buffer: AnyObject {
    return Builtin.castFromNativeObject(_nativeBuffer)
  }

  /// The actual number of elements that can be stored in this object.
  ///
  /// This value may be nontrivial to compute; it is usually a good
  /// idea to store this information in the "header" area when
  /// an instance is created.
  public var capacity: Int {
    return (_capacityInBytes &- _My._elementOffset) / MemoryLayout<Element>.stride
  }

  /// Call `body` with an `UnsafeMutablePointer` to the stored
  /// `Header`.
  ///
  /// - Note: This pointer is only valid
  ///   for the duration of the call to `body`.
  public func withUnsafeMutablePointerToHeader<R>(
    _ body: (UnsafeMutablePointer<Header>) throws -> R
  ) rethrows -> R {
    return try withUnsafeMutablePointers { (v, e) in return try body(v) }
  }

  /// Call `body` with an `UnsafeMutablePointer` to the `Element`
  /// storage.
  ///
  /// - Note: This pointer is only valid for the duration of the
  ///   call to `body`.
  public func withUnsafeMutablePointerToElements<R>(
    _ body: (UnsafeMutablePointer<Element>) throws -> R
  ) rethrows -> R {
    return try withUnsafeMutablePointers { return try body($0.1) }
  }

  /// Call `body` with `UnsafeMutablePointer`s to the stored `Header`
  /// and raw `Element` storage.
  ///
  /// - Note: These pointers are only valid for the duration of the
  ///   call to `body`.
  public func withUnsafeMutablePointers<R>(
    _ body: (UnsafeMutablePointer<Header>, UnsafeMutablePointer<Element>) throws -> R
  ) rethrows -> R {
    defer { _fixLifetime(_nativeBuffer) }
    return try body(_headerPointer, _elementPointer)
  }

  /// Returns `true` iff `self` holds the only strong reference to its buffer.
  ///
  /// See `isUniquelyReferenced` for details.
  public mutating func isUniqueReference() -> Bool {
    return _isUnique(&_nativeBuffer)
  }

  //===--- internal/private API -------------------------------------------===//

  /// Create with new storage containing space for an initial `Header`
  /// and at least `minimumCapacity` `element`s.
  ///
  /// - parameter bufferClass: The class of the object used for storage.
  /// - parameter minimumCapacity: The minimum number of `Element`s that
  ///   must be able to be stored in the new buffer.
  ///
  /// - Precondition: `minimumCapacity >= 0`, and the type indicated by
  ///   `bufferClass` is a non-`@objc` class with no declared stored
  ///   properties.  The `deinit` of `bufferClass` must destroy its
  ///   stored `Header` and any constructed `Element`s.
  internal init(
    bufferClass: AnyClass,
    minimumCapacity: Int
  ) {
    ManagedBufferPointer._checkValidBufferClass(bufferClass, creating: true)
    _precondition(
      minimumCapacity >= 0,
      "ManagedBufferPointer must have non-negative capacity")

    self.init(
      _uncheckedBufferClass: bufferClass, minimumCapacity: minimumCapacity)
  }

  /// Internal version for use by _ContiguousArrayBuffer.init where we know that
  /// we have a valid buffer class and that the capacity is >= 0.
  @_versioned
  internal init(
    _uncheckedBufferClass: AnyClass,
    minimumCapacity: Int
  ) {
    ManagedBufferPointer._sanityCheckValidBufferClass(_uncheckedBufferClass, creating: true)
    _sanityCheck(
      minimumCapacity >= 0,
      "ManagedBufferPointer must have non-negative capacity")

    let totalSize = _My._elementOffset
      +  minimumCapacity * MemoryLayout<Element>.stride

    let newBuffer: AnyObject = _swift_bufferAllocate(
      bufferType: _uncheckedBufferClass,
      size: totalSize,
      alignmentMask: _My._alignmentMask)

    self._nativeBuffer = Builtin.castToNativeObject(newBuffer)
  }

  /// Manage the given `buffer`.
  ///
  /// - Note: It is an error to use the `header` property of the resulting
  ///   instance unless it has been initialized.
  internal init(_ buffer: ManagedBuffer<Header, Element>) {
    _nativeBuffer = Builtin.castToNativeObject(buffer)
  }

  internal typealias _My = ManagedBufferPointer

  internal static func _checkValidBufferClass(
    _ bufferClass: AnyClass, creating: Bool = false
  ) {
    _debugPrecondition(
      _class_getInstancePositiveExtentSize(bufferClass) == MemoryLayout<_HeapObject>.size
      || (
        !creating
        && _class_getInstancePositiveExtentSize(bufferClass)
          == _headerOffset + MemoryLayout<Header>.size),
      "ManagedBufferPointer buffer class has illegal stored properties"
    )
    _debugPrecondition(
      _usesNativeSwiftReferenceCounting(bufferClass),
      "ManagedBufferPointer buffer class must be non-@objc"
    )
  }

  internal static func _sanityCheckValidBufferClass(
    _ bufferClass: AnyClass, creating: Bool = false
  ) {
    _sanityCheck(
      _class_getInstancePositiveExtentSize(bufferClass) == MemoryLayout<_HeapObject>.size
      || (
        !creating
        && _class_getInstancePositiveExtentSize(bufferClass)
          == _headerOffset + MemoryLayout<Header>.size),
      "ManagedBufferPointer buffer class has illegal stored properties"
    )
    _sanityCheck(
      _usesNativeSwiftReferenceCounting(bufferClass),
      "ManagedBufferPointer buffer class must be non-@objc"
    )
  }

  /// The required alignment for allocations of this type, minus 1
  internal static var _alignmentMask: Int {
    return max(
      MemoryLayout<_HeapObject>.alignment,
      max(MemoryLayout<Header>.alignment, MemoryLayout<Element>.alignment)) &- 1
  }

  /// The actual number of bytes allocated for this object.
  internal var _capacityInBytes: Int {
    return _swift_stdlib_malloc_size(_address)
  }

  /// The address of this instance in a convenient pointer-to-bytes form
  internal var _address: UnsafeMutableRawPointer {
    return UnsafeMutableRawPointer(Builtin.bridgeToRawPointer(_nativeBuffer))
  }

  /// Offset from the allocated storage for `self` to the stored `Header`
  internal static var _headerOffset: Int {
    _onFastPath()
    return _roundUp(
      MemoryLayout<_HeapObject>.size,
      toAlignment: MemoryLayout<Header>.alignment)
  }

  /// An **unmanaged** pointer to the storage for the `Header`
  /// instance.  Not safe to use without _fixLifetime calls to
  /// guarantee it doesn't dangle
  internal var _headerPointer: UnsafeMutablePointer<Header> {
    _onFastPath()
    return (_address + _My._headerOffset).assumingMemoryBound(
      to: Header.self)
  }

  /// An **unmanaged** pointer to the storage for `Element`s.  Not
  /// safe to use without _fixLifetime calls to guarantee it doesn't
  /// dangle.
  internal var _elementPointer: UnsafeMutablePointer<Element> {
    _onFastPath()
    return (_address + _My._elementOffset).assumingMemoryBound(
      to: Element.self)
  }

  /// Offset from the allocated storage for `self` to the `Element` storage
  internal static var _elementOffset: Int {
    _onFastPath()
    return _roundUp(
      _headerOffset + MemoryLayout<Header>.size,
      toAlignment: MemoryLayout<Element>.alignment)
  }

  internal mutating func _isUniqueOrPinnedReference() -> Bool {
    return _isUniqueOrPinned(&_nativeBuffer)
  }

  internal var _nativeBuffer: Builtin.NativeObject
}

public func == <Header, Element>(
  lhs: ManagedBufferPointer<Header, Element>,
  rhs: ManagedBufferPointer<Header, Element>
) -> Bool {
  return lhs._address == rhs._address
}

// FIXME: when our calling convention changes to pass self at +0,
// inout should be dropped from the arguments to these functions.

/// Returns a Boolean value indicating whether the given object is a
/// class instance known to have a single strong reference.
///
/// The `isKnownUniquelyReferenced(_:)` function is useful for implementating
/// the copy-on-write optimization for the deep storage of value types:
///
///     mutating func modifyMe(_ arg: X) {
///         if isKnownUniquelyReferenced(&myStorage) {
///             myStorage.modifyInPlace(arg)
///         } else {
///             myStorage = self.createModified(myStorage, arg)
///         }
///     }
///
/// Weak references do not affect the result of this function.
///
/// This function is safe to use for mutating functions in multithreaded code
/// because a false positive implies that there is already a user-level data
/// race on the value being mutated.
///
/// - Parameter object: An instance of a class. This function does *not* modify
///   `object`; the use of `inout` is an implementation artifact.
/// - Returns: `true` if `object` is a known to have a
///   single strong reference; otherwise, `false`.
public func isKnownUniquelyReferenced<T : AnyObject>(_ object: inout T) -> Bool
{
  return _isUnique(&object)
}

internal func _isKnownUniquelyReferencedOrPinned<T : AnyObject>(_ object: inout T) -> Bool {
  return _isUniqueOrPinned(&object)
}

/// Returns a Boolean value indicating whether the given object is a
/// class instance known to have a single strong reference.
///
/// The `isKnownUniquelyReferenced(_:)` function is useful for implementating
/// the copy-on-write optimization for the deep storage of value types:
///
///     mutating func modifyMe(_ arg: X) {
///         if isKnownUniquelyReferenced(&myStorage) {
///             myStorage.modifyInPlace(arg)
///         } else {
///             myStorage = self.createModified(myStorage, arg)
///         }
///     }
///
/// Weak references do not affect the result of this function.
///
/// This function is safe to use for mutating functions in multithreaded code
/// because a false positive implies that there is already a user-level data
/// race on the value being mutated.
///
/// - Parameter object: An instance of a class. This function does *not* modify
///   `object`; the use of `inout` is an implementation artifact.
/// - Returns: `true` if `object` is a known to have a
///   single strong reference; otherwise, `false`. If `object` is `nil`, the
///   return value is `false`.
public func isKnownUniquelyReferenced<T : AnyObject>(
  _ object: inout T?
) -> Bool {
  return _isUnique(&object)
}

extension ManagedBufferPointer {
  @available(*, unavailable, renamed: "capacity")
  public var allocatedElementCount: Int {
    Builtin.unreachable()
  }

  @available(*, unavailable, renamed: "isUniqueReference")
  public mutating func holdsUniqueReference() -> Bool {
    Builtin.unreachable()
  }

  @available(*, unavailable, message: "this API is no longer available")
  public mutating func holdsUniqueOrPinnedReference() -> Bool {
    Builtin.unreachable()
  }
}

@available(*, unavailable, renamed: "isKnownUniquelyReferenced")
public func isUniquelyReferenced<T>(
  _ object: inout T
) -> Bool {
  Builtin.unreachable()
}

@available(*, unavailable, message: "use isKnownUniquelyReferenced instead")
public class NonObjectiveCBase {}


@available(*, unavailable, renamed: "isKnownUniquelyReferenced")
public func isUniquelyReferencedNonObjC<T : AnyObject>(
_ object: inout T
) -> Bool {
  Builtin.unreachable()
}

@available(*, unavailable, renamed: "isKnownUniquelyReferenced")
public func isUniquelyReferencedNonObjC<T : AnyObject>(
  _ object: inout T?
) -> Bool {
  Builtin.unreachable()
}
