private static HashSet <UInt128> Parse128BitHashes(CosmosObject hashDictionary, string propertyName)
            {
                HashSet <UInt128> hashSet = new HashSet <UInt128>();

                if (!hashDictionary.TryGetValue(propertyName, out CosmosArray array))
                {
                    throw new MalformedContinuationTokenException(
                              $"{nameof(UnorderdDistinctMap)} continuation token was malformed.");
                }

                foreach (CosmosElement item in array)
                {
                    if (!(item is CosmosBinary binary))
                    {
                        throw new MalformedContinuationTokenException(
                                  $"{nameof(UnorderdDistinctMap)} continuation token was malformed.");
                    }

                    // Todo have this method work with span<byte> instead to avoid the allocation.
                    UInt128 uint128 = UInt128.FromByteArray(binary.Value.ToArray());
                    hashSet.Add(uint128);
                }

                return(hashSet);
            }
Esempio n. 2
0
            /// <summary>
            /// Adds a string to the distinct map.
            /// </summary>
            /// <param name="value">The string to add.</param>
            /// <returns>Whether or not the value was successfully added.</returns>
            private bool AddStringValue(string value)
            {
                bool added      = false;
                int  utf8Length = Encoding.UTF8.GetByteCount(value);

                // If you fit the string with full fidelity in 24 bytes, then you might as well just hash the string.
                if (utf8Length <= UnorderdDistinctMap.UInt192Length)
                {
                    // Zero out the array since you want all trailing bytes to be 0 for the conversions that happen next.
                    Array.Clear(this.utf8Buffer, 0, this.utf8Buffer.Length);
                    Encoding.UTF8.GetBytes(value, 0, utf8Length, this.utf8Buffer, 0);

                    if (utf8Length == 0)
                    {
                        added = this.AddSimpleValue(SimpleValues.EmptyString);
                    }
                    else if (utf8Length <= UnorderdDistinctMap.UIntLength)
                    {
                        uint uintValue = BitConverter.ToUInt32(this.utf8Buffer, 0);
                        added = this.stringsLength4.Add(uintValue);
                    }
                    else if (utf8Length <= UnorderdDistinctMap.ULongLength)
                    {
                        ulong uLongValue = BitConverter.ToUInt64(this.utf8Buffer, 0);
                        added = this.stringLength8.Add(uLongValue);
                    }
                    else if (utf8Length <= UnorderdDistinctMap.UInt128Length)
                    {
                        UInt128 uInt128Value = UInt128.FromByteArray(this.utf8Buffer, 0);
                        added = this.stringLength16.Add(uInt128Value);
                    }
                    else
                    {
                        UInt192 uInt192Value = UInt192.FromByteArray(this.utf8Buffer, 0);
                        added = this.stringLength24.Add(uInt192Value);
                    }
                }
                else
                {
                    // Else the string is too large and we will just store the hash.
                    UInt192 uint192Value = DistinctMap.GetHash(CosmosString.Create(value));
                    added = this.stringLength24Plus.Add(uint192Value);
                }

                return(added);
            }
Esempio n. 3
0
            /// <summary>
            /// Adds a string to the distinct map.
            /// </summary>
            /// <param name="value">The string to add.</param>
            /// <returns>Whether or not the value was successfully added.</returns>
            private bool AddStringValue(string value)
            {
                bool added      = false;
                int  utf8Length = Encoding.UTF8.GetByteCount(value);

                // If you can fit the string with full fidelity in 16 bytes, then you might as well just hash the string itself.
                if (utf8Length <= UnorderdDistinctMap.UInt128Length)
                {
                    Span <byte> utf8Buffer = stackalloc byte[UInt128Length];
                    Encoding.UTF8.GetBytes(value, utf8Buffer);
                    if (utf8Length == 0)
                    {
                        added = this.AddSimpleValue(SimpleValues.EmptyString);
                    }
                    else if (utf8Length <= UnorderdDistinctMap.UIntLength)
                    {
                        uint uintValue = MemoryMarshal.Read <uint>(utf8Buffer);
                        added = this.stringsLength4.Add(uintValue);
                    }
                    else if (utf8Length <= UnorderdDistinctMap.ULongLength)
                    {
                        ulong uLongValue = MemoryMarshal.Read <ulong>(utf8Buffer);
                        added = this.stringsLength8.Add(uLongValue);
                    }
                    else
                    {
                        UInt128 uInt128Value = UInt128.FromByteArray(utf8Buffer);
                        added = this.stringsLength16.Add(uInt128Value);
                    }
                }
                else
                {
                    // Else the string is too large and we will just store the hash.
                    UInt128 uint128Value = DistinctHash.GetHash(CosmosString.Create(value));
                    added = this.stringsLength16Plus.Add(uint128Value);
                }

                return(added);
            }