lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nightowl...@apache.org
Subject [lucenenet] 05/11: Lucene.Net.Diagnostics.Debugging: Updated documentation
Date Tue, 03 Nov 2020 21:24:17 GMT
This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit 53a216893f39010e2a2a0f96c96582740840481f
Author: Shad Storhaug <shad@shadstorhaug.com>
AuthorDate: Tue Nov 3 11:31:55 2020 +0700

    Lucene.Net.Diagnostics.Debugging: Updated documentation
---
 src/Lucene.Net/Support/Diagnostics/Debugging.cs | 183 +++++++++++++++++++-----
 1 file changed, 150 insertions(+), 33 deletions(-)

diff --git a/src/Lucene.Net/Support/Diagnostics/Debugging.cs b/src/Lucene.Net/Support/Diagnostics/Debugging.cs
index 33b70e2..0dca2f0 100644
--- a/src/Lucene.Net/Support/Diagnostics/Debugging.cs
+++ b/src/Lucene.Net/Support/Diagnostics/Debugging.cs
@@ -1,5 +1,6 @@
 using J2N.Text;
 using Lucene.Net.Util;
+using System;
 using System.Runtime.CompilerServices;
 
 namespace Lucene.Net.Diagnostics
@@ -38,6 +39,8 @@ namespace Lucene.Net.Diagnostics
 
         /// <summary>
         /// Checks for a condition; if the condition is <c>false</c>, throws
an <see cref="AssertionException"/>.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -49,106 +52,218 @@ namespace Lucene.Net.Diagnostics
 
         /// <summary>
         /// Checks for a condition; if the <paramref name="condition"/> is <c>false</c>,
throws an <see cref="AssertionException"/> with the message formated 
-        /// from the specified <paramref name="messageToFormat"/>.
+        /// from the specified <paramref name="messageFormat"/>.
+        /// <para/>
+        /// IMPORTANT: The purpose of using this overload is to defer execution of building
the string until it the <paramref name="condition"/> is <c>false</c>. Ideally,
we would
+        /// use a <see cref="Func{String}"/> parameter, but doing so allocates extra
RAM even when calls to the method are in an unreachable execution path. When passing
+        /// parameters, strive to pass value or reference types without doing any pre-processing
or string formatting. If necessary, wrap the parameter in another class or struct and
+        /// override the <see cref="object.ToString()"/> method so any expensive formatting
is deferred until after <paramref name="condition"/> is checked.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
-        /// <param name="messageToFormat">A string format (i.e. with {0} that will
be filled with the parameters</param>
+        /// <param name="messageFormat">A composite format string to use to build a
failure message.
+        /// This message contains text intermixed with zero or more format items, which correspond
to
+        /// the <paramref name="p0"/> parameter.</param>
+        /// <param name="p0">The parameter corresponding to the format item at index
0 (<c>{0}</c>).</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void Assert<T0>(bool condition, string messageToFormat, T0 p0)
+        public static void Assert<T0>(bool condition, string messageFormat, T0 p0)
         {
             if (AssertsEnabled && !condition)
-                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageToFormat, p0));
+                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageFormat, p0));
         }
 
         /// <summary>
         /// Checks for a condition; if the <paramref name="condition"/> is <c>false</c>,
throws an <see cref="AssertionException"/> with the message formated 
-        /// from the specified <paramref name="messageToFormat"/>.
+        /// from the specified <paramref name="messageFormat"/>.
+        /// <para/>
+        /// IMPORTANT: The purpose of using this overload is to defer execution of building
the string until it the <paramref name="condition"/> is <c>false</c>. Ideally,
we would
+        /// use a <see cref="Func{String}"/> parameter, but doing so allocates extra
RAM even when calls to the method are in an unreachable execution path. When passing
+        /// parameters, strive to pass value or reference types without doing any pre-processing
or string formatting. If necessary, wrap the parameter in another class or struct and
+        /// override the <see cref="object.ToString()"/> method so any expensive formatting
is deferred until after <paramref name="condition"/> is checked.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
-        /// <param name="messageToFormat">A string format (i.e. with {0} that will
be filled with the parameters</param>
+        /// <param name="messageFormat">A composite format string to use to build a
failure message.
+        /// This message contains text intermixed with zero or more format items, which correspond
to
+        /// the <paramref name="p0"/> or <paramref name="p1"/> parameters.</param>
+        /// <param name="p0">The parameter corresponding to the format item at index
0 (<c>{0}</c>).</param>
+        /// <param name="p1">The parameter corresponding to the format item at index
1 (<c>{1}</c>).</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void Assert<T0, T1>(bool condition, string messageToFormat, T0
p0, T1 p1)
+        public static void Assert<T0, T1>(bool condition, string messageFormat, T0
p0, T1 p1)
         {
             if (AssertsEnabled && !condition)
-                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageToFormat, p0, p1));
+                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageFormat, p0, p1));
         }
 
         /// <summary>
         /// Checks for a condition; if the <paramref name="condition"/> is <c>false</c>,
throws an <see cref="AssertionException"/> with the message formated 
-        /// from the specified <paramref name="messageToFormat"/>.
+        /// from the specified <paramref name="messageFormat"/>.
+        /// <para/>
+        /// IMPORTANT: The purpose of using this overload is to defer execution of building
the string until it the <paramref name="condition"/> is <c>false</c>. Ideally,
we would
+        /// use a <see cref="Func{String}"/> parameter, but doing so allocates extra
RAM even when calls to the method are in an unreachable execution path. When passing
+        /// parameters, strive to pass value or reference types without doing any pre-processing
or string formatting. If necessary, wrap the parameter in another class or struct and
+        /// override the <see cref="object.ToString()"/> method so any expensive formatting
is deferred until after <paramref name="condition"/> is checked.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
-        /// <param name="messageToFormat">A string format (i.e. with {0} that will
be filled with the parameters</param>
+        /// <param name="messageFormat">A composite format string to use to build a
failure message.
+        /// This message contains text intermixed with zero or more format items, which correspond
to
+        /// the <paramref name="p0"/>, <paramref name="p1"/> or <paramref
name="p2"/> parameters.</param>
+        /// <param name="p0">The parameter corresponding to the format item at index
0 (<c>{0}</c>).</param>
+        /// <param name="p1">The parameter corresponding to the format item at index
1 (<c>{1}</c>).</param>
+        /// <param name="p2">The parameter corresponding to the format item at index
2 (<c>{2}</c>).</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void Assert<T0, T1, T2>(bool condition, string messageToFormat,
T0 p0, T1 p1, T2 p2)
+        public static void Assert<T0, T1, T2>(bool condition, string messageFormat,
T0 p0, T1 p1, T2 p2)
         {
             if (AssertsEnabled && !condition)
-                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageToFormat, p0, p1, p2));
+                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageFormat, p0, p1, p2));
         }
 
         /// <summary>
         /// Checks for a condition; if the <paramref name="condition"/> is <c>false</c>,
throws an <see cref="AssertionException"/> with the message formated 
-        /// from the specified <paramref name="messageToFormat"/>.
+        /// from the specified <paramref name="messageFormat"/>.
+        /// <para/>
+        /// IMPORTANT: The purpose of using this overload is to defer execution of building
the string until it the <paramref name="condition"/> is <c>false</c>. Ideally,
we would
+        /// use a <see cref="Func{String}"/> parameter, but doing so allocates extra
RAM even when calls to the method are in an unreachable execution path. When passing
+        /// parameters, strive to pass value or reference types without doing any pre-processing
or string formatting. If necessary, wrap the parameter in another class or struct and
+        /// override the <see cref="object.ToString()"/> method so any expensive formatting
is deferred until after <paramref name="condition"/> is checked.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
-        /// <param name="messageToFormat">A string format (i.e. with {0} that will
be filled with the parameters</param>
+        /// <param name="messageFormat">A composite format string to use to build a
failure message.
+        /// This message contains text intermixed with zero or more format items, which correspond
to
+        /// the <paramref name="p0"/>, <paramref name="p1"/>, <paramref name="p2"/>
or <paramref name="p3"/> parameters.</param>
+        /// <param name="p0">The parameter corresponding to the format item at index
0 (<c>{0}</c>).</param>
+        /// <param name="p1">The parameter corresponding to the format item at index
1 (<c>{1}</c>).</param>
+        /// <param name="p2">The parameter corresponding to the format item at index
2 (<c>{2}</c>).</param>
+        /// <param name="p3">The parameter corresponding to the format item at index
3 (<c>{3}</c>).</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void Assert<T0, T1, T2, T3>(bool condition, string messageToFormat,
T0 p0, T1 p1, T2 p2, T3 p3)
+        public static void Assert<T0, T1, T2, T3>(bool condition, string messageFormat,
T0 p0, T1 p1, T2 p2, T3 p3)
         {
             if (AssertsEnabled && !condition)
-                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageToFormat, p0, p1, p2, p3));
+                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageFormat, p0, p1, p2, p3));
         }
 
         /// <summary>
         /// Checks for a condition; if the <paramref name="condition"/> is <c>false</c>,
throws an <see cref="AssertionException"/> with the message formated 
-        /// from the specified <paramref name="messageToFormat"/>.
+        /// from the specified <paramref name="messageFormat"/>.
+        /// <para/>
+        /// IMPORTANT: The purpose of using this overload is to defer execution of building
the string until it the <paramref name="condition"/> is <c>false</c>. Ideally,
we would
+        /// use a <see cref="Func{String}"/> parameter, but doing so allocates extra
RAM even when calls to the method are in an unreachable execution path. When passing
+        /// parameters, strive to pass value or reference types without doing any pre-processing
or string formatting. If necessary, wrap the parameter in another class or struct and
+        /// override the <see cref="object.ToString()"/> method so any expensive formatting
is deferred until after <paramref name="condition"/> is checked.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
-        /// <param name="messageToFormat">A string format (i.e. with {0} that will
be filled with the parameters</param>
+        /// <param name="messageFormat">A composite format string to use to build a
failure message.
+        /// This message contains text intermixed with zero or more format items, which correspond
to
+        /// the <paramref name="p0"/>, <paramref name="p1"/>, <paramref name="p2"/>,
<paramref name="p3"/>
+        /// or <paramref name="p4"/> parameters.</param>
+        /// <param name="p0">The parameter corresponding to the format item at index
0 (<c>{0}</c>).</param>
+        /// <param name="p1">The parameter corresponding to the format item at index
1 (<c>{1}</c>).</param>
+        /// <param name="p2">The parameter corresponding to the format item at index
2 (<c>{2}</c>).</param>
+        /// <param name="p3">The parameter corresponding to the format item at index
3 (<c>{3}</c>).</param>
+        /// <param name="p4">The parameter corresponding to the format item at index
4 (<c>{4}</c>).</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void Assert<T0, T1, T2, T3, T4>(bool condition, string messageToFormat,
T0 p0, T1 p1, T2 p2, T3 p3, T4 p4)
+        public static void Assert<T0, T1, T2, T3, T4>(bool condition, string messageFormat,
T0 p0, T1 p1, T2 p2, T3 p3, T4 p4)
         {
             if (AssertsEnabled && !condition)
-                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageToFormat, p0, p1, p2, p3, p4));
+                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageFormat, p0, p1, p2, p3, p4));
         }
 
         /// <summary>
         /// Checks for a condition; if the <paramref name="condition"/> is <c>false</c>,
throws an <see cref="AssertionException"/> with the message formated 
-        /// from the specified <paramref name="messageToFormat"/>.
+        /// from the specified <paramref name="messageFormat"/>.
+        /// <para/>
+        /// IMPORTANT: The purpose of using this overload is to defer execution of building
the string until it the <paramref name="condition"/> is <c>false</c>. Ideally,
we would
+        /// use a <see cref="Func{String}"/> parameter, but doing so allocates extra
RAM even when calls to the method are in an unreachable execution path. When passing
+        /// parameters, strive to pass value or reference types without doing any pre-processing
or string formatting. If necessary, wrap the parameter in another class or struct and
+        /// override the <see cref="object.ToString()"/> method so any expensive formatting
is deferred until after <paramref name="condition"/> is checked.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
-        /// <param name="messageToFormat">A string format (i.e. with {0} that will
be filled with the parameters</param>
+        /// <param name="messageFormat">A composite format string to use to build a
failure message.
+        /// This message contains text intermixed with zero or more format items, which correspond
to
+        /// the <paramref name="p0"/>, <paramref name="p1"/>, <paramref name="p2"/>,
<paramref name="p3"/>,
+        /// <paramref name="p4"/> or <paramref name="p5"/> parameters.</param>
+        /// <param name="p0">The parameter corresponding to the format item at index
0 (<c>{0}</c>).</param>
+        /// <param name="p1">The parameter corresponding to the format item at index
1 (<c>{1}</c>).</param>
+        /// <param name="p2">The parameter corresponding to the format item at index
2 (<c>{2}</c>).</param>
+        /// <param name="p3">The parameter corresponding to the format item at index
3 (<c>{3}</c>).</param>
+        /// <param name="p4">The parameter corresponding to the format item at index
4 (<c>{4}</c>).</param>
+        /// <param name="p5">The parameter corresponding to the format item at index
5 (<c>{5}</c>).</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void Assert<T0, T1, T2, T3, T4, T5>(bool condition, string messageToFormat,
T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
+        public static void Assert<T0, T1, T2, T3, T4, T5>(bool condition, string messageFormat,
T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
         {
             if (AssertsEnabled && !condition)
-                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageToFormat, p0, p1, p2, p3, p4, p5));
+                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageFormat, p0, p1, p2, p3, p4, p5));
         }
 
         /// <summary>
         /// Checks for a condition; if the <paramref name="condition"/> is <c>false</c>,
throws an <see cref="AssertionException"/> with the message formated 
-        /// from the specified <paramref name="messageToFormat"/>.
+        /// from the specified <paramref name="messageFormat"/>.
+        /// <para/>
+        /// IMPORTANT: The purpose of using this overload is to defer execution of building
the string until it the <paramref name="condition"/> is <c>false</c>. Ideally,
we would
+        /// use a <see cref="Func{String}"/> parameter, but doing so allocates extra
RAM even when calls to the method are in an unreachable execution path. When passing
+        /// parameters, strive to pass value or reference types without doing any pre-processing
or string formatting. If necessary, wrap the parameter in another class or struct and
+        /// override the <see cref="object.ToString()"/> method so any expensive formatting
is deferred until after <paramref name="condition"/> is checked.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
-        /// <param name="messageToFormat">A string format (i.e. with {0} that will
be filled with the parameters</param>
+        /// <param name="messageFormat">A composite format string to use to build a
failure message.
+        /// This message contains text intermixed with zero or more format items, which correspond
to
+        /// the <paramref name="p0"/>, <paramref name="p1"/>, <paramref name="p2"/>,
<paramref name="p3"/>,
+        /// <paramref name="p4"/>, <paramref name="p5"/> or <paramref name="p6"/>
parameters.</param>
+        /// <param name="p0">The parameter corresponding to the format item at index
0 (<c>{0}</c>).</param>
+        /// <param name="p1">The parameter corresponding to the format item at index
1 (<c>{1}</c>).</param>
+        /// <param name="p2">The parameter corresponding to the format item at index
2 (<c>{2}</c>).</param>
+        /// <param name="p3">The parameter corresponding to the format item at index
3 (<c>{3}</c>).</param>
+        /// <param name="p4">The parameter corresponding to the format item at index
4 (<c>{4}</c>).</param>
+        /// <param name="p5">The parameter corresponding to the format item at index
5 (<c>{5}</c>).</param>
+        /// <param name="p6">The parameter corresponding to the format item at index
6 (<c>{6}</c>).</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void Assert<T0, T1, T2, T3, T4, T5, T6>(bool condition, string
messageToFormat, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6)
+        public static void Assert<T0, T1, T2, T3, T4, T5, T6>(bool condition, string
messageFormat, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6)
         {
             if (AssertsEnabled && !condition)
-                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageToFormat, p0, p1, p2, p3, p4, p5, p6));
+                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageFormat, p0, p1, p2, p3, p4, p5, p6));
         }
 
         /// <summary>
         /// Checks for a condition; if the <paramref name="condition"/> is <c>false</c>,
throws an <see cref="AssertionException"/> with the message formated 
-        /// from the specified <paramref name="messageToFormat"/>.
+        /// from the specified <paramref name="messageFormat"/>.
+        /// <para/>
+        /// IMPORTANT: The purpose of using this overload is to defer execution of building
the string until it the <paramref name="condition"/> is <c>false</c>. Ideally,
we would
+        /// use a <see cref="Func{String}"/> parameter, but doing so allocates extra
RAM even when calls to the method are in an unreachable execution path. When passing
+        /// parameters, strive to pass value or reference types without doing any pre-processing
or string formatting. If necessary, wrap the parameter in another class or struct and
+        /// override the <see cref="object.ToString()"/> method so any expensive formatting
is deferred until after <paramref name="condition"/> is checked.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
-        /// <param name="messageToFormat">A string format (i.e. with {0} that will
be filled with the parameters</param>
+        /// <param name="messageFormat">A composite format string to use to build a
failure message.
+        /// This message contains text intermixed with zero or more format items, which correspond
to
+        /// the <paramref name="p0"/>, <paramref name="p1"/>, <paramref name="p2"/>,
<paramref name="p3"/>,
+        /// <paramref name="p4"/>, <paramref name="p5"/>, <paramref name="p6"/>
or <paramref name="p7"/> parameters.</param>
+        /// <param name="p0">The parameter corresponding to the format item at index
0 (<c>{0}</c>).</param>
+        /// <param name="p1">The parameter corresponding to the format item at index
1 (<c>{1}</c>).</param>
+        /// <param name="p2">The parameter corresponding to the format item at index
2 (<c>{2}</c>).</param>
+        /// <param name="p3">The parameter corresponding to the format item at index
3 (<c>{3}</c>).</param>
+        /// <param name="p4">The parameter corresponding to the format item at index
4 (<c>{4}</c>).</param>
+        /// <param name="p5">The parameter corresponding to the format item at index
5 (<c>{5}</c>).</param>
+        /// <param name="p6">The parameter corresponding to the format item at index
6 (<c>{6}</c>).</param>
+        /// <param name="p7">The parameter corresponding to the format item at index
7 (<c>{7}</c>).</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static void Assert<T0, T1, T2, T3, T4, T5, T6, T7>(bool condition, string
messageToFormat, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7)
+        public static void Assert<T0, T1, T2, T3, T4, T5, T6, T7>(bool condition, string
messageFormat, T0 p0, T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7)
         {
             if (AssertsEnabled && !condition)
-                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageToFormat, p0, p1, p2, p3, p4, p5, p6, p7));
+                throw new AssertionException(string.Format(StringFormatter.InvariantCulture,
messageFormat, p0, p1, p2, p3, p4, p5, p6, p7));
         }
 
         /// <summary>
@@ -156,9 +271,11 @@ namespace Lucene.Net.Diagnostics
         /// <para/>
         /// IMPORTANT: If you need to use string concatenation when building the message,
use an overload of
         /// <see cref="Assert{T0}(bool, string, T0)"/> for better performance.
+        /// <para/>
+        /// IMPORTANT: For best performance, only call this method after checking to ensure
the value of <see cref="AssertsEnabled"/> is <c>true</c>.
         /// </summary>
         /// <param name="condition">The conditional expression to evaluate. If the
condition is <c>true</c>, no exception is thrown.</param>
-        /// <param name="message">The message to use.</param>
+        /// <param name="message">The message to use to indicate a failure of <paramref
name="condition"/>.</param>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static void Assert(bool condition, string message)
         {


Mime
View raw message