blob: 50c363b07720f7216fea1be352b4f6a84072a3b7 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
using System;
using System.Runtime.InteropServices;
using Apache.Arrow.Types;
namespace Apache.Arrow.C
{
/// <summary>
/// An Arrow C Data Interface Schema, which represents a type, field, or schema.
/// </summary>
/// <remarks>
/// This is used to export <see cref="ArrowType"/>, <see cref="Field"/>, or
/// <see cref="Schema"/> to other languages. It matches the layout of the
/// ArrowSchema struct described in https://github.com/apache/arrow/blob/main/cpp/src/arrow/c/abi.h.
/// </remarks>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct CArrowSchema
{
public byte* format;
public byte* name;
public byte* metadata;
public long flags;
public long n_children;
public CArrowSchema** children;
public CArrowSchema* dictionary;
#if NET5_0_OR_GREATER
internal delegate* unmanaged<CArrowSchema*, void> release;
#else
internal IntPtr release;
#endif
public void* private_data;
/// <summary>
/// Allocate and zero-initialize an unmanaged pointer of this type.
/// </summary>
/// <remarks>
/// This pointer must later be freed by <see cref="Free"/>.
/// </remarks>
public static CArrowSchema* Create()
{
var ptr = (CArrowSchema*)Marshal.AllocHGlobal(sizeof(CArrowSchema));
*ptr = default;
return ptr;
}
/// <summary>
/// Free a pointer that was allocated in <see cref="Create"/>.
/// </summary>
/// <remarks>
/// Do not call this on a pointer that was allocated elsewhere.
/// </remarks>
public static void Free(CArrowSchema* schema)
{
if (schema->release != default)
{
// Call release if not already called.
#if NET5_0_OR_GREATER
schema->release(schema);
#else
Marshal.GetDelegateForFunctionPointer<CArrowSchemaExporter.ReleaseArrowSchema>(schema->release)(schema);
#endif
}
Marshal.FreeHGlobal((IntPtr)schema);
}
/// <summary>
/// For dictionary-encoded types, whether the ordering of dictionary indices is semantically meaningful.
/// </summary>
public const long ArrowFlagDictionaryOrdered = 1;
/// <summary>
/// Whether this field is semantically nullable (regardless of whether it actually has null values)
/// </summary>
public const long ArrowFlagNullable = 2;
/// <summary>
/// For map types, whether the keys within each map value are sorted.
/// </summary>
public const long ArrowFlagMapKeysSorted = 4;
/// <summary>
/// Get the value of a particular flag.
/// </summary>
/// <remarks>
/// Known valid flags are <see cref="ArrowFlagDictionaryOrdered" />,
/// <see cref="ArrowFlagNullable" />, and <see cref="ArrowFlagMapKeysSorted" />.
/// </remarks>
public readonly bool GetFlag(long flag)
{
return (flags & flag) == flag;
}
internal readonly CArrowSchema* GetChild(long i)
{
if ((ulong)i >= (ulong)n_children)
{
throw new ArgumentOutOfRangeException("Child index out of bounds.");
}
if (children == null)
{
throw new ArgumentOutOfRangeException($"Child index '{i}' out of bounds.");
}
return children[i];
}
}
}