Skip to content

Commit

Permalink
Optimize some methods in RightsManagementEncryptionTransform, reduce …
Browse files Browse the repository at this point in the history
…allocs (#9851)

* Use Span in Base32EncodeWithoutPadding and MakeUseLicenseStreamName

* Spanify ParseTypePrefixedUserName as well to remove an allocation

* Use StartsWith instead of CompareOrdinal in EnumUseLicenseStreams

* Use string.Concat to prevent DefaultInterpolatedStringHandler creation
  • Loading branch information
h3xds1nz authored Nov 8, 2024
1 parent c0b716b commit bb8503c
Showing 1 changed file with 18 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -649,11 +649,7 @@ ref bool stop
/// If the RM information in this file cannot be read by the current version of
/// this class.
/// </exception>
internal void
EnumUseLicenseStreams(
UseLicenseStreamCallback callback,
object param
)
internal void EnumUseLicenseStreams(UseLicenseStreamCallback callback, object param)
{
ArgumentNullException.ThrowIfNull(callback);

Expand All @@ -662,11 +658,7 @@ object param
foreach (StreamInfo si in _useLicenseStorage.GetStreams())
{
// Stream names: we preserve casing, but do case-insensitive comparison (Native CompoundFile API behavior)
if (String.CompareOrdinal(
LicenseStreamNamePrefix.ToUpperInvariant(), 0,
si.Name.ToUpperInvariant(), 0,
LicenseStreamNamePrefixLength
) == 0)
if (si.Name.StartsWith(LicenseStreamNamePrefix, StringComparison.OrdinalIgnoreCase))
{
callback(this, si, param, ref stop);
if (stop)
Expand Down Expand Up @@ -741,9 +733,7 @@ out ContentUser user
// If the type-prefixed name is not in a valid format, a FileFormatException
// will be thrown.
//
AuthenticationType authenticationType;
string userName;
ParseTypePrefixedUserName(typePrefixedUserName, out authenticationType, out userName);
ParseTypePrefixedUserName(typePrefixedUserName, out AuthenticationType authenticationType, out string userName);
user = new ContentUser(userName, authenticationType);

//
Expand Down Expand Up @@ -872,11 +862,7 @@ ref bool stop
/// SaveUseLicense has removed any existing use licenses for this
/// user before calling this internal function.
/// </remarks>
internal void
SaveUseLicenseForUser(
ContentUser user,
UseLicense useLicense
)
internal void SaveUseLicenseForUser(ContentUser user, UseLicense useLicense)
{
//
// Generate a unique name for the use license stream, and create the stream.
Expand Down Expand Up @@ -1007,10 +993,7 @@ internal UseLicense UseLicense
/// <remarks>
/// This function dose NOT produce a proper Base32Encoding since it will NOT produce proper padding.
/// </remarks>
private static char[]
Base32EncodeWithoutPadding(
byte[] bytes
)
private static ReadOnlySpan<char> Base32EncodeWithoutPadding(ReadOnlySpan<byte> bytes, Span<char> initialBuffer)
{
int numBytes = bytes.Length;
int numBits = checked (numBytes * 8);
Expand All @@ -1020,7 +1003,7 @@ byte[] bytes
if (numBits % 5 != 0)
++numChars;

char[] chars = new char[numChars];
Span<char> chars = initialBuffer.Length >= numChars ? initialBuffer.Slice(0, numChars) : new char[numChars];

for (int iChar = 0; iChar < numChars; ++iChar)
{
Expand Down Expand Up @@ -1055,8 +1038,10 @@ byte[] bytes
/// </summary>
private static string MakeUseLicenseStreamName()
{
return LicenseStreamNamePrefix +
new string(Base32EncodeWithoutPadding(Guid.NewGuid().ToByteArray()));
Span<byte> guidBytes = stackalloc byte[16];
Guid.NewGuid().TryWriteBytes(guidBytes);

return string.Concat(LicenseStreamNamePrefix, Base32EncodeWithoutPadding(guidBytes, stackalloc char[26]));
}

/// <summary>
Expand Down Expand Up @@ -1088,21 +1073,12 @@ ContentUser user
/// <param name="userName">
/// The user's ID.
/// </param>
private static void
ParseTypePrefixedUserName(
string typePrefixedUserName,
out AuthenticationType authenticationType,
out string userName
)
private static void ParseTypePrefixedUserName(string typePrefixedUserName, out AuthenticationType authenticationType, out string userName)
{
//
// We don't actually know the authentication type yet, and we might find that
// the type-prefixed user name doesn't even specify a valid authentication
// type. But we have to assign to authenticationType because it's an out
// parameter.
//
authenticationType = AuthenticationType.Windows;

int colonIndex = typePrefixedUserName.IndexOf(':');
if (colonIndex < 1 || colonIndex >= typePrefixedUserName.Length - 1)
{
Expand All @@ -1112,33 +1088,15 @@ out string userName
// No need to use checked{} here since colonIndex cannot be >= to (max int - 1)
userName = typePrefixedUserName.Substring(colonIndex + 1);

string authenticationTypeString = typePrefixedUserName.Substring(0, colonIndex);
bool validEnum = false;
// Usernames: Case-Insensitive comparison
ReadOnlySpan<char> authenticationSpan = typePrefixedUserName.AsSpan(0, colonIndex);

// user names: case-insensitive comparison
if (string.Equals(authenticationTypeString, nameof(AuthenticationType.Windows), StringComparison.OrdinalIgnoreCase))
{
if (authenticationSpan.Equals(nameof(AuthenticationType.Windows), StringComparison.OrdinalIgnoreCase))
authenticationType = AuthenticationType.Windows;
validEnum = true;
}
else if (string.Equals(authenticationTypeString, nameof(AuthenticationType.Passport), StringComparison.OrdinalIgnoreCase))
{
else if (authenticationSpan.Equals(nameof(AuthenticationType.Passport), StringComparison.OrdinalIgnoreCase))
authenticationType = AuthenticationType.Passport;
validEnum = true;
}

//
// Didn't find a matching enumeration constant.
//
if (!validEnum)
{
throw new FileFormatException(
SR.Format(
SR.InvalidAuthenticationTypeString,
typePrefixedUserName
)
);
}
else // Didn't find a matching enumeration constant.
throw new FileFormatException(SR.Format(SR.InvalidAuthenticationTypeString, typePrefixedUserName));
}

/// <summary>
Expand Down Expand Up @@ -1215,9 +1173,7 @@ BinaryReader utf8Reader
// If the type-prefixed name is not in a valid format, a FileFormatException
// will be thrown.
//
AuthenticationType authenticationType;
string userName;
ParseTypePrefixedUserName(typePrefixedUserName, out authenticationType, out userName);
ParseTypePrefixedUserName(typePrefixedUserName, out AuthenticationType authenticationType, out string userName);
return new ContentUser(userName, authenticationType);
}

Expand Down Expand Up @@ -1378,7 +1334,6 @@ Encoding encoding
// All use licenses reside in streams whose names begin with this prefix:
//
private const string LicenseStreamNamePrefix = "EUL-";
private static readonly int LicenseStreamNamePrefixLength = LicenseStreamNamePrefix.Length;

//
// The RM version information for the current version of this class.
Expand Down

0 comments on commit bb8503c

Please # to comment.