/// <summary>
        /// Gets the mapping from T into a StringBuilder representation, using various heuristics.
        /// This StringBuilder representation will be a component of the composed KeyValues for the
        /// hash outputs.
        /// </summary>
        public static ValueMapper <T, StringBuilder> GetSimpleMapper <T>(Schema schema, int col)
        {
            Contracts.AssertValue(schema);
            Contracts.Assert(0 <= col && col < schema.ColumnCount);
            var type = schema.GetColumnType(col).ItemType;

            Contracts.Assert(type.RawType == typeof(T));
            var conv = Conversion.Conversions.Instance;

            // First: if not key, then get the standard string converison.
            if (!type.IsKey)
            {
                return(conv.GetStringConversion <T>(type));
            }

            bool identity;

            // Second choice: if key, utilize the KeyValues metadata for that key, if it has one and is text.
            if (schema.HasKeyNames(col, type.KeyCount))
            {
                // REVIEW: Non-textual KeyValues are certainly possible. Should we handle them?
                // Get the key names.
                VBuffer <ReadOnlyMemory <char> > keyValues = default;
                schema.GetMetadata(MetadataUtils.Kinds.KeyValues, col, ref keyValues);
                ReadOnlyMemory <char> value = default;

                // REVIEW: We could optimize for identity, but it's probably not worthwhile.
                var keyMapper = conv.GetStandardConversion <T, uint>(type, NumberType.U4, out identity);
                return
                    ((ref T src, ref StringBuilder dst) =>
                {
                    ClearDst(ref dst);
                    uint intermediate = 0;
                    keyMapper(ref src, ref intermediate);
                    if (intermediate == 0)
                    {
                        return;
                    }
                    keyValues.GetItemOrDefault((int)(intermediate - 1), ref value);
                    dst.AppendMemory(value);
                });
            }

            // Third choice: just use the key value itself, subject to offsetting by the min.
            return(conv.GetKeyStringConversion <T>(type.AsKey));
        }