// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 namespace Amazon.TranscribeStreamingService { /// /// Performs 32-bit reversed cyclic redundancy checks. /// public class Crc32 { private static Crc32? _singleton; public static Crc32 Singleton { get { if(_singleton == null) _singleton = new Crc32(); return _singleton; } } #region Constants /// /// Generator polynomial (modulo 2) for the reversed CRC32 algorithm. /// private const UInt32 s_generator = 0xEDB88320; #endregion #region Constructors /// /// Creates a new instance of the Crc32 class. /// public Crc32() { // Constructs the checksum lookup table. Used to optimize the checksum. m_checksumTable = Enumerable.Range(0, 256).Select(i => { var tableEntry = (uint)i; for (var j = 0; j < 8; ++j) { tableEntry = ((tableEntry & 1) != 0) ? (s_generator ^ (tableEntry >> 1)) : (tableEntry >> 1); } return tableEntry; }).ToArray(); } #endregion #region Methods /// /// Calculates the checksum of the byte stream. /// /// The byte stream to calculate the checksum for. /// A 32-bit reversed checksum. public UInt32 Get(IEnumerable byteStream) { try { // Initialize checksumRegister to 0xFFFFFFFF and calculate the checksum. return ~byteStream.Aggregate(0xFFFFFFFF, (checksumRegister, currentByte) => (m_checksumTable[(checksumRegister & 0xFF) ^ Convert.ToByte(currentByte)] ^ (checksumRegister >> 8))); } catch (FormatException e) { throw new Exception("Could not read the stream out as bytes.", e); } catch (InvalidCastException e) { throw new Exception("Could not read the stream out as bytes.", e); } catch (OverflowException e) { throw new Exception("Could not read the stream out as bytes.", e); } } #endregion #region Fields /// /// Contains a cache of calculated checksum chunks. /// private readonly UInt32[] m_checksumTable; #endregion } }