GithubHelp home page GithubHelp logo

pinkdiamond1 / samir Goto Github PK

View Code? Open in Web Editor NEW

This project forked from hypercubed/samir

0.0 1.0 0.0 810 KB

Samir uses an incremental implementation of the MurmurHash3 (32-bit) hashing algorithm and a plugable processing system to convert JS values and objects to a non-cryptographic hash.

License: MIT License

JavaScript 8.65% TypeScript 91.35%

samir's Introduction

Samir

OK, I'll do it.

Goals

Samir uses an incremental implementation of the MurmurHash3 (32-bit) hashing algorithm and a plugable processing system to convert JS values and objects to a non-cryptographic hash. Co-worker of Smykowski and Milton.

Features

  • Extensible
  • Incremental

Install

npm i @hypercubed/samir

Usage

import { Samir, defaultPlugins } from '@hypercubed/samir';

const hasher = new Samir();
hasher.use(defaultPlugins);

const obj: any = {
  null: null,
  numbers: [
    3.14159,
    NaN,
    Infinity,
    -Infinity,
    -0
  ],
  strings: {
    empty: '',
    string: 'foo',
    multiline: `
    This
    is
    multiline
    `
  },
  arrays: {
    empty: [],
    array: [ 'one', 'two', 'three' ]
  },
  nested: { hello: 'hapi' },
  false: false,
  true: true,
  undef: undefined,
  regexp: /.*\n/g,
  function: function Yes() { /* noop */ },
  map: new Map([['key1', 'value1'], ['key2', 'value2']]),
  set: new Set([1, 2, 3]),
  date: new Date('1972-02-12T03:24:00'),
  objects: {
    class: Samir,
    instance: hasher
  }
};

obj.self = obj;
console.log(hasher.hash(obj));

prints:

1394490113

Incremtental hashing:

hasher
  .reset()                // resets the hash
  .update('Hello');

// Sometime later

hasher
  .update(' World!');

console.log(hasher.result());  // Same as hasher.hash('Hello World')

Description

Samir is an interface for hashing JS objects and values. In Samir we have a concept of plugins and presets. Plugins are functions that define a "replacer" functions. Replacer functions accept each value and returns a stringified result (or the original value). The value returned by the replacer function replaces the original value in the hashed result. Values returned from one replacer are passed down to the next untill the replacer returns a string. Once a string is returned this string value is incrementally added to the hash.

Plugins are added using the .add method on a Samir instance. The order of the plugins does matter. The first plugin to return a string wins.

Presets are ordered sets of plugins. You may use a preset by invoking the .use method on a Samir instance.

| .............................. hash ................................ |
        | .................... preset ................... |
        | ... plugin ... |

           +----------+     +----------+     +----------+
Input  --> | Replacer | --> | Replacer | --> | Replacer | --> Output
           +----------+     +----------+     +----------+

Presets and plugins may be used together:

const hasher = new Samir();
hasher
  .use(defaultPlugins)
  .add(myPlugin);

Presets

  • defaultPlugins - includes all plugins below, in the order listed, with defualt settings.

(see presets.ts for more)

Plugins

  • primitives - Generates hashes for primitive JS values, by default number, boolean, bigint, undefined, and null.
  • symbols - Generates hashes for symbols. Global symbols generate repeatable hashes. Ordinary symbols are unique and generate random hashes (repeatable within a JS environment)
  • functions - Genertates hases for functions based on toString. Native functions use the native function name.
  • dataTypes - Handles JS object types like Date (based on getTime), Error (based on stack) and RegExp (based on toString).
  • buffer - Generates hashes for Buffers
  • reference - Captures and replaces repeated object references. Improves hashing speed by not decending repeated itmes and allows cirecular objects and arrays.
  • arrayDecender - Recursively processes arrays
  • objectDecender - Recursively processes enumerable keys on objects, key order agnostic.
  • setMap - Recursively processes Maps and Set. Map is key order agnostic.

(see plugins.ts for more)

Writing Plugins and Presets

A plugin is a function that accepts an options object, the root value (the first value passed to the samir#hash or samir#update method), and a "continue" function used for recursion. Each plugin must return a replacer/visitor function that is called (recursively) on each value to be hashed.

For example here is very simple plugin that will handle a hypothetical Decimal class:

const decimalPlugin = () => (s: any) => {
  if (s instanceof Decimal) {
    return `$float#${s.toString()}`;
  }
  return s;
};

It is importrant that the replacer function return the input value if it is unaltered.

(see plugins.ts for more)

Presets are functions that add plugins to a samir instance in a desiered order. For example:

function mySamirPlugins(_: samir) {
  _.add(decimalPlugin);
  _.add(primitives);

  _.add(reference);

  _.add(arrayDecender);
  _.add(objectDecender);

  return _;
}

API

Class Samir

Creates a new Samir instance with it's own Murmur3 incremental hasher

new Samir()

Method samir.add(plugin[, options])

Adds a plugin to a Samir instance

add(plugin: Plugin, options?: any): this
  • plugin - A function that initializes and returns a replacer
  • options (optional, default = null) โ€” Configuration for plugin

Method samir.use(preset)

Adds a preset (set of plugins) to a Samir instance

use(preset: Preset, ...args?: any[]): this
  • preset - A adds plugins to a samir instance in the desired order
  • args - Arguments taht are passed to the preset on initialization

Method samir.reset(seed)

Resets the state object and using (optionally) the given seed (defaults to 0).

reset(seed?: number = 0): this
  • seed (optional, default = 0) - the hashing seed

Method samir.update(value)

Pass the value through the added replacers, incrementally adding the resulting string to the hash.

update(value: any): this
  • value - any value/object to hash as supported by the plugins

Method samir.result()

Get the result of the hash as a 32-bit positive integer.

result(): number

Method samir.hash(value, seed)

Reset the hash, update with a value, return the result. Calling instance.hash(value, seed) is the same as instance.reset(seed).update(value).result().

hash(value: any, seed?: number = 0): number
  • value - any value/object to hash as supported by the plugins
  • seed (optional, default = 0) - the hashing seed

Replacer

type Replacer = (s: any, p: Path, value: any) => any ;

Plugin

type Plugin = (options: any, root: any, cont: StringifyFunction) => Replacer;

Preset

type Preset = (samir: samir) => samir;

License

This project is licensed under the MIT License - see the LICENSE file for details

samir's People

Contributors

dependabot[bot] avatar hypercubed avatar renovate-bot avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.