// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Text;
using Regorus.Internal;
#nullable enable
namespace Regorus
{
///
/// Provides static methods for managing the global resource schema registry.
/// Resource schemas define the structure and validation rules for Azure Policy resources.
///
public static unsafe class SchemaRegistry
{
///
/// Register a resource schema from JSON with a given name.
///
/// Name to register the schema under
/// JSON string representing the schema
/// Thrown when schema registration fails
public static void RegisterResource(string name, string schemaJson)
{
Utf8Marshaller.WithUtf8(name, namePtr =>
{
Utf8Marshaller.WithUtf8(schemaJson, schemaPtr =>
{
unsafe
{
CheckAndDropResult(Internal.API.regorus_resource_schema_register((byte*)namePtr, (byte*)schemaPtr));
}
});
});
}
///
/// Check if a resource schema with the given name exists.
///
/// Name of the schema to check
/// True if the schema exists, false otherwise
/// Thrown when the operation fails
public static bool ContainsResource(string name)
{
return Utf8Marshaller.WithUtf8(name, namePtr =>
{
unsafe
{
var result = Internal.API.regorus_resource_schema_contains((byte*)namePtr);
return GetBoolResult(result);
}
});
}
///
/// Get the number of registered resource schemas.
///
/// The number of registered resource schemas
/// Thrown when the operation fails
public static long ResourceCount
{
get
{
var result = Internal.API.regorus_resource_schema_len();
return GetIntResult(result);
}
}
///
/// Check if the resource schema registry is empty.
///
/// True if the registry is empty, false otherwise
/// Thrown when the operation fails
public static bool IsResourceRegistryEmpty
{
get
{
var result = Internal.API.regorus_resource_schema_is_empty();
return GetBoolResult(result);
}
}
///
/// List all registered resource schema names.
///
/// JSON array of schema names
/// Thrown when the operation fails
public static string ListResourceNames()
{
return CheckAndDropResult(Internal.API.regorus_resource_schema_list_names()) ?? "[]";
}
///
/// Remove a resource schema by name.
///
/// Name of the schema to remove
/// True if the schema was removed, false if it wasn't found
/// Thrown when the operation fails
public static bool RemoveResource(string name)
{
return Utf8Marshaller.WithUtf8(name, namePtr =>
{
unsafe
{
var result = Internal.API.regorus_resource_schema_remove((byte*)namePtr);
return GetBoolResult(result);
}
});
}
///
/// Clear all resource schemas from the registry.
///
/// Thrown when the operation fails
public static void ClearResources()
{
CheckAndDropResult(Internal.API.regorus_resource_schema_clear());
}
///
/// Register an effect schema from JSON with a given name.
///
/// Name to register the schema under
/// JSON string representing the schema
/// Thrown when schema registration fails
public static void RegisterEffect(string name, string schemaJson)
{
Utf8Marshaller.WithUtf8(name, namePtr =>
{
Utf8Marshaller.WithUtf8(schemaJson, schemaPtr =>
{
unsafe
{
CheckAndDropResult(Internal.API.regorus_effect_schema_register((byte*)namePtr, (byte*)schemaPtr));
}
});
});
}
///
/// Check if an effect schema with the given name exists.
///
/// Name of the schema to check
/// True if the schema exists, false otherwise
/// Thrown when the operation fails
public static bool ContainsEffect(string name)
{
return Utf8Marshaller.WithUtf8(name, namePtr =>
{
unsafe
{
var result = Internal.API.regorus_effect_schema_contains((byte*)namePtr);
return GetBoolResult(result);
}
});
}
///
/// Get the number of registered effect schemas.
///
/// The number of registered effect schemas
/// Thrown when the operation fails
public static long EffectCount
{
get
{
var result = Internal.API.regorus_effect_schema_len();
return GetIntResult(result);
}
}
///
/// Check if the effect schema registry is empty.
///
/// True if the registry is empty, false otherwise
/// Thrown when the operation fails
public static bool IsEffectRegistryEmpty
{
get
{
var result = Internal.API.regorus_effect_schema_is_empty();
return GetBoolResult(result);
}
}
///
/// List all registered effect schema names.
///
/// JSON array of schema names
/// Thrown when the operation fails
public static string ListEffectNames()
{
return CheckAndDropResult(Internal.API.regorus_effect_schema_list_names()) ?? "[]";
}
///
/// Remove an effect schema by name.
///
/// Name of the schema to remove
/// True if the schema was removed, false if it wasn't found
/// Thrown when the operation fails
public static bool RemoveEffect(string name)
{
return Utf8Marshaller.WithUtf8(name, namePtr =>
{
unsafe
{
var result = Internal.API.regorus_effect_schema_remove((byte*)namePtr);
return GetBoolResult(result);
}
});
}
///
/// Clear all effect schemas from the registry.
///
/// Thrown when the operation fails
public static void ClearEffects()
{
CheckAndDropResult(Internal.API.regorus_effect_schema_clear());
}
private static string? StringFromUTF8(IntPtr ptr)
{
#if NETSTANDARD2_1
return System.Runtime.InteropServices.Marshal.PtrToStringUTF8(ptr);
#else
int len = 0;
while (System.Runtime.InteropServices.Marshal.ReadByte(ptr, len) != 0) { ++len; }
byte[] buffer = new byte[len];
System.Runtime.InteropServices.Marshal.Copy(ptr, buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
#endif
}
private static string? CheckAndDropResult(Internal.RegorusResult result)
{
try
{
if (result.status != Internal.RegorusStatus.Ok)
{
var message = StringFromUTF8((IntPtr)result.error_message);
throw new Exception(message ?? "Unknown error occurred");
}
return result.data_type switch
{
Internal.RegorusDataType.String => StringFromUTF8((IntPtr)result.output),
Internal.RegorusDataType.Boolean => result.bool_value.ToString().ToLowerInvariant(),
Internal.RegorusDataType.Integer => result.int_value.ToString(),
Internal.RegorusDataType.None => null,
_ => StringFromUTF8((IntPtr)result.output)
};
}
finally
{
Internal.API.regorus_result_drop(result);
}
}
private static bool GetBoolResult(Internal.RegorusResult result)
{
try
{
if (result.status != Internal.RegorusStatus.Ok)
{
var message = StringFromUTF8((IntPtr)result.error_message);
throw new Exception(message ?? "Unknown error occurred");
}
return result.data_type == Internal.RegorusDataType.Boolean ? result.bool_value : false;
}
finally
{
Internal.API.regorus_result_drop(result);
}
}
private static long GetIntResult(Internal.RegorusResult result)
{
try
{
if (result.status != Internal.RegorusStatus.Ok)
{
var message = StringFromUTF8((IntPtr)result.error_message);
throw new Exception(message ?? "Unknown error occurred");
}
return result.data_type == Internal.RegorusDataType.Integer ? result.int_value : 0;
}
finally
{
Internal.API.regorus_result_drop(result);
}
}
}
}