Simple validation for Rust structs

Overview

validator

Build

Macros 1.1 custom derive to simplify struct validation inspired by marshmallow and Django validators.

The minimum supported version is Rust 1.42.

Installation:

[dependencies]
validator = { version = "0.12", features = ["derive"] }

A short example:

use serde::Deserialize;

// A trait that the Validate derive will impl
use validator::{Validate, ValidationError};

#[derive(Debug, Validate, Deserialize)]
struct SignupData {
    #[validate(email)]
    mail: String,
    #[validate(phone)]
    phone: String,
    #[validate(url)]
    site: String,
    #[validate(length(min = 1), custom = "validate_unique_username")]
    #[serde(rename = "firstName")]
    first_name: String,
    #[validate(range(min = 18, max = 20))]
    age: u32,
}

fn validate_unique_username(username: &str) -> Result<(), ValidationError> {
    if username == "xXxShad0wxXx" {
        // the value of the username will automatically be added later
        return Err(ValidationError::new("terrible_username"));
    }

    Ok(())
}

match signup_data.validate() {
  Ok(_) => (),
  Err(e) => return e;
};

A validation on an Option<_> field will be executed on the contained type if the option is Some. The validate() method returns a Result<(), ValidationErrors>. In the case of an invalid result, the ValidationErrors instance includes a map of errors keyed against the struct's field names. Errors may be represented in three ways, as described by the ValidationErrorsKind enum:

#[derive(Debug, Serialize, Clone, PartialEq)]
#[serde(untagged)]
pub enum ValidationErrorsKind {
    Struct(Box<ValidationErrors>),
    List(BTreeMap<usize, Box<ValidationErrors>>),
    Field(Vec<ValidationError>),
}

In the simple example above, any errors would be of the Field(Vec<ValidationError>) type, where a single ValidationError has the following structure:

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ValidationError {
  pub code: Cow<'static, str>,
  pub message: Option<Cow<'static, str>>,
  pub params: HashMap<Cow<'static, str>, Value>,
}

The value of the field will automatically be added to the params with a key of value.

Note that validator works in conjunction with serde: in the example we can see that the first_name field is renamed from/to firstName. Any error on that field will be in the firstName key of the hashmap, not first_name.

The other two ValidationErrorsKind types represent errors discovered in nested (vectors of) structs, as described in this example:

use serde::Deserialize;
// A trait that the Validate derive will impl
use validator::Validate;

#[derive(Debug, Validate, Deserialize)]
struct SignupData {
   #[validate]
   contact_details: ContactDetails,
   #[validate]
   preferences: Vec<Preference>,
   #[validate(required)]
   allow_cookies: Option<bool>,
}

#[derive(Debug, Validate, Deserialize)]
struct ContactDetails {
   #[validate(email)]
   mail: String,
   #[validate(phone)]
   phone: String
}

#[derive(Debug, Validate, Deserialize)]
struct Preference {
   #[validate(length(min = 4))]
   name: String,
   value: bool,
}

match signup_data.validate() {
 Ok(_) => (),
 Err(e) => return e;
};

Here, the ContactDetails and Preference structs are nested within the parent SignupData struct. Because these child types also derive Validate, the fields where they appear can be tagged for inclusion in the parent struct's validation method.

Any errors found in a single nested struct (the contact_details field in this example) would be returned as a Struct(Box<ValidationErrors>) type in the parent's ValidationErrors result.

Any errors found in a vector of nested structs (the preferences field in this example) would be returned as a List(BTreeMap<usize, Box<ValidationErrors>>) type in the parent's ValidationErrors result, where the map is keyed on the index of invalid vector entries.

Usage

You will need to import the Validate trait.

The validator crate can also be used without the custom derive as it exposes all the validation functions and types.

Validators

The crate comes with some built-in validators and you can have several validators for a given field.

email

Tests whether the String is a valid email according to the HTML5 regex, which means it will mark some esoteric emails as invalid that won't be valid in a email input as well. This validator doesn't take any arguments: #[validate(email)].

url

Tests whether the String is a valid URL. This validator doesn't take any arguments: #[validate(url)];

length

Tests whether a String or a Vec match the length requirement given. length has 3 integer arguments:

  • min
  • max
  • equal

Using equal excludes the min or max and will result in a compilation error if they are found.

At least one argument is required with a maximum of 2 (having min and max at the same time).

Examples:

const MIN_CONST: u64 = 1;
const MAX_CONST: u64 = 10;

#[validate(length(min = 1, max = 10))]
#[validate(length(min = 1))]
#[validate(length(max = 10))]
#[validate(length(equal = 10))]
#[validate(length(min = "MIN_CONST", max = "MAX_CONST"))]

range

Tests whether a number is in the given range. range takes 1 or 2 arguments min and max that can be a number or a value path.

Examples:

const MAX_CONSTANT: i32 = 10;
const MIN_CONSTANT: i32 = 0;

#[validate(range(min = 1))]
#[validate(range(min = "MIN_CONSTANT"))]
#[validate(range(min = 1, max = 10))]
#[validate(range(min = 1.1, max = 10.8))]
#[validate(range(max = 10.8))]
#[validate(range(min = "MAX_CONSTANT"))]
#[validate(range(min = "crate::MAX_CONSTANT"))]

must_match

Tests whether the 2 fields are equal. must_match takes 1 string argument. It will error if the field mentioned is missing or has a different type than the field the attribute is on.

Examples:

#[validate(must_match = "password2")]
#[validate(must_match(other = "password2"))]

contains

Tests whether the string contains the substring given or if a key is present in a hashmap. contains takes 1 string argument.

Examples:

#[validate(contains = "gmail")]
#[validate(contains(pattern = "gmail"))]

regex

Tests whether the string matches the regex given. regex takes 1 string argument: the path to a static Regex instance.

Examples:

lazy_static! {
    static ref RE_TWO_CHARS: Regex = Regex::new(r"[a-z]{2}$").unwrap();
}

#[validate(regex = "RE_TWO_CHARS")]
#[validate(regex(path = "RE_TWO_CHARS"))]

credit_card

Test whether the string is a valid credit card number.

Examples:

#[validate(credit_card)]

phone

Tests whether the String is a valid phone number (in international format, ie. containing the country indicator like +14152370800 for an US number β€” where 4152370800 is the national number equivalent, which is seen as invalid). To use this validator, you must enable the phone feature for the validator crate. This validator doesn't take any arguments: #[validate(phone)];

custom

Calls one of your functions to perform a custom validation. The field will reference be given as a parameter to the function, which should return a Result<(), ValidationError>.

Examples:

#[validate(custom = "validate_something")]
#[validate(custom = "::utils::validate_something")]
#[validate(custom(function = "validate_something"))]

You can also parse arguments from the validation function to your custom validation by setting the arg parameter. arg can only be set to one type but you can set it to a tuple to pass multiple types at once. Defining the arg parameter will implement the ValidateArgs trait with the corresponding function types like this:

use validator::{Validate, ValidateArgs, ValidationError};

fn validate(value: &str, arg: (i64, i64)) -> Result<(), ValidationError> {
    [...]
}

#[derive(Debug, Validate)]
struct TestStruct {
    #[validate(custom(function = "validate", arg = "(i64, i64)"))]
    value: String,
}

let test_struct: TestStruct = [...]
test_struct.validate_args((77, 555)).is_ok();

It is also possible to pass references by using the lifetime 'v_a not that this lifetime should only be used for the function parameters like this:

fn validate_value(_: &str, arg: &mut Database) -> Result<(), ValidationError> {
    [...]
}

#[derive(Debug, Validate)]
struct TestStruct {
    //                                                     vvvv This is the lifetime for references
    #[validate(custom(function = "validate_value", arg = "&'v_a mut Database"))]
    value: String,
}

let mut database: Database = [...]
let test_struct: TestStruct = [...]
test_struct.validate_args(&mut database).is_ok();

Custom validation with arguments doesn't work on nested validation. See validator_derive_tests/tests/custom.rs and validator_derive_tests/tests/custom_args.rs for more examples.

nested

Performs validation on a field with a type that also implements the Validate trait (or a vector of such types).

Examples:

#[validate]

non_control_character

Tests whether the String has any utf-8 control caracters, fails validation if it does. To use this validator, you must enable the unic feature for the validor crate. This validator doesn't take any arguments: #[validate(non_control_character)];

required

Tests whether the Option<T> field is Some;

required_nested

Tests whether the Option<T> field is Some and performs validation as nested do;

Struct level validation

Often, some error validation can only be applied when looking at the full struct, here's how it works here:

#[derive(Debug, Validate, Deserialize)]
#[validate(schema(function = "validate_category", skip_on_field_errors = false))]
struct CategoryData {
    category: String,
    name: String,
}

The function mentioned should return a Result<(), ValidationError> and will be called after validation is done for all fields.

The skip_on_field_errors defaults to true if not present and will ensure that the function is not called if an error happened while validating the struct fields.

Any error on the struct level validation will appear in the key __all__ of the hashmap of errors.

Message and code

Each validator can take 2 optional arguments in addition to their own arguments:

  • message: a message to go with the error, for example if you want to do i18n
  • code: each validator has a default error code (for example the regex validator code is regex) but it can be overriden if necessary, mainly needed for the custom validator

Note that these arguments can't be applied to nested validation calls with #[validate].

For example, the following attributes all work:

// code attribute
#[validate(email(code = "code_str"))]
#[validate(credit_card(code = "code_str"))]
#[validate(length(min = 5, max = 10, code = "code_str"))]

#[validate(regex(path = "static_regex", code = "code_str"))]
#[validate(custom(function = "custom_fn", code = "code_str"))]
#[validate(contains(pattern = "pattern_str", code = "code_str"))]
#[validate(must_match(other = "match_value", code = "code_str"))]

// message attribute
#[validate(url(message = "message_str"))]
#[validate(length(min = 5, max = 10, message = "message_str"))]

#[validate(regex(path = "static_regex", message = "message_str"))]
#[validate(custom(function = "custom_fn", message = "message_str"))]
#[validate(contains(pattern = "pattern_str", message = "message_str"))]
#[validate(must_match(other = "match_value", message = "message_str"))]

// both attributes
#[validate(url(message = "message", code = "code_str"))]
#[validate(email(code = "code_str", message = "message"))]
#[validate(custom(function = "custom_fn", code = "code_str", message = "message_str"))]
Comments
  • Arguments for custom validation functions. #38

    Arguments for custom validation functions. #38

    This was quite an experience to create but a fun one :)

    Okay, the implementation is pretty similar to the plan I described in #38. The implementation is based on the ValidateArgs<'v_a> trait:

    pub trait ValidateArgs<'v_a> {
        type Args;
    
        fn validate_args(&self, args: Self::Args) -> Result<(), ValidationErrors>;
    }
    

    The usual Validate implementation simply references the ValidateArgs<'v_a> implementation. The custom validator now takes an arg parameter that can be set to one type. Here are some examples:

    // fn validate_tuple(value: &str, tuple: (i64, i64)) -> Result<(), ValidationError>
    #[validate(custom(function = "validate_tuple", arg = "(i64, i64)"))]
    value: String
    // instance.validate_args((77, 555));
    
    // fn validate_with_db(value: &str, db: &mut Database) -> Result<(), ValidationError>
    #[validate(custom(function = "validate_with_db", arg = "&'v_a mut Database"))]
    value: String
    // instance.validate_args(&mut db_instance);
    

    More examples can be seen in the tests. The tests also include some error messages in the compile-fail folder.


    The implementation also support arguments in multiple custom validators by packing them into a tuple like this:

    #[derive(Debug, Validate)]
    struct TestStruct {
        #[validate(custom(function = "validate_tuple", arg = "(i64, i64)"))]
        tuple_validation: String,
    
        #[validate(custom(function = "validate_with_db", arg = "&'v_a mut Database"))]
        db_validation: String
    }
    // Args type: ((i64, i64), &'v_a mut Database)
    //
    //                        |<-- Args tuple          -->|
    // instance.validate_args(((77, 555), &mut db_instance));
    //                         |<--1-->|  |<--    2   -->|
    //      1. Tuple from tuple_validation
    //      2. Reference from validate_with_db
    

    This implementation doesn't support schema validation. But it should be extendable if that is required.


    TODOs:

    • [x] Improve error reporting for types with unknown size
    • [x] Save syn::Type instead of string in the Validator enum

    btw: I find the readme a bit unreadable due to it's length by now. I tried to use <details> tags to hide some content. Here is an example. I can merge it if this is interesting to you as well. It's sadly not the perfect solution -.- Link

    Hello Hello World
    opened by xFrednet 47
  • Nested Validation

    Nested Validation

    I've made an implementation of nested struct validation. It uses plain [#validate] attributes added to a parent struct's fields in order to detect which nested structs should be validated. With specialization, it could work without the field attribute as we could speculatively validate all fields, having a default no-op trait implementation for cases where a struct has no real validations to execute. But currently this would have required using nightly so I opted for the explicit attribute approach instead. Also, this gives the user more control over which sub-structs to opt-in for validation.

    I aimed to avoid changing the API of the existing library; the main observable difference I think is that the ValidationErrors HashMap is now keyed with a String instead of a &' static str. I don't know if this will make much difference in real world usage; it didn't cause existing tests to fail at least. The ValidationErrors keys use a path.to.nested.field format to indicate the position of invalid nested fields, and each ValidationError instance includes that path as a ["path", "to", "nested", "field"] vector for convenience.

    This implemetation also works with Optional nested structs and Vectors of nested structs (but currently not combinations of the two).

    Keats/validator#31 Keats/validator#51

    opened by simonsparks 14
  • Better display implementation

    Better display implementation

    As discussed a little in #80, this PR adds a slightly nicer Display implementation which prints the paths to each error, and then either a generic description of the error, or the provided error message.

    See the added tests for the format.

    opened by dyedgreen 13
  • Question: why I can't find .validate() function

    Question: why I can't find .validate() function

    Hi there,

    I'm a Rust beginner started a few days ago. I'm trying to design a server-side Kanban app (like Trello etc) with Actix-web and MongoDB. I'm trying to use your validator library to validate the user registration form. However, my IDE tells me it can't find the validate() function. Did I forget to add something?

    Here's my project repo: https://github.com/huming2207/shachiku-rs

    And here's my environment:

    • Host OS: Linux (Manjaro stable)
    • Rust 1.41.1
    • IDE: Intellij IDEA or CLion + Intellij Rust
    • validator: 0.10.0

    Here's my struct, in src/controller/auth.rs:

    image

    As you can see in src/service/auth.rs, seralize and deserialize works:

    image

    However, there's no such option for validate:

    image

    Could you please give me some ideas? Thanks in advance!

    Regards, Jackson

    opened by huming2207 13
  • Define a format for errors and/or allow user defined error messages

    Define a format for errors and/or allow user defined error messages

    Right now it only returns the error code for the validation that failed, which is enough for me as I usually have control of both frontend and backend and just want to know which bit failed on which field.

    However, having some more verbose error or user-defined ones (or both) would be welcome. For example when sending error message to a third party doing an API calls or if you don't control the frontend and need to send all the info (args used for the validator) to it.

    A few things to consider:

    Serialize validators

    Change the error type of validate from Result<(), HashMap<String, Vec<String>>> to Result<(), HashMap<String, Vec<Validator>>> and have Validator manually (so we can add their name) implement Serialize from Serde.

    Pros That's the easy option since this way we will get the name of the validator and all its args easily Cons Doesn't really work if we want custom error messages

    Custom message

    Add an optional error_msg field to every single validator that will be sent with the error code. Sending only the error message makes it less flexible wrt if the frontend wants to change it, so we should it still have both error code and error. Error type will be Result<(), HashMap<String, Vec<(String, Option<String>)>>>

    Default error messages

    A neat way to do that would be to impl a function on Validator that returns a default error message. I would ignore i18n in default error messages as I don't think it will provide a good end user interface since end users will end up with errors like "Bank account number must match [0-9]{7}" or something like that that I got today with Transferwise. Proper error messages should be built by using the serialized validators in the frontend or just overwritten in the backend directly. There are also too many format for i18n and afaik not library for it in Rust yet.

    The user could iterate on the errors hashmap or we could even impl a function on the hashmap directly so the user can do something like if they just want a hashmap with error messages:

    match signup_data.validate() {
       Ok(()) => (),
       Err(e) => return e.get_error_messages()
    };
    

    which could be turned into a validate_or_error_messages! macro easily

    If that approach works, it could be extended to transform errors into i18n objects potentially

    Current thoughts

    I like the idea of serializing validators and having default error messages if wanted but I'm not sure where the custom error messages fit in that system. Ideally we'd have String | Validator as type for the value of hashmap but that's not possible in Rust. Another option is (Validator, Option<String>). The main issue would be what to do with the custom validator since you can have multiple kind of errors and how to work with serialization errors if we decide to let validator handle those (for consistent errors)

    question 
    opened by Keats 13
  • How to pass args to custom validators?

    How to pass args to custom validators?

    I want to have a validator that works like length but uses the byte length of a string (or rather, the length after converting utf8 to cp852).

    How can I pass the len arg to that custom validation function?

    help wanted 
    opened by Boscop 12
  • Reexport validator_derive macros from validator crate

    Reexport validator_derive macros from validator crate

    This solution is admittedly a little silly, but it's a working attempt at exporting the derive macro from the validator crate. I'm happy to modify this in any way that meshes best with how the library should be structured.

    I also added a root Cargo.toml to turn the repo into a workspace sine the validator crate is the main and only entry point to behavior.

    The changes here are a little sweeping with regards to the ui tests, so I understand if there's reticence there. I switched from compiletest-rs to trybuild for its ease-of-use and its ability to use Rust 2018 macro imports transparently (no need for extern crate, just use validator::Validate works). I also had to drop the pinned version since it looks like an upstream dependency no longer builds on Rust 1.36 (object it looks like?).

    This should resolve #58.

    opened by ELD 11
  • Add a phone number validator

    Add a phone number validator

    This validator can be handy when writing APIs, where the front-end does the work of retrieving a country and national phone number, and generating an international phone number (eg. +33xxxxx, +1xxxxx, etc).

    I used on the best phone number validation library I could find (phonenumber), which unfortunately has a lot of dependencies. Thus, I added a phone feature to validator.

    Note that it does not work given a national (non-international) number (eg. 06xxxxx w/o the country indicator), as the library cannot figure out the country by itself to validate the local number (it can be provided to phonenumber, but it's a bit of an overhead for validator purposes here).

    The unit tests are all green for the validator part. However, I couldn't figure how to properly test /write the validator_derive part, knowing phone is an optional feature. Any hint on this? πŸ™‚

    I did a first commit for validator, and a second commit for validator_derive to separate things properly for your review.

    Cheers!

    opened by valeriansaliou 10
  • Make `must_match` work with Option?

    Make `must_match` work with Option?

    Not sure if it even make sense to be honest, I had

    pub fn validate_must_match<T>(a: T, b: T) -> bool
        where
            I: Eq,
            T: Into<Option<I>>,
            T2: Into<Option<I>>,
    {
        let a = a.into();
        let b  = b.into();
        if a.is_none() && b.is_none() {
            return true;
        }
        if !(a.is_some() && b.is_some()) {
            return false;
        }
        a == b
    }
    

    before removing it

    question 
    opened by Keats 10
  • added message for required

    added message for required

    When passing a message or code to the required attribute I get the following errors: unexpected list validator: "required" and no method namedvalidatefound for structcan_specify_message_for_required::TestStructin the current scope

    I guess the required attribute doesn't take in any additional arguments? I'm still figuring out how to add that, here I just copied the tests from other attributes.

    opened by pintariching 9
  • Allow passing multiple schema-level validations

    Allow passing multiple schema-level validations

    Hello, this is the re-implementation of https://github.com/Keats/validator/pull/62 to allow passing multiple schema-level validations, e.g.

    fn invalid_schema_fn(_: &TestStruct) -> Result<(), ValidationError> {
        Err(ValidationError::new("meh"))
    }
    
    fn invalid_schema_fn2(_: &TestStruct) -> Result<(), ValidationError> {
        Err(ValidationError::new("meh2"))
    }
    
    #[derive(Debug, Validate)]
    #[validate(schema(function = "invalid_schema_fn"))]
    #[validate(schema(function = "invalid_schema_fn2"))]
    struct TestStruct {
        val: String,
    }
    

    All tests pass and the implementation seems to be alright. The only thing that bugs me is now I'm getting a Clippy warning, which I frankly don't know how to fix yet. Macro is complex and I feel slightly lost in it. Here's the warn:

    Unnecessary nested match
    `#[warn(clippy::collapsible_match)]` on by default
    for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_matchclippycollapsible_match
    lib.rs(104, 38): The outer pattern can be modified to include the inner pattern.
    lib.rs(207, 9): Error originated from macro here
    
    opened by buinauskas 9
  • Implement Validate for `Option<T: Validate>`

    Implement Validate for `Option`

    Currently, option validation is done through the proc macro by checking if the type starts with Option< this is causing problems for me because I have to use the full path to option (std::option::Option) due to a bug in another crate. I may be missing something, but why not just do something like this:

    impl<T: Validate> for Option<T> {
        pub fn validate(&self) -> Result<(), ValidateError> {
            if let Some(inner) = self {
                inner.validate()
            }
        }
    }
    

    Other than this we could check if someone is using the full path when doing option unwrapping in the proc macro. I'd be willing to do a pr for either, just checking to see what aligns with the goals of this crate the most.

    opened by tsar-boomba 1
  • Improve Display Impl - Each ValidationError should be on its own line

    Improve Display Impl - Each ValidationError should be on its own line

    The current impl for Display doesn't break newlines frequently enough.

    The display output of the list variant of ValidationErrorsKind currently looks like the following:

    my_field[0].subfield: Validation error: Some error. [{"value": String("some-value")}]my_field[1].subfield: Validation error: Some error. [{"value": String("some-value-2")}]
    other_field[0].other: Validation error: Other error [{"value": String("other-value")}]
    

    It only breaks line when the top-level field of the ValidationErrors changes. I would prefer for it to look like the following:

    my_field[0].subfield: Validation error: Some error. [{"value": String("some-value")}]
    my_field[1].subfield: Validation error: Some error. [{"value": String("some-value-2")}]
    
    other_field[0].other: Validation error: Other error [{"value": String("other-value")}]
    

    It seems pretty clear that separate field-level errors belong on their own line - having multiple on the same line always looks bad. Having multiple line-breaks when the top-level field changes doesn't feel like a regression either, but we could remove the existing writeln! call if we wanted a maximum of 1 new line after every error display.

    opened by aarashy 4
  • Always first perform least expensive validations

    Always first perform least expensive validations

    Basically, first perform length-checks (especially for arrays) and only then perform all other checks. Perform custom checks last.

    This is to aid as an additional buffer against primitive DOS attacks.

    enhancement 
    opened by Glitchy-Tozier 0
  • ValidationError - Dynamic code and message

    ValidationError - Dynamic code and message

    Currently, ValidationError expects nothing but static string references for code, message and the key for the params. This works well in the majority of cases where we know at compile time which field we are validating.

    However, I have a use case where I am validating random data (from serde json) against a soft schema stored in the database. Therefore, the fields to validate are not known at compile time, therefore static string references cannot be used.

    https://github.com/Keats/validator/blob/master/validator/src/types.rs

    Im fairly new to rust so I am not 100% sure if there is something I can do in my app to work around this or if this use case needs a change to this library ?

    If the latter, is the change possible ? I am happy to do a PR for it

    opened by garytaylor 6
  • Large integers may lose some lowest bits in `range`

    Large integers may lose some lowest bits in `range`

    #[test]
    fn test() {
        #[derive(Debug, Validate)]
        struct TestStruct {
            #[validate(range(max = 10000000000000000))]
            val: u64,
        }
        let s = TestStruct { val: 10000000000000001 };
        assert!(s.validate().is_err());
    }
    
    opened by zhu-he 0
Owner
Vincent Prouillet
Vincent Prouillet
Simple node and rust script to achieve an easy to use bridge between rust and node.js

Node-Rust Bridge Simple rust and node.js script to achieve a bridge between them. Only 1 bridge can be initialized per rust program. But node.js can h

Pure 5 Apr 30, 2023
The simple password manager for geeks, built with Rust.

Rooster Rooster is a simple password manager for geeks (it works in the terminal). Rooster is made available free of charge. You can support its devel

Conrad Kleinespel 131 Dec 25, 2022
A simple password manager written in rust

Passman - A password manager written in rust. How to use?: USAGE: passman option Currently available options are: new - initalize passman with a new m

Strawkage 7 Aug 26, 2021
A simple password manager written in Rust

ripasso A simple password manager written in Rust. The root crate ripasso is a library for accessing and decrypting passwords stored in pass format (G

Joakim Lundborg 550 Dec 30, 2022
Simple template for building smart contract(Rust) and RPC Client(web3.js) on Solana (WIP) β›πŸ‘·πŸš§βš οΈ

Solana BPF Boilerplate Simple template for building smart contract(Rust) and RPC Client(web3.js) on Solana This boilerplate provides the following. Si

ono 6 Jan 30, 2022
Simple example for building a blockchain in Rust

rust-blockchain-example Simple example for building a blockchain in Rust Start using RUST_LOG=info cargo run This starts the client locally. The block

mario 51 Dec 31, 2022
A simple frontend web app in the seed.rs Rust framework.

Seed Quickstart Basic Rust-only template for your new Seed app. 1. Create a new project You can use cargo generate to use this template. $ cargo gener

null 0 Dec 24, 2021
A simple test on interacting between languages with JS and Rust.

NODE-JS-RUST-FFI A simple test on interacting between languages with JS and Rust. How to run Requirements nodejs rustc + cargo Compile First compile t

Eder Lima 3 Aug 25, 2022
Simple rust library for NFT metadata w/ an easy server

NFT Server Simple rust lib for NFT Metadata, and a basic axum server for delivering it $ cargo build $ cargo clippy $ cargo run --bin example Usage I

Nomad 6 Nov 4, 2022
Simple to use CLI tool that makes encryption easy! Written in Rust.

?? eme: Encryption Made Easy an extremely simple AES-256 encryption tool written in Rust Usage: # To encrypt: eme --encrypt secret.png # To decrypt: e

null 5 Jan 3, 2023
A pretty simple tool for password generation, written in Rust.

passwdgen A pretty simple tool for password generation, written in Rust. Usage: passwdgen - a pretty simple tool for password generation Usage: passw

Kirill Belolipetsky 9 Feb 19, 2023
Simple shared types for multi-threaded Rust programs

Keep Calm (and call Clone) Simple shared types for multi-threaded Rust programs: keepcalm gives you permission to simplify your synchronization code i

Matt Mastracci 5 Mar 6, 2023
πŸ—‚οΈ A simple, opinionated, tool, written in Rust, for declaratively managing Git repos on your machine.

gitrs ??️ A simple, opinionated, tool, written in Rust, for declaretively managing Git repos on your machine. "simple" - limited in what it supports.

Colton J. McCurdy 14 May 30, 2023
a simple rust service for Scheduling commands execution on time basis, an easy alternative to cron

Tasker A Simple crate which provides a service and a configuration API for genrating commands based tasks ,on time basis. Installation build from sour

Daniel Madmon 5 Jun 1, 2023
A simple and secure rust command-line tool to protect your text by encrypting and decrypting it using the robust AES-256 algorithm.

Secret Keeper A simple and secure command-line tool to protect your text by encrypting and decrypting it using the robust AES-256 algorithm. Built wit

Kunal Bagaria 9 May 11, 2023
Simple EVM implementation from scratch using Rust.

smol-evm-rs β€’ smol-evm-rs is a Rust port of the smol-evm project, originally implemented in Python by karmacoma. This project aims to implement the Et

Pranesh A S 29 Dec 27, 2023
A Simple Rust NFT API + Smart Contract

Rust NFT API Purpose Rust NFT API is a simple RESTful API developed in Rust that offers functionalities for creating, retrieving, and listing Non-Fung

Luis Soares 5 Feb 25, 2024
Simple CI program for running fuzzing over TezEdge.

Fuzzing CI This program is designed to run fuzzing on selected branches of a source project, restarting it as a new commit arrives. Building cargo bui

TezEdge 5 Aug 6, 2021
Simple automated proof assistant.

Esther is a work-in-progress, proof-of-concept automated theorem proof assistant based on Homotopy Type Theory. Acknowledgements Arend, Lean, Coq and

Aodhnait Γ‰taΓ­n 5 Sep 14, 2021