aboutsummaryrefslogtreecommitdiff
path: root/lib/VNLib.Plugins.Extensions.Loading/src
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-07-15 19:05:01 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2024-07-15 19:05:01 -0400
commitc8567e58dc1d4135da1f6cefa6fa66af5fcd7b19 (patch)
treedb44b1f41544953c89bde723b3a3ef2dc9fb5c8c /lib/VNLib.Plugins.Extensions.Loading/src
parent640ee6760c07b628529e3160c16641773c76e800 (diff)
feat: Smiplify configuration helpers
Diffstat (limited to 'lib/VNLib.Plugins.Extensions.Loading/src')
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/Configuration/ConfigScope.cs28
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs85
-rw-r--r--lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs5
3 files changed, 92 insertions, 26 deletions
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/Configuration/ConfigScope.cs b/lib/VNLib.Plugins.Extensions.Loading/src/Configuration/ConfigScope.cs
index 7f5c09c..d8f4347 100644
--- a/lib/VNLib.Plugins.Extensions.Loading/src/Configuration/ConfigScope.cs
+++ b/lib/VNLib.Plugins.Extensions.Loading/src/Configuration/ConfigScope.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2023 Vaughn Nugent
+* Copyright (c) 2024 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Extensions.Loading
@@ -29,13 +29,15 @@ using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+using VNLib.Utils.Resources;
+
namespace VNLib.Plugins.Extensions.Loading
{
internal sealed class ConfigScope: IConfigScope
{
- private readonly Lazy<IReadOnlyDictionary<string, JsonElement>> _config;
+ private readonly LazyInitializer<IReadOnlyDictionary<string, JsonElement>> _config;
private readonly JsonElement _element;
@@ -48,36 +50,40 @@ namespace VNLib.Plugins.Extensions.Loading
private IReadOnlyDictionary<string, JsonElement> LoadTable()
{
- return _element.EnumerateObject().ToDictionary(static k => k.Name, static k => k.Value);
+ return _element.EnumerateObject()
+ .ToDictionary(
+ static k => k.Name,
+ static k => k.Value
+ );
}
///<inheritdoc/>
- public JsonElement this[string key] => _config.Value[key];
+ public JsonElement this[string key] => _config.Instance[key];
///<inheritdoc/>
- public IEnumerable<string> Keys => _config.Value.Keys;
+ public IEnumerable<string> Keys => _config.Instance.Keys;
///<inheritdoc/>
- public IEnumerable<JsonElement> Values => _config.Value.Values;
+ public IEnumerable<JsonElement> Values => _config.Instance.Values;
///<inheritdoc/>
- public int Count => _config.Value.Count;
+ public int Count => _config.Instance.Count;
///<inheritdoc/>
public string ScopeName { get; }
///<inheritdoc/>
- public bool ContainsKey(string key) => _config.Value.ContainsKey(key);
+ public bool ContainsKey(string key) => _config.Instance.ContainsKey(key);
///<inheritdoc/>
public T Deserialze<T>() => _element.Deserialize<T>()!;
///<inheritdoc/>
- public IEnumerator<KeyValuePair<string, JsonElement>> GetEnumerator() => _config.Value.GetEnumerator();
+ public IEnumerator<KeyValuePair<string, JsonElement>> GetEnumerator() => _config.Instance.GetEnumerator();
///<inheritdoc/>
- public bool TryGetValue(string key, [MaybeNullWhen(false)] out JsonElement value) => _config.Value.TryGetValue(key, out value);
+ public bool TryGetValue(string key, [MaybeNullWhen(false)] out JsonElement value) => _config.Instance.TryGetValue(key, out value);
- IEnumerator IEnumerable.GetEnumerator() => _config.Value.GetEnumerator();
+ IEnumerator IEnumerable.GetEnumerator() => _config.Instance.GetEnumerator();
}
}
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs
index 0a1bc7f..39bdc86 100644
--- a/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs
+++ b/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using VNLib.Utils.Extensions;
+using VNLib.Plugins.Extensions.Loading.Configuration;
namespace VNLib.Plugins.Extensions.Loading
{
@@ -67,7 +68,6 @@ namespace VNLib.Plugins.Extensions.Loading
public const string S3_SECRET_KEY = "s3_secret";
public const string PLUGIN_ASSET_KEY = "assets";
public const string PLUGINS_HOST_KEY = "plugins";
- public const string PLUGIN_PATHS_KEY = "paths";
/// <summary>
/// Retrieves a top level configuration dictionary of elements for the specified type.
@@ -200,13 +200,28 @@ namespace VNLib.Plugins.Extensions.Loading
ArgumentNullException.ThrowIfNull(getter);
//Get the property
- if (!config.TryGetValue(property, out JsonElement el))
- {
- throw new ConfigurationException($"Missing required configuration property '{property}' in config {config.ScopeName}");
- }
+ bool hasValue = config.TryGetValue(property, out JsonElement el);
+ Validate.Assert(hasValue, $"Missing required configuration property '{property}' in config {config.ScopeName}");
+
+ T? value = getter(el);
+ Validate.Assert(value is not null, $"Missing required configuration property '{property}' in config {config.ScopeName}");
- //Even if the getter returns null, throw
- return getter(el) ?? throw new ConfigurationException($"Missing required configuration property '{property}' in config {config.ScopeName}");
+ return value;
+ }
+
+
+ /// <summary>
+ /// Gets a required configuration property from the specified configuration scope
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="config"></param>
+ /// <param name="property">The name of the property to get</param>
+ /// <returns>The property value</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ConfigurationException"></exception>
+ public static T GetRequiredProperty<T>(this IConfigScope config, string property)
+ {
+ return GetRequiredProperty(config, property, static p => p.Deserialize<T>()!);
}
/// <summary>
@@ -258,6 +273,28 @@ namespace VNLib.Plugins.Extensions.Loading
}
/// <summary>
+ /// Gets a configuration property from the specified configuration scope
+ /// and invokes your callback function on the element if found to transform the
+ /// output value, or returns the default value if the property is not found.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="config"></param>
+ /// <param name="property">The name of the configuration element to get</param>
+ /// <param name="defaultValue">The default value to return</param>
+ /// <returns>The property value returned from your getter callback, or the default value if not found</returns>
+ /// <exception cref="ArgumentNullException"></exception>
+ [return: NotNullIfNotNull(nameof(defaultValue))]
+ public static T? GetValueOrDefault<T>(this IConfigScope config, string property, T defaultValue)
+ {
+ return GetValueOrDefault(
+ config,
+ property,
+ static p => p.Deserialize<T>(),
+ defaultValue
+ );
+ }
+
+ /// <summary>
/// Gets the configuration property name for the type
/// </summary>
/// <param name="type">The type to get the configuration name for</param>
@@ -442,7 +479,6 @@ namespace VNLib.Plugins.Extensions.Loading
}
}
-
/// <summary>
/// Attempts to load the basic S3 configuration variables required
/// for S3 client access
@@ -483,11 +519,34 @@ namespace VNLib.Plugins.Extensions.Loading
//Get global plugin config element
IConfigScope config = plugin.GetConfig(PLUGINS_HOST_KEY);
- //Get the plugins path or throw because it should ALWAYS be defined if this method is called
- return config[PLUGIN_PATHS_KEY].EnumerateArray()
- .Select(static p => p.GetString()!)
- .Select(Path.GetFullPath) //Get absolute file paths
- .ToArray();
+ /*
+ * Hosts are allowed to define mutliple plugin loading paths. A
+ * single path is supported for compat. Multi path takes precidence
+ * of course so attempt to load a string array first
+ */
+
+ if (!config.TryGetValue("paths", out JsonElement searchPaths)
+ && !config.TryGetValue("path", out searchPaths))
+ {
+ return [];
+ }
+
+ if (searchPaths.ValueKind == JsonValueKind.Array)
+ {
+ //Get the plugins path or throw because it should ALWAYS be defined if this method is called
+ return searchPaths.EnumerateArray()
+ .Select(static p => p.GetString()!)
+ .Select(Path.GetFullPath) //Get absolute file paths
+ .ToArray();
+ }
+ else if (searchPaths.ValueKind == JsonValueKind.String)
+ {
+ return [Path.GetFullPath(searchPaths.GetString()!)];
+ }
+ else
+ {
+ return [];
+ }
}
}
}
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs
index 4ffb3a1..58478d4 100644
--- a/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs
+++ b/lib/VNLib.Plugins.Extensions.Loading/src/LoadingExtensions.cs
@@ -123,7 +123,7 @@ namespace VNLib.Plugins.Extensions.Loading
*/
if (searchDirs.Length == 0)
{
- throw new ArgumentException("No plugin asset directory is defined for the current host configuration, this is likely a bug");
+ throw new ConfigurationException("No plugin asset directory is defined for the current host configuration, this is likely a bug");
}
//Get the first file that matches the search file
@@ -268,9 +268,10 @@ namespace VNLib.Plugins.Extensions.Loading
/// </summary>
/// <param name="plugin"></param>
/// <exception cref="ObjectDisposedException"></exception>
- public static void ThrowIfUnloaded(this PluginBase plugin)
+ public static void ThrowIfUnloaded(this PluginBase? plugin)
{
//See if the plugin was unlaoded
+ ArgumentNullException.ThrowIfNull(plugin);
ObjectDisposedException.ThrowIf(plugin.UnloadToken.IsCancellationRequested, plugin);
}