-module(crc32). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/crc32.gleam"). -export([finalize/1, update/2, new/0, checksum/1, verify/2]). -export_type([crc32/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Calculate CRC-32/ISO-HDLC checksums in pure Gleam.\n" "\n" " This module is the supported public API for the `crc32` package. It provides\n" " both one-shot checksum calculation and immutable incremental state for data\n" " processed in chunks.\n" "\n" " The implemented algorithm is CRC-32/ISO-HDLC, the conventional reflected\n" " CRC-32 variant commonly used by ZIP, gzip, PNG, and Ethernet. The standard\n" " check value for the ASCII bytes `\"123456789\"` is `0xCBF43926`.\n" "\n" " The public API intentionally works with `BitArray` values and returns the\n" " finalized checksum as a Gleam `Int`. Hexadecimal formatting is left to\n" " callers that need textual output.\n" "\n" " ```gleam\n" " import crc32\n" "\n" " pub fn main() {\n" " let checksum = crc32.checksum(<<\"123456789\":utf8>>)\n" " assert checksum == 0xCBF43926\n" " }\n" " ```\n" "\n" " ```gleam\n" " import crc32\n" "\n" " pub fn main() {\n" " let checksum =\n" " crc32.new()\n" " |> crc32.update(<<\"hello \":utf8>>)\n" " |> crc32.update(<<\"world\":utf8>>)\n" " |> crc32.finalize()\n" "\n" " assert checksum == crc32.checksum(<<\"hello world\":utf8>>)\n" " }\n" " ```\n" "\n" " CRC-32 is useful for detecting accidental corruption. It is not a\n" " cryptographic hash and must not be used for authentication or tamper\n" " resistance.\n" ). -opaque crc32() :: {crc32, integer()}. -file("src/crc32.gleam", 115). -spec table_lookup(integer()) -> integer(). table_lookup(Index) -> case gleam@list:drop( [16#00000000, 16#77073096, 16#EE0E612C, 16#990951BA, 16#076DC419, 16#706AF48F, 16#E963A535, 16#9E6495A3, 16#0EDB8832, 16#79DCB8A4, 16#E0D5E91E, 16#97D2D988, 16#09B64C2B, 16#7EB17CBD, 16#E7B82D07, 16#90BF1D91, 16#1DB71064, 16#6AB020F2, 16#F3B97148, 16#84BE41DE, 16#1ADAD47D, 16#6DDDE4EB, 16#F4D4B551, 16#83D385C7, 16#136C9856, 16#646BA8C0, 16#FD62F97A, 16#8A65C9EC, 16#14015C4F, 16#63066CD9, 16#FA0F3D63, 16#8D080DF5, 16#3B6E20C8, 16#4C69105E, 16#D56041E4, 16#A2677172, 16#3C03E4D1, 16#4B04D447, 16#D20D85FD, 16#A50AB56B, 16#35B5A8FA, 16#42B2986C, 16#DBBBC9D6, 16#ACBCF940, 16#32D86CE3, 16#45DF5C75, 16#DCD60DCF, 16#ABD13D59, 16#26D930AC, 16#51DE003A, 16#C8D75180, 16#BFD06116, 16#21B4F4B5, 16#56B3C423, 16#CFBA9599, 16#B8BDA50F, 16#2802B89E, 16#5F058808, 16#C60CD9B2, 16#B10BE924, 16#2F6F7C87, 16#58684C11, 16#C1611DAB, 16#B6662D3D, 16#76DC4190, 16#01DB7106, 16#98D220BC, 16#EFD5102A, 16#71B18589, 16#06B6B51F, 16#9FBFE4A5, 16#E8B8D433, 16#7807C9A2, 16#0F00F934, 16#9609A88E, 16#E10E9818, 16#7F6A0DBB, 16#086D3D2D, 16#91646C97, 16#E6635C01, 16#6B6B51F4, 16#1C6C6162, 16#856530D8, 16#F262004E, 16#6C0695ED, 16#1B01A57B, 16#8208F4C1, 16#F50FC457, 16#65B0D9C6, 16#12B7E950, 16#8BBEB8EA, 16#FCB9887C, 16#62DD1DDF, 16#15DA2D49, 16#8CD37CF3, 16#FBD44C65, 16#4DB26158, 16#3AB551CE, 16#A3BC0074, 16#D4BB30E2, 16#4ADFA541, 16#3DD895D7, 16#A4D1C46D, 16#D3D6F4FB, 16#4369E96A, 16#346ED9FC, 16#AD678846, 16#DA60B8D0, 16#44042D73, 16#33031DE5, 16#AA0A4C5F, 16#DD0D7CC9, 16#5005713C, 16#270241AA, 16#BE0B1010, 16#C90C2086, 16#5768B525, 16#206F85B3, 16#B966D409, 16#CE61E49F, 16#5EDEF90E, 16#29D9C998, 16#B0D09822, 16#C7D7A8B4, 16#59B33D17, 16#2EB40D81, 16#B7BD5C3B, 16#C0BA6CAD, 16#EDB88320, 16#9ABFB3B6, 16#03B6E20C, 16#74B1D29A, 16#EAD54739, 16#9DD277AF, 16#04DB2615, 16#73DC1683, 16#E3630B12, 16#94643B84, 16#0D6D6A3E, 16#7A6A5AA8, 16#E40ECF0B, 16#9309FF9D, 16#0A00AE27, 16#7D079EB1, 16#F00F9344, 16#8708A3D2, 16#1E01F268, 16#6906C2FE, 16#F762575D, 16#806567CB, 16#196C3671, 16#6E6B06E7, 16#FED41B76, 16#89D32BE0, 16#10DA7A5A, 16#67DD4ACC, 16#F9B9DF6F, 16#8EBEEFF9, 16#17B7BE43, 16#60B08ED5, 16#D6D6A3E8, 16#A1D1937E, 16#38D8C2C4, 16#4FDFF252, 16#D1BB67F1, 16#A6BC5767, 16#3FB506DD, 16#48B2364B, 16#D80D2BDA, 16#AF0A1B4C, 16#36034AF6, 16#41047A60, 16#DF60EFC3, 16#A867DF55, 16#316E8EEF, 16#4669BE79, 16#CB61B38C, 16#BC66831A, 16#256FD2A0, 16#5268E236, 16#CC0C7795, 16#BB0B4703, 16#220216B9, 16#5505262F, 16#C5BA3BBE, 16#B2BD0B28, 16#2BB45A92, 16#5CB36A04, 16#C2D7FFA7, 16#B5D0CF31, 16#2CD99E8B, 16#5BDEAE1D, 16#9B64C2B0, 16#EC63F226, 16#756AA39C, 16#026D930A, 16#9C0906A9, 16#EB0E363F, 16#72076785, 16#05005713, 16#95BF4A82, 16#E2B87A14, 16#7BB12BAE, 16#0CB61B38, 16#92D28E9B, 16#E5D5BE0D, 16#7CDCEFB7, 16#0BDBDF21, 16#86D3D2D4, 16#F1D4E242, 16#68DDB3F8, 16#1FDA836E, 16#81BE16CD, 16#F6B9265B, 16#6FB077E1, 16#18B74777, 16#88085AE6, 16#FF0F6A70, 16#66063BCA, 16#11010B5C, 16#8F659EFF, 16#F862AE69, 16#616BFFD3, 16#166CCF45, 16#A00AE278, 16#D70DD2EE, 16#4E048354, 16#3903B3C2, 16#A7672661, 16#D06016F7, 16#4969474D, 16#3E6E77DB, 16#AED16A4A, 16#D9D65ADC, 16#40DF0B66, 16#37D83BF0, 16#A9BCAE53, 16#DEBB9EC5, 16#47B2CF7F, 16#30B5FFE9, 16#BDBDF21C, 16#CABAC28A, 16#53B39330, 16#24B4A3A6, 16#BAD03605, 16#CDD70693, 16#54DE5729, 16#23D967BF, 16#B3667A2E, 16#C4614AB8, 16#5D681B02, 16#2A6F2B94, 16#B40BBE37, 16#C30C8EA1, 16#5A05DF1B, 16#2D02EF8D], Index ) of [Head | _] -> Head; [] -> 0 end. -file("src/crc32.gleam", 122). -spec update_bytes(integer(), bitstring()) -> integer(). update_bytes(Crc, Data) -> case Data of <<>> -> Crc; <> -> Crc@1 = erlang:'bxor'(Crc, Byte), Index = erlang:'band'(Crc@1, 16#FF), Crc@2 = erlang:'bsr'(Crc@1, 8), Crc@3 = erlang:'bxor'(Crc@2, table_lookup(Index)), update_bytes(Crc@3, Rest); _ -> Crc end. -file("src/crc32.gleam", 204). ?DOC( " Finalize an incremental calculation and return its CRC-32 checksum.\n" "\n" " The returned `Int` is the finalized CRC-32/ISO-HDLC value after the\n" " algorithm's final XOR step.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let checksum =\n" " crc32.new()\n" " |> crc32.update(data)\n" " |> crc32.finalize()\n" " ```\n" ). -spec finalize(crc32()) -> integer(). finalize(Crc) -> erlang:'bxor'(erlang:element(2, Crc), 16#FFFFFFFF). -file("src/crc32.gleam", 186). ?DOC( " Feed another chunk of bytes into an incremental CRC-32 calculation.\n" "\n" " This function is pipeline-friendly and returns a new state value. Updating\n" " with multiple chunks produces the same finalized checksum as processing the\n" " concatenated bytes in a single call to [`checksum`](#checksum).\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " crc32.new()\n" " |> crc32.update(<<\"hello \":utf8>>)\n" " |> crc32.update(<<\"world\":utf8>>)\n" " |> crc32.finalize()\n" " // => same as crc32.checksum(<<\"hello world\":utf8>>)\n" " ```\n" ). -spec update(crc32(), bitstring()) -> crc32(). update(Crc, Data) -> {crc32, update_bytes(erlang:element(2, Crc), Data)}. -file("src/crc32.gleam", 166). ?DOC( " Start a new incremental CRC-32/ISO-HDLC calculation.\n" "\n" " The returned state uses the standard initial value for CRC-32/ISO-HDLC.\n" " Pass the state to [`update`](#update) for each chunk of input and then\n" " finish with [`finalize`](#finalize).\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let crc = crc32.new()\n" " ```\n" ). -spec new() -> crc32(). new() -> {crc32, 16#FFFFFFFF}. -file("src/crc32.gleam", 148). ?DOC( " Calculate the CRC-32/ISO-HDLC checksum of the complete input.\n" "\n" " This is the convenience entry point for callers that already have all bytes\n" " available in one `BitArray`. It is equivalent to calling [`new`](#new),\n" " [`update`](#update), and then [`finalize`](#finalize).\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let value = crc32.checksum(<<\"hello\":utf8>>)\n" " ```\n" ). -spec checksum(bitstring()) -> integer(). checksum(Data) -> _pipe = new(), _pipe@1 = update(_pipe, Data), finalize(_pipe@1). -file("src/crc32.gleam", 223). ?DOC( " Finalize an incremental calculation and compare it with an expected checksum.\n" "\n" " This is a convenience helper for verification workflows. The `expected`\n" " value should be the finalized CRC-32/ISO-HDLC checksum, typically written as\n" " a hexadecimal integer literal in source code.\n" "\n" " ## Examples\n" "\n" " ```gleam\n" " let valid =\n" " crc32.new()\n" " |> crc32.update(data)\n" " |> crc32.verify(expected)\n" " ```\n" ). -spec verify(crc32(), integer()) -> boolean(). verify(Crc, Expected) -> finalize(Crc) =:= Expected.