#1 2025-06-02 14:33:50

flydev
Member
From: France
Registered: 2020-11-27
Posts: 94
Website

[proposal] Add GetSetCsvValueTrimmed() for scoped set parsing

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

Board footer

Powered by FluxBB