|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.Reflection.Internal;
using System.Text;
namespace System.Reflection.Metadata
{
/// <summary>
/// Provides the <see cref="MetadataReader"/> with a custom mechanism for decoding
/// byte sequences in metadata that represent text.
/// </summary>
/// <remarks>
/// This can be used for the following purposes:
///
/// 1) To customize the treatment of invalid input. When no decoder is provided,
/// the <see cref="MetadataReader"/> uses the default fallback replacement
/// with \uFFFD)
///
/// 2) To reuse existing strings instead of allocating a new one for each decoding
/// operation.
/// </remarks>
public class MetadataStringDecoder
{
/// <summary>
/// Gets the encoding used by this instance.
/// </summary>
public Encoding Encoding { get; }
/// <summary>
/// The default decoder used by <see cref="MetadataReader"/> to decode UTF-8 when
/// no decoder is provided to the constructor.
/// </summary>
public static MetadataStringDecoder DefaultUTF8 { get; } = new MetadataStringDecoder(Encoding.UTF8);
/// <summary>
/// Creates a <see cref="MetadataStringDecoder"/> for the given encoding.
/// </summary>
/// <param name="encoding">The encoding to use.</param>
/// <remarks>
/// To cache and reuse existing strings. Create a derived class and override <see cref="GetString(byte*, int)"/>
/// </remarks>
public MetadataStringDecoder(Encoding encoding)
{
if (encoding is null)
{
Throw.ArgumentNull(nameof(encoding));
}
// Non-enforcement of (encoding is UTF8Encoding) here is by design.
//
// This type is not itself aware of any particular encoding. However, the constructor argument that accepts a
// MetadataStringDecoder argument is validated however because it must be a UTF8 decoder.
Encoding = encoding;
}
/// <summary>
/// The mechanism through which the <see cref="MetadataReader"/> obtains strings
/// for byte sequences in metadata. Override this to cache strings if required.
/// Otherwise, it is implemented by forwarding straight to <see cref="Encoding"/>
/// and every call will allocate a new string.
/// </summary>
/// <param name="bytes">Pointer to bytes to decode.</param>
/// <param name="byteCount">Number of bytes to decode.</param>
/// <returns>The decoded string.</returns>
public virtual unsafe string GetString(byte* bytes, int byteCount)
{
Debug.Assert(Encoding != null);
return Encoding.GetString(bytes, byteCount);
}
}
}
|