/* tslint:disable */
/* eslint-disable */

/* auto-generated by NAPI-RS */

/** Settings for a synchronisation attempt. */
export interface Settings {
  /** How many samples to gather for synchronisation. */
  samples?: number
  /** The maximum amount of time in microseconds between taking two samples. */
  jitter?: number
}
/**
 * Simple sans-io timesync client and server.
 *
 * Timesimp is based on the averaging method described in [Simpson (2002), A Stream-based Time
 * Synchronization Technique For Networked Computer Games][paper], but with a corrected delta
 * calculation. Compared to NTP, it's a simpler and less accurate time synchronisation algorithm
 * that is usable over network streams, rather than datagrams. Simpson asserts they were able to
 * achieve accuracies of 100ms or better, which is sufficient in many cases; my testing gets
 * accuracies well below 5ms. The main limitation of the algorithm is that round-trip-time is
 * assumed to be symmetric: if the forward trip time is different from the return trip time, then
 * an error is induced equal to the value of the difference in trip times.
 *
 * This library provides a sans-io implementation: you bring in your transport and your storage;
 * timesimp gives you time offsets. Internally, timesimp is implemented in Rust.
 *
 * If the local clock goes backward during a synchronisation, the invalid delta is discarded; this
 * may cause the sync attempt to fail, especially if the `samples` count is lowered to its minimum
 * of 3. This is a deliberate design decision: you should handle failure and retry, and the sync
 * will proceed correctly when the clock is stable.
 *
 * [paper]: https://web.archive.org/web/20160310125700/http://mine-control.com/zack/timesync/timesync.html
 */
export declare class Timesimp {
  /**
   * Create a new timesimp instance.
   *
   * `load()` must be an async function that returns the current offset in microseconds, or
   * `null` if no offset is currently stored.
   *
   * `store()` must be an async function that stores a given offset in microseconds. Once
   * `store()` has been called once, `load()` should no longer return `null` if it did.
   *
   * `query()` must be an async function that sends the `request` buffer to a timesimp server,
   * and returns the bytes that the server sends back. If a transport error occurs, the function
   * should throw. For example, this can be an HTTP POST using `fetch()`.
   *
   * Due to internal API limitations, all three of these have a first `err` argument; this
   * must be immediately thrown if truthy:
   *
   * ```js
   * new Timesimp(
   *     async (err) => { // load
   *         if (err) throw err;
   *         return db.query("offset");
   *     },
   *     async (err, offset) => { // store
   *         if (err) throw err;
   *         await db.update("offset", offset);
   *     },
   *     async (err, request) => {
   *         if (err) throw err;
   *         const res = await fetch("https://timesimp.server", {
   *             method: "POST",
   *             body: request,
   *         });
   *         return res.blob();
   *     }
   * );
   * ```
   */
  constructor(load: (err: Error) => Promise<number | null>, store: (err: Error, offset: number) => Promise<void>, query: (err: Error, request: Buffer) => Promise<Buffer>)
  /**
   * The current time in microseconds since the epoch, adjusted with the offset.
   *
   * This is a convenience function that internally calls your `load()`. You may want to
   * implement your own function, especially if you want to get a `Date` or `Temporal`, or if
   * you’ve implemented some caching.
   */
  microtime(): Promise<number>
  /**
   * The implementation of the server endpoint.
   *
   * Use this in your server endpoint implementation. The endpoint should do as little else as
   * possible to avoid adding unpredictable latency.
   *
   * You should obtain some bytes from the request’s payload (in this version, 8 bytes), and
   * this method will return some other bytes (in this version, 16 bytes), which you should
   * send back to the client.
   */
  answerClient(request: Buffer): Promise<Buffer>
  /**
   * The main client state driver. Call this in a loop.
   *
   * You’re expected to sleep for a while after calling this, or to run it on a schedule. Take
   * care to compute your schedule on your raw system clock or equivalent, so it does not get
   * influenced by the offset, which could make it jump around or even spin. `setInterval` or
   * `setTimeout` are appropriate.
   *
   * If `load()` returns `null`, this method will attempt to `store()` the first delta it gets
   * from the server. This lets you get an “accurate enough” timestamp pretty quickly, instead
   * of waiting for a full round of samples. Errors from that store are ignored silently.
   *
   * If this returns `null`, not enough samples were obtained to have enough confidence in the
   * result, likely because the `query()` function encountered an error for most tries. Errors
   * from `query()` are not returned; you may want to catch them for logging before passing them
   * on.
   *
   * On success, returns the calculated offset in microseconds.
   */
  attemptSync(settings: Settings): Promise<number | null>
}
