You are not logged in.
hi @ab,
I'd like to propose the addition of a helper function in `mormot.core.rtti.pas` to enhance support for parsing scoped CSV values into enum sets.
About use case, in JWT-based APIs, I often use enum sets encoded as scoped strings such as: `users:create,users:read,system:logs`
These values are not directly mappable using `GetSetCsvValue()` due to their prefixed format (I might missed an existing gem!).
I wrote a helper named `GetSetCsvValueTrimmed()` which uses `TrimOneChar()` to remove the scoped prefix before matching against enumeration names (maybe another internal function would be more appropriate):
/// Parse a delimited list of scoped identifiers into a set, returned as a 64-bit bitmask
// - each entry in the CSV should follow a scoped naming pattern, e.g. 'users:create'
// - the prefix separator (scopeChar) is customizable and defaults to ':' if not specified
// - this function is similar to GetSetCsvValue(), but will remove the scope prefix
// from each identifier before matching it against the enumeration names
// - returns 0 on parsing failure, or if none of the values map to known enum items
// - expects aTypeInfo to point to a set of enumerations with matching names
function GetSetCsvValueTrimmed(aTypeInfo: PRttiInfo; Csv: PUtf8Char; scopeChar: AnsiChar = ':'): QWord;
function GetSetCsvValueTrimmed(aTypeInfo: PRttiInfo; Csv: PUtf8Char; scopeChar: AnsiChar): QWord;
var
tmp: RawUtf8;
begin
result := 0;
if (Csv = nil) or (Csv^ = #0) or (aTypeInfo = nil) then
exit;
// remove scopes like 'users:' or 'system:' prefixes from each value
tmp := TrimOneChar(Csv, scopeChar);
result := GetSetCsvValue(aTypeInfo, pointer(tmp));
end;
If it makes sense, I also wrote unit tests to validate typical JWT-like scope strings.
type
TEnumPetStorePerm = (
epsPermNone, epsStoreRead, epsStoreWrite);
TEnumPetStorePermSet = set of TEnumPetStorePerm;
checkEqual(GetSetCsvValueTrimmed(TypeInfo(TEnumPetStorePermSet), 'store:read,store:write'), 6, 'TEnumPetStorePerm');
// ...
Thanks!
Offline