=begin pod

=head1 NAME

CRoaring - Raku bindings for CRoaring compressed bitmap library

=head1 SYNOPSIS

=begin code :lang<raku>

use CRoaring;

# Create bitmaps
my CRoaring $a = CRoaring.from-array([1, 2, 3, 4, 5]);
my CRoaring $b = CRoaring.from-range(3, 7);
my CRoaring $c = CRoaring.new;
$c.add(10);
$c.add-many([11, 12, 13]);

# Set operations (return new owned bitmaps)
my CRoaring $union     = $a.or($b);       # {1,2,3,4,5,6,7}
my CRoaring $intersect = $a.and($b);      # {3,4,5}
my CRoaring $diff      = $a.andnot($b);   # {1,2}
my CRoaring $sym-diff  = $a.xor($b);      # {1,2,6,7}

# Query
say $union.cardinality;   # 7
say $union.elems;          # 7 (alias)
say $a.contains(3);       # True
say $a.is-empty;           # False
say 3 ~~ $a;              # True (smartmatch)

# Comparison
say $a.equals($b);         # False
say $a.is-subset-of($union); # True

# Clone
my CRoaring $copy = $a.clone;

# Conversion
say $a.to-array;           # (1, 2, 3, 4, 5)
say $a.list;               # Same as to-array

# Pagination (O(log n) per element, no full materialization)
say $a.select(0);              # 1 (element at rank 0)
say $a.select(4);              # 5 (element at rank 4)
say $a.slice(1, 3);            # (2, 3, 4) (3 elements starting at offset 1)
say $a.slice-reverse(0, 3);    # (5, 4, 3) (newest 3, descending)
say $a.slice-reverse(3, 3);    # (2, 1) (next page, partial)

# Serialize / deserialize (portable format)
my Buf $data = $a.serialize;
my CRoaring $restored = CRoaring.deserialize($data);

# Optimize storage
$a.optimize;

# Deterministic cleanup (also called automatically by GC via DESTROY)
$copy.dispose;

=end code

=head1 DESCRIPTION

CRoaring provides Raku bindings for the CRoaring compressed bitmap library (Roaring Bitmaps).
Roaring bitmaps are compressed bitsets that support fast set operations — ideal for tagging,
filtering, and indexing millions of items.

The C library is vendored as an amalgamation. No system dependencies
are required beyond libc.

=head1 INSTALLATION

    zef install CRoaring

On install, C<Build.rakumod> tries two paths in order:

=item B<Prebuilt binary download> from this repo's GitHub Releases for
  the detected (OS, arch) pair. Verified against a SHA256 bundled in
  the distribution (C<resources/checksums.txt>). Statically-linked,
  stripped, no transitive dependencies. ~2–5 seconds on a decent
  connection. This is the default path when a matching release
  exists.

=item B<Source compile fallback> via C<cc> (or C<cl> on Windows/MSVC).
  Used when no prebuilt is available for the platform, when the
  download fails, when the checksum doesn't match, or when the
  user has opted out of prebuilts via env var. Takes ~20–30 seconds
  and needs a C toolchain but no other system libraries.

=head2 Supported prebuilt platforms

=item macOS universal (arm64 + x86_64 slices in one dylib)
=item Linux x86_64 glibc
=item Linux aarch64 glibc
=item Windows x86_64
=item Windows arm64 (Copilot+ PCs, Snapdragon X)

On platforms outside this list (Alpine musl, BSDs, i686, etc.) the
fallback compile path runs automatically.

=head2 Environment variables

=item C<CROARING_BUILD_FROM_SOURCE=1> — skip the prebuilt path and
  always compile. Useful for reproducible builds or when auditing
  what's going into the dylib.
=item C<CROARING_BINARY_ONLY=1> — refuse to fall back to compile if
  the prebuilt is unavailable. Useful in CI where a 10× slower
  install via surprise compile is worse than a loud failure.
=item C<CROARING_BINARY_URL=<url>> — override the GitHub Releases
  base URL. For private mirrors, air-gapped setups, or testing a
  pre-release build.
=item C<CROARING_CACHE_DIR=<path>> — override the download cache
  location. Defaults to C<$XDG_CACHE_HOME/CRoaring-binaries/> or
  C<~/.cache/CRoaring-binaries/>.
=item C<CROARING_LIB=<path>> — bypass C<%?RESOURCES> entirely and
  load the library from an explicit path. Undocumented escape
  hatch for custom notcurses builds and similar; you take full
  responsibility for ABI compatibility.

=head2 Binary release versioning

Prebuilt binaries are tagged independently of the Raku distribution:

    binaries-croaring-<upstream-version>-r<recipe-revision>

e.g. C<binaries-croaring-0.6.0-r1>. The C<upstream-version> tracks
the vendored CRoaring amalgamation; C<recipe-revision> bumps only
when build flags change (compiler flags, strip options, platform
additions) while the upstream library stays the same.

C<Build.rakumod> hardcodes which binary tag it expects, so a Raku-
side bugfix release of C<CRoaring> can ship without rebuilding
binaries. Users upgrading within the same binary tag get their
download from the cache, not the network.

=head2 Performance

Union/intersection of two 1M-element bitmaps: under 1ms. 100K contains lookups in a 1M bitmap: 15ms.
Serialize+deserialize 1M contiguous values: 6ms, 230 bytes.

=head2 Memory management

Every C<CRoaring> object owns its underlying C bitmap handle. Set operations (C<and>, C<or>,
C<xor>, C<andnot>) return new owned instances. The handle is freed automatically by Raku's GC
via C<DESTROY>, or deterministically by calling C<.dispose>. After dispose, the handle is set
to C<Nil> and further operations are safe (no double-free).

=head2 Value range

CRoaring uses uint32 document IDs (0 to 4,294,967,295).

=head1 AUTHOR

Matt Doughty <matt@apogee.guru>

=head1 COPYRIGHT AND LICENSE

Copyright 2026 Matt Doughty

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

CRoaring C library is licensed under Apache 2.0 / MIT.

=end pod
