8.2.165-stable Switch to dev

std > util > Source

/// An optionally bounded FIFO collection
type Queue<T> {
    /// Internal array of values laid out as `[<front>, ..., <back>]`
    private values: Array<T>?;
    /// If non-null, the queue elements will be dropped when the size reaches the capacity.
    private capacity: int?;

    /// Add element to queue back, if values size equals capacity, one element at front is removed.
    native fn push(value: T);
    /// Gets and removes the element at queue front.
    native fn pop(): T?;
    /// Returns the element at the back of the queue. Does not remove the element from the queue.
    native fn front(): T?;
    /// Returns the element at the front of the queue. Does not remove the element from the queue.
    native fn back(): T?;
    /// Clears the queue of all its content.
    native fn clear();
}

/// A LIFO (Last-In-First-Out) collection.
type Stack<T> {
    /// Internal array of values laid out as `[<bottom>, ..., <top>]`
    private values: Array<T>?;

    /// Adds an element to the top of the stack.
    native fn push(value: T);
    /// Gets and removes the element from the top of the stack.
    native fn pop(): T?;
    /// Returns the element at the top of the stack without removing it.
    native fn first(): T?;
    /// Returns the element at the bottom of the stack without removing it.
    native fn last(): T?;
    /// Clears the stack of all its content.
    native fn clear();
}

/// A FIFO collection to compute moving average over a fixed number of values.
/// Use this collection during iterations to efficiently obtain avg and std while regularly adding values.
type SlidingWindow<T> {
    /// Internal array of values laid out as FIFO
    private values: Array<T>?;
    /// The maximum number of elements in the window
    span: int;
    /// Running sum of values in the window for efficient average calculation
    sum: float?;
    /// Running sum of squared values for efficient standard deviation calculation
    sumsq: float?;
    /// Field to extract numerical value taken into account in the moving average
    private field: field?;

    /// Adds a new value value to the window. Following this addition, the last value in the window is discarded if the maximum size is reached.
    native fn add(value: T);
    /// Clears the window of all its values.
    native fn clear();
    /// Returns the median of the values contained in the window.
    native fn median(): float?;
    /// Returns the min of the values contained in the window.
    native fn min(): T?;
    /// Returns the min of the values contained in the window.
    native fn max(): T?;
    /// Returns the standard deviation of the values contained in the window.
    native fn std(): float?;
    /// Returns the average of the values contained in the window.
    native fn avg(): float?;
    /// Return number of current values stored in backend Array
    native fn size(): int;
}

/// A FIFO collection to compute moving average over values spaced by a maximum period of time.
/// Use this collection during iteration to efficiently obtain avg and std while regularly adding values.
type TimeWindow<T> {
    /// Internal array of values laid out as FIFO
    private values: Table<Tuple<time, T>>?;
    /// The maximum window span as a `duration` between the first and the last time.
    span: duration;
    /// Running sum of values in the window for efficient average calculation
    sum: float?;
    /// Running sum of squared values for efficient standard deviation calculation
    sumsq: float?;
    /// Field to extract numerical value taken into account in the moving average
    private field: field?;

    /// Adds a new value `value` to the window at time `t`.
    /// Following this addition, any value which exceeds the period of time configured from the most recent timepoint will be discarded from the window.
    native fn add(t: time, value: T);
    /// Moves the time window in time, so the window contains the time `t` given in parameter, without needing to add a value.
    native fn update(t: time);
    /// Clears the window of all its values.
    native fn clear();
    /// Returns the minimum of the values contained in the window.
    native fn min(): Tuple<time, T>?;
    /// Returns the maximum of the values contained in the window.
    native fn max(): Tuple<time, T>?;
    /// Returns the median of the values contained in the window.
    native fn median(): float?;
    /// Returns the standard deviation of the values contained in the window.
    native fn std(): float?;
    /// Returns the average of the values contained in the window.
    native fn avg(): float?;
    /// Return number of current values stored in backend Array
    native fn size(): int;
}

/// Structure to compute and update live gaussian distribution
type Gaussian<T> {
    /// Running sum of all added values
    sum: float?;
    /// Running sum of squared values for standard deviation calculation
    sumsq: float?;
    /// Total count of values added to the distribution
    count: int?;
    /// Minimum value observed in the distribution
    min: T?;
    /// Maximum value observed in the distribution
    max: T?;

    /// Adds a new value to the profile. Returns true if the value has successfully been added, false otherwise.
    native fn add(value: T?): bool;
    /// Adds a new value to the profile count number of times. Returns true if the value has successfully been added, false otherwise.
    native fn addx(value: T?, count: int): bool;
    /// Adds another gaussian in this one. Returns true if the value has successfully been added, false otherwise.
    native fn add_gaussian(value: Gaussian<T>): bool;

    /// Returns the standard deviation of the accepted values in the profile.
    native fn std(): T?;
    /// Returns the average of the accepted values in the profile.
    native fn avg(): T?;

    /// Does (value-min)/(max-min)
    native fn normalize(value: T): float?;
    /// Does value*(max-min)+min
    native fn inverse_normalize(value: float): T;
    /// Does (value-avg)/(std)
    native fn standardize(value: T): float;
    /// Does (value*std)+avg
    native fn inverse_standardize(value: float): T;
    /// Return the confidence given a value
    native fn confidence(value: T): float;
    /// Returns the probability distribution function (PDF) at a certain `value`
    native fn pdf(value: T): float;
    /// Returns the cumulative distribution function (CDF) at a certain value
    native fn cdf(value: T): float;
}

/// Random generator state can be initialized by setting the seed to stable value
type Random {
    seed: int?;
    private v: float?;

    /// Generates a random char between 'a' and 'z'.
    native fn char(): char;
    /// Generates a random int between the interval [min,max[.
    native fn uniform(min: int, max: int): int;
    /// Generates a random float between the interval [min,max[.
    native fn uniformf(min: float, max: float): float;
    /// Generates a random geo between the interval [min,max[.
    native fn uniformGeo(min: geo, max: geo): geo;
    /// Generates a random float from the normal distribution with average `avg` and standard deviation `std`.
    native fn normal(avg: float, std: float): float;
    /// Generates a random float from the gaussian `profile`.
    native fn gaussian(profile: Gaussian): float;
    /// Fill target structure with random uniform values
    native fn fill<T>(target: any, nb: int, min: T, max: T);
    /// Generates a UUID v4 string in the canonical 8-4-4-4-12 hex form.
    ///
    /// Uses this `Random`'s seedable PRNG (xorshift64*), so output is
    /// **reproducible** given a fixed `seed` — useful for tests and simulations.
    ///
    /// NOT cryptographically secure and NOT collision-resistant at the scale
    /// the spec implies (effective entropy is bounded by the 64-bit PRNG state).
    /// For security tokens or database primary keys, use `Uuid.v4()` instead.
    native fn uuid(): String;
    /// Generates a UUID v7 string (RFC 9562): 48-bit Unix-ms timestamp prefix
    /// followed by random bits.
    ///
    /// Uses this `Random`'s seedable PRNG. The timestamp component still comes
    /// from wall-clock time, so only the random tail is reproducible.
    /// Does NOT guarantee intra-millisecond monotonicity.
    ///
    /// For production IDs (DB primary keys, etc.), prefer `Uuid.v7()`.
    native fn uuid_v7(): String;
}

/// `Assert` is mainly used for testing purposes.
/// It verifies that assertions you make on the state of your data is correct, or throws an `Error`.
type Assert {
    /// Verifies that `a` is equal to `b`, throws an error if not. `a` and `b` can be of any type.
    static native fn equals(a: any?, b: any?);
    /// Verifies that `a` is equal to `b`, throws an error if not. `a` and `b` must be floats.
    static native fn equalsd(a: float, b: float, epsilon: float);
    /// Verifies that `a` is equal to `b`, throws an error if not. `a` and `b` must be tensors.
    static native fn equalst(a: Tensor, b: Tensor, epsilon: float);
    /// Verifies that `v` is true, throws an error if not.
    static native fn isTrue(v: bool);
    /// Verifies that `v` is false, throws an error if not.
    static native fn isFalse(v: bool);
    /// Verifies that `v` is null, throws an error if not.
    static native fn isNull(v: any?);
    /// Verifies that `v` is not null, throws an error if not.
    static native fn isNotNull(v: any?);
}

/// The `ProgressTracker` is used to monitor the progress of a computation, hence its performance.
/// It reports the overall performance (speed, ETA) measured since `start`, plus a smoothed
/// speed that reacts to the recent pace between consecutive updates.
type ProgressTracker {
    /// default `smoothing` weight used when `smoothing` is null; lower = steadier ETA
    static DEFAULT_SMOOTHING: float = 0.1;

    /// the start time of the tracker
    start: time;
    /// the maximum expected count, used to compute `progress` and `remaining`
    total: int?;
    /// the current step count, as last set by `update` (absolute, not a running sum)
    counter: int?;
    /// overall duration since `start`
    duration: duration?;
    /// ratio of progress from `0.0` to `1.0`
    progress: float?;
    /// overall recorded speed, in counter per second, averaged since `start`
    speed: float?;
    /// expected remaining duration until the end, estimated from `speed_smoothed`
    remaining: duration?;
    /// smoothed speed, in counter per second: an exponential moving average of the
    /// per-update (lap) speed, reacting faster to the recent pace than `speed`
    speed_smoothed: float?;
    /// EMA weight in `[0.0, 1.0]` applied to the latest lap when updating `speed_smoothed`
    /// (0 = overall average, 1 = last lap only); when null, `DEFAULT_SMOOTHING` is used
    smoothing: float?;

    /// Sets the current step count to `nb` (absolute, not incremental) and recomputes
    /// `duration`, `speed`, `speed_smoothed`, `progress` and `remaining`.
    native fn update(nb: int);
}

/// Represents the bounds of a quantizer slot
type QuantizerSlotBound<T> {
    min: T;
    max: T;
    center: T;
}

/// Represents a single bin in a histogram with count and ratio statistics
type HistogramBin<T> {
    /// The bounds of this histogram bin
    bin: QuantizerSlotBound<T>;
    /// Number of values in this bin
    count: int;
    /// Ratio of values in this bin relative to total
    ratio: float;
    /// Cumulative count of values up to and including this bin
    cumulative_count: int;
    /// Cumulative ratio of values up to and including this bin
    cumulative_ratio: float;
}

abstract type Quantizer<T> {
    abstract fn size(): int;
    abstract fn quantize(value: T): int;
    abstract fn bounds(slot: int): QuantizerSlotBound<T>;
}

/// Defines a dense (uniform) dimension.
type LinearQuantizer<T> extends Quantizer<T> {
    min: T;
    max: T;
    bins: int;
    open: bool?;

    native fn size(): int;
    native fn quantize(value: T): int;
    native fn bounds(slot: int): QuantizerSlotBound<T>;
}

type LogQuantizer<T> extends Quantizer<T> {
    min: T;
    max: T;
    bins: int;
    open: bool?;

    native fn size(): int;
    native fn quantize(value: T): int;
    native fn bounds(slot: int): QuantizerSlotBound<T>;
}

/// Defines a sparse dimension defined by enumerating step values.
type CustomQuantizer<T> extends Quantizer<T> {
    min: T;
    max: T;
    step_starts: Array<T>;
    open: bool?;

    native fn size(): int;
    native fn quantize(value: T): int;
    native fn bounds(slot: int): QuantizerSlotBound<T>;
}

type MultiQuantizer<T> extends Quantizer<Array<T>> {
    quantizers: Array<Quantizer<T>>;

    native fn size(): int;
    native fn quantize(value: Array<T>): int;
    native fn bounds(slot: int): QuantizerSlotBound<Array<T>>;
    native fn slot_vector(slot: int): Array<int>;
}

/// Slot for tracking gaussian statistics in a profiled bin
type GaussianProfileSlot {
    /// Sum of all values in this slot
    sum: int;
    /// Sum of squared values in this slot
    sumsq: int;
    /// Count of values in this slot
    count: int;
}

type GaussianProfile<T> {
    quantizer: Quantizer<T>;
    private precision: FloatPrecision;
    private bins: Table<GaussianProfileSlot?>?;
    value_min: float?;
    nb_rejected: int?;

    native fn add(key: T, value: float);
    native fn avg(key: T): float;
    native fn std(key: T): float;
    native fn sum(key: T): float;
    native fn count(key: T): int;
}

type Histogram<T> {
    quantizer: Quantizer<T>;
    bins: Array<int?>?;
    nb_rejected: int?;
    nb_accepted: int?;
    min: T?;
    max: T?;
    sum: float?;
    sumsq: float?;

    native fn add(value: T);
    /// similar to add but increase the weight of value by count times
    native fn addx(value: T, count: int);
    native fn stats(): HistogramStats<T>?;
    native fn percentile(ratio: float): T?;
    native fn ratio_under(value: T): float;
    native fn get_bins(): Array<HistogramBin<T>>;
}

type HistogramStats<T> {
    min: T;
    max: T;
    whisker_low: T;
    whisker_high: T;
    percentile1: T;
    percentile5: T;
    percentile10: T;
    percentile20: T;
    percentile25: T;
    percentile50: T;
    percentile75: T;
    percentile80: T;
    percentile90: T;
    percentile95: T;
    percentile99: T;

    sum: float;
    avg: T;
    std: T;
    size: int;
}

/// Hashing, signing, and the encodings that usually travel with them.
///
/// Every method takes and returns `String`. A `String` is a length-carrying byte
/// buffer, so the raw (non-hex) digests hold arbitrary bytes, NUL included, and
/// their `size()` is a byte count rather than a character count.
///
/// The decoders (`base64_decode`, `base64url_decode`, `hex_decode`, `url_decode`)
/// are lenient by design: malformed input yields a best-effort result instead of
/// an error. Validate untrusted input before decoding it.
type Crypto {
    /// Computes the SHA-1 digest of `content` as raw 20 bytes.
    /// SHA-1 is broken for collision resistance. Use it for legacy wire formats
    /// and non-security checksums, never for signatures.
    static native fn sha1(content: String): String;
    /// Computes the SHA-1 digest of `content` as 40 lowercase hex characters.
    /// Carries the same security caveat as `sha1`.
    static native fn sha1hex(content: String): String;
    /// Computes the SHA-256 digest of `content` as raw 32 bytes.
    static native fn sha256(content: String): String;
    /// Computes the SHA-256 digest of `content` as 64 lowercase hex characters.
    static native fn sha256hex(content: String): String;
    /// Signs an already-computed SHA-256 digest with the RSA private key at
    /// `key_path`, returning the raw RSASSA-PKCS1-v1_5 signature. The signature is
    /// as long as the key modulus, so 256 bytes for an RSA-2048 key.
    ///
    /// `input` is the digest, not the message: pass `Crypto::sha256(message)`.
    /// Anything that is not exactly 32 bytes throws `"unable to sign input"`.
    ///
    /// `key_path` points at a PEM or DER private key. Passphrase-protected keys are
    /// not supported; an encrypted, missing or malformed key throws
    /// `"unable to parse keyfile"`.
    static native fn sha256_sign_pkcs1(input: String, key_path: String): String;
    /// Same as `sha256_sign_pkcs1`, with the signature encoded as lowercase hex,
    /// so 512 characters for an RSA-2048 key.
    static native fn sha256_sign_pkcs1_hex(input: String, key_path: String): String;
    /// Computes the HMAC-SHA256 of `input` under `key` as 64 lowercase hex
    /// characters. `key` is taken as raw bytes and may be of any length.
    static native fn sha256_hmac_hex(input: String, key: String): String;
    /// Computes the MD5 digest of `content` as raw 16 bytes.
    /// Not cryptographically secure: use it for checksums and legacy wire formats
    /// (S3 `Content-MD5`, S3 single-part ETag), never for signatures or passwords.
    static native fn md5(content: String): String;
    /// Computes the MD5 digest of `content` as 32 lowercase hex characters.
    /// Carries the same security caveat as `md5`.
    static native fn md5hex(content: String): String;
    /// Encodes `v` as standard base64 (RFC 4648 section 4): alphabet `A-Za-z0-9+/`,
    /// padded with `=` to a multiple of 4 characters.
    static native fn base64_encode(v: String): String;
    /// Decodes standard base64 back to raw bytes.
    /// Characters outside the alphabet are read as zero bits, and a trailing group
    /// of fewer than 4 characters is dropped, so malformed input decodes to
    /// garbage rather than throwing.
    static native fn base64_decode(v: String): String;
    /// Encodes `v` as URL-safe base64 (RFC 4648 section 5): alphabet `A-Za-z0-9-_`,
    /// with no `=` padding.
    static native fn base64url_encode(v: String): String;
    /// Decodes the unpadded URL-safe base64 produced by `base64url_encode`.
    /// Trailing `=` characters are decoded as data and corrupt the result, so strip
    /// the padding before decoding a padded value.
    static native fn base64url_decode(v: String): String;
    /// Encodes every byte of `v` as two lowercase hex characters.
    static native fn hex_encode(v: String): String;
    /// Decodes a hex string into raw bytes, accepting both upper and lower case.
    /// The result is always `v.size() / 2` bytes: an odd-length input, or one
    /// holding a non-hex character, yields a string of that length with
    /// unspecified contents rather than an error.
    static native fn hex_decode(v: String): String;
    /// Percent-encodes `v` for use in a URL. Preserves the RFC 3986 unreserved set
    /// `A-Za-z0-9-._~` and encodes every other byte as `%XX` with uppercase hex, so
    /// a space becomes `%20` and never `+`.
    static native fn url_encode(v: String): String;
    /// Percent-decodes `v`. Only `%XX` sequences are decoded: `+` stays a literal
    /// `+` rather than becoming a space, so this does not read
    /// `application/x-www-form-urlencoded` payloads. An incomplete or non-hex `%`
    /// sequence is passed through unchanged.
    static native fn url_decode(v: String): String;
}

/// Cryptographically strong UUID generator.
///
/// Backed by a dedicated CTR_DRBG (mbedTLS) seeded from system entropy.
/// Output is NOT reproducible — each call returns a fresh value.
///
/// For seedable/deterministic UUIDs (tests, simulations), use
/// `Random.uuid()` / `Random.uuid_v7()` instead.
type Uuid {
    /// Generates a UUID v4 (RFC 9562 §5.4): 122 bits of CSPRNG entropy in
    /// canonical 8-4-4-4-12 hex form. Suitable for security tokens,
    /// secrets, and unique identifiers at any scale.
    static native fn v4(): String;
    /// Generates a UUID v7 (RFC 9562 §5.7): 48-bit Unix-ms timestamp + 12-bit
    /// sub-millisecond counter (from µs resolution) + 62 CSPRNG bits.
    /// Time-sortable — ideal for database primary keys.
    ///
    /// Monotonic at microsecond resolution within the same process.
    /// Two calls in the exact same microsecond may sort in random order.
    static native fn v7(): String;
}