Ejemplo n.º 1
0
        /// <summary>
        /// Returns a <see cref="SwiftHandle"/> bridging the given object to Swift.
        /// </summary>
        /// <remarks>
        /// The returned <see cref="SwiftHandle"/> must be disposed when no longer needed.
        /// </remarks>
        /// <param name="obj">The managed object to bridge to Swift</param>
        /// <param name="nullability">Determines whether to bridge the value to Swift
        ///  as an Optional value. If <typeparamref name="T"/> is identified as a known
        ///  nullable wrapper, such as <see cref="Nullable"/>, then the value is bridged
        ///  as an Optional regardless of the value of this parameter.</param>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="obj"/> is
        ///	 <c>null</c>, <typeparamref name="T"/> is not a known nullable wrapper type,
        ///	 and <paramref name="nullability"/> returns <c>false</c> from <see cref="Nullability.IsNullable"/>.</exception>
        /// <exception cref="ArgumentException">Thrown when the type <typeparamref name="T"/> cannot
        ///  be directly bridged to Swift</exception>
        public static unsafe SwiftHandle GetSwiftHandle <T> (this T obj, Nullability nullability = default)
        {
            var type      = typeof(T);
            var swiftType = SwiftType.Of(type, nullability);

            if (swiftType == null && obj != null)
            {
                type      = obj.GetType();
                swiftType = SwiftType.Of(type, nullability);
            }
            if (swiftType == null)
            {
                throw new ArgumentException($"Type '{type}' cannot be bridged to Swift");
            }

            // Nullable types are bridged to Swift optionals
            if (nullability.IsNullable || Nullability.IsReifiedNullable(type))
            {
                if (Nullability.IsNull(obj))
                {
                    var underlyingType      = Nullability.GetUnderlyingType(type);
                    var underlyingSwiftType = SwiftType.Of(underlyingType, nullability.Strip()) !;
                    return(Optional.Wrap(null, swiftType, underlyingSwiftType));
                }
                else
                {
                    var unwrapped = Nullability.Unwrap(obj);
                    using (var unwrappedHandle = unwrapped.GetSwiftHandle(nullability.Strip()))
                        return(Optional.Wrap(unwrappedHandle.Pointer, swiftType, unwrappedHandle.SwiftType));
                }
            }
            else if (obj is null)
            {
                throw new ArgumentNullException(nameof(obj));
            }

            return(obj switch {
                ISwiftValue swiftValue => swiftValue.GetSwiftHandle(),
                string val => new SwiftHandle(new Swift.String(val), swiftType, destroyOnDispose: true),
                _ when type.IsPrimitive => new SwiftHandle(obj, swiftType),
                _ => throw new NotImplementedException(type.ToString())
            });