122 lines
4.2 KiB
C#
122 lines
4.2 KiB
C#
using System.Diagnostics.CodeAnalysis;
|
|
|
|
using CertMgr.Core.Log;
|
|
using CertMgr.Core.Storage;
|
|
|
|
namespace CertMgr.Core.Converters.Impl;
|
|
|
|
internal sealed class StorageConverter : ValueConverter<IStorage>
|
|
{
|
|
private const char Separator = '|';
|
|
|
|
protected override Task<IStorage?> DoConvertAsync(string rawValue, Type targetType, CancellationToken cancellationToken)
|
|
{
|
|
ReadOnlySpan<char> rawSpan = rawValue.AsSpan();
|
|
|
|
int storageTypeSplitIndex = rawSpan.IndexOf(Separator);
|
|
if (storageTypeSplitIndex == -1)
|
|
{
|
|
return Task.FromResult((IStorage?)EmptyStorage.Empty);
|
|
}
|
|
|
|
IStorage? storage;
|
|
|
|
ReadOnlySpan<char> storageTypeSpan = rawSpan.Slice(0, storageTypeSplitIndex);
|
|
ReadOnlySpan<char> storageDefinition = rawSpan.Slice(storageTypeSplitIndex + 1);
|
|
switch (storageTypeSpan)
|
|
{
|
|
case "file":
|
|
if (!TryGetFileStore(storageDefinition, out storage))
|
|
{
|
|
storage = EmptyStorage.Empty;
|
|
}
|
|
break;
|
|
default:
|
|
storage = EmptyStorage.Empty;
|
|
break;
|
|
}
|
|
|
|
return Task.FromResult((IStorage?)storage);
|
|
}
|
|
|
|
private bool TryGetFileStore(ReadOnlySpan<char> storageDefinition, [NotNullWhen(true)] out IStorage? storage)
|
|
{
|
|
// expecting that 'storageDefinition' is something like:
|
|
// <store-mode>|<file-path>
|
|
// or
|
|
// |<file-path>
|
|
// or
|
|
// <file-path>
|
|
//
|
|
// where <store-mode> can be:
|
|
// 'o' or 'overwrite' or 'overwriteornew'
|
|
// or
|
|
// 'a' or 'append' or 'appendornew'
|
|
// or
|
|
// 'c' or 'create' or 'createnew'
|
|
//
|
|
// where <file-path> can be:
|
|
// 'c:\path\myfile.txt'
|
|
// or
|
|
// '/path/myfile.txt'
|
|
// or
|
|
// './path/myfile.txt'
|
|
// in addition - <file-path> can be either quoted or double-quoted
|
|
|
|
storage = null;
|
|
|
|
FileStoreMode defaultStoreMode = FileStoreMode.OverwriteOrNew;
|
|
FileStoreMode storeMode;
|
|
ReadOnlySpan<char> filename;
|
|
|
|
int firstSplitIndex = storageDefinition.IndexOf(Separator);
|
|
if (firstSplitIndex != -1)
|
|
{
|
|
// there is a splitter. On the left side of it there must be <store-mode>. On the right there is a <file-path>
|
|
|
|
ReadOnlySpan<char> firstPart = storageDefinition.Slice(0, firstSplitIndex);
|
|
filename = storageDefinition.Slice(firstSplitIndex + 1);
|
|
|
|
if (firstPart.Length == 0)
|
|
{
|
|
storeMode = defaultStoreMode;
|
|
}
|
|
else if (Enum.TryParse(firstPart, true, out FileStoreMode tmpMode))
|
|
{
|
|
storeMode = tmpMode;
|
|
}
|
|
else if (firstPart.Equals("w", StringComparison.OrdinalIgnoreCase) || firstPart.Equals("overwrite", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
storeMode = FileStoreMode.OverwriteOrNew;
|
|
}
|
|
else if (firstPart.Equals("c", StringComparison.OrdinalIgnoreCase) || firstPart.Equals("createnew", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
storeMode = FileStoreMode.Create;
|
|
}
|
|
else if (firstPart.Equals("a", StringComparison.OrdinalIgnoreCase) || firstPart.Equals("append", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
storeMode = FileStoreMode.AppendOrNew;
|
|
}
|
|
else if (firstPart.Equals("o", StringComparison.OrdinalIgnoreCase) || firstPart.Equals("open", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
storeMode = FileStoreMode.Open;
|
|
}
|
|
else
|
|
{
|
|
// it is not store-mode or there is a typo or unsupported value
|
|
CLog.Error(string.Concat("Unsupported store-mode '", firstPart, "'"));
|
|
storeMode = defaultStoreMode;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// no split-char => just filename
|
|
storeMode = defaultStoreMode;
|
|
filename = storageDefinition;
|
|
}
|
|
|
|
storage = new FileStorage(filename.ToString(), storeMode);
|
|
return true;
|
|
}
|
|
}
|