Coder Social home page Coder Social logo

strum's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

strum's Issues

Does not compile on rust 1.36.0

Although the docs state compatibility with 1.31.0

error[E0658]: use of unstable library feature 'iter_nth_back'
   --> src/main.rs:139:75
    |
139 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, EnumIter)]
    |                                                                           ^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/56995

error: aborting due to previous error

IntoEnumIterator: consider using standard IntoIterator instead

It would be nice if strum could incapsulate a bit more its implementation details.

In particular, I'd like to avoid having strum::IntoEnumIterator to be imported by all consumers, and instead use the IntoIterator one from stdlib.
That one however is a consuming method, so I'm not sure if it can be transparently adopted. An alternative would be to drop the trait completely and just expose a naked iter() like most collection types do.

Convert isize to enum variant

Sometimes we need to convert isize to an enum variant with explicit discriminator.
enum/c_like
For example, high level API converts error code to an error enum variant. The feature will be useful when it comes to unsafe and FFI.

The solution is to implement a proc macro like:
proc_macro_derive(EnumFromIsize)

The generated code will look like:

impl TryFrom<isize> for MyEnum {
    type Error = StrumCustomError;
    fn try_from(u: isize) -> Result<MyEnum, StrumCustomError> {
        match u {
            // ......
        }
    }
}

EnumIter construction

As it currently is, Strum's EnumIterator trait only allows for the construction of enum iterators from the first variant, which makes it horribly inefficient (relatively speaking) to perform incremental iteration of enum variants. A means of constructing this iterator so it starts from an existing enum would resolve this.

Add EnumCount derive

I wrote this proc-macro because I needed it (for mapping Enum cases from different enums to Vec regions, making the Vec len equal to the combined number of all cases) and I think it would make sense to include it in this crate, because it already contains many useful derives for enums.
https://github.com/Boscop/enum-count/blob/master/src/lib.rs
https://github.com/Boscop/enum-count-derive/blob/master/src/lib.rs

It allows stuff like this:

#[derive(EnumCount)] enum Aa { }

#[derive(EnumCount)]
enum Bb { B0 = AA_COUNT as _ }

#[repr(u8)]
#[derive(EnumCount)]
enum Cc { C0 = AA_COUNT as _, C1 = BB_COUNT as _ }

#[repr(usize)]
#[derive(EnumCount)]
enum Dd { D0 = AA_COUNT, D1 = BB_COUNT, D2 = CC_COUNT }

fn main() {
	println!("{} {} {} {}", Aa::count(), BB_COUNT, Cc::count(), DD_COUNT);
}

(The constant is necessary for it to be used in other enums and static array lens etc.)

EnumProperty other than String?

When will it be possible to use EnumProperty with other types than String?
Are only literals supported or full expressions? :)

How do I add docstrings to discriminants?

First of all, thanks for this crate!

I'm refactoring some code to use the discriminants and would like to keept the documentation and doctests on the discriminant enum. Is there any way I can do that?

Can enum::count() be a const function?

When EnumCount was introduced, there was a comment that the count() function could be const once the required feature get stabilized in Rust. It seems to me it is possible now, but I'm not a Rust expert yet, so I could be wrong. What is your opinion of this?

As a side effect, this could get rid of the X _COUNT constants polluting the public namespace, but I don't know if you'd want to remove them due to backwards compatibility. However, according to semver, version 0.x.y does not provide any guarantees, so the users should not have any assumptions anyway.

Attribute to format field names

I would like to be able to do something like this

#[derive(Display)]
#[strum("series.{}", serialize_all = "snake_case")]
struct Series {
    Media
}

assert_eq!(Series::Media.to_string(), "series.media".to_string());

The attribute could also look like this

#[strum(format = "series.{}", serialize_all = "snake_case")]

The implementation would be relatively simple (I think?):

use syn::LitStr;

// parse this from the attribute:
let format_string = "series.{}".to_string();
// the serialized field name
let field_name = "media".to_string();

let lit_str = LitStr::new(&format_string.replace("{}", &field_name), Span::call_site());

quote {
    impl ::std::fmt::Display for Series {
        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
            match &self {
                Self::Media => f.write_str(#lit_str),
            }
        }
    }
}

EnumString: implement ToString/Display as well?

I was briefly looking at this crate, and I think I would love to see an automatic to_string() implementation and some way to link it to the current attributes-based approach employed for from_string(). This would allow for roundtrips Enum <-> String.

I'm actually thinking about something similar to serde ones plus additional aliases:

#[derive(EnumString)]
enum Color {
    #[strum(rename="blue",alias="b")]
    Blue,
    ...
}

impl std::str::FromStr for Color {
    fn from_str(s: &str) -> ::std::result::Result<Color, Self::Error> {
        match s {
               "blue" | "b" => ::std::result::Result::Ok(Color::Blue),
               ...
        }
    }
}

impl fmt::Display for Color {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
               Color::Blue => write!(f, "blue"),
               ...
        }
    }
}

There are also a bunch more interesting methods in https://docs.rs/enum_derive/0.1.7/enum_derive/#overview.

Implement From<&str> instead of FromStr for enums with lifetimes

FromStr doesn't support lifetimes, and I'd like the following to be possible:

#[derive(Debug, PartialEq, Eq, Clone, Copy, strum_macros::AsRefStr, strum_macros::EnumString)]
pub enum ChunkType<'a> {
    #[strum(to_string = "nMC")]
    MChat,
    #[strum(to_string = "nM")]
    MPlayer,
    #[strum(to_string = "nMR")]
    MRequest,
    #[strum(to_string = "nM?")]
    MServerInfo,
    #[strum(to_string = "nU")]
    UUpdate,
    #[strum(to_string = "\r\n")]
    Eof,
    #[strum(to_string = "nH")]
    HHead,
    #[strum(default = "true")]
    Unknown(&'a str),
}

Impl back from EnumDiscriminant

The derive for EnumDiscriminant is helpful, but it doesn't provide a way to convert back to the original enum whose variants it enumerates. Is this something that can be implemented?

Cannot use full-qualified path to trait inside `#[strum_discriminants(derive())]`

When trying to use full-qualified paths for the custom derive, none of the attributes are applied.

For example:

#[allow(dead_code)]
#[derive(Debug, Eq, PartialEq, strum_macros::EnumDiscriminants)]
#[strum_discriminants(name(SplitAttributesBoo), derive(strum_macros::Display))]
#[strum_discriminants(derive(strum_macros::EnumIter))]
enum SplitAttributes {
    Variant0(bool),
    Variant1(i32),
}

I digged a bit into the code and it actually looks like syn doesn't report the full path in that case. I googled around a bit and found a similar problem here: rust-lang/rust#55168

But not sure how relevant that actually is.
I created a PR that reproduces the issue here: #54.

Naming problems

I wonder how you manage the non-descriptive names like as_static, as_ref, when you have an enum that, e.g. describes a state:

enum MyState {
    Position1(i32),
    GameOver(String),
}

Having my_state.as_ref() or my_state.as_static() looks odd to me when I really want to express my_state.as_variant_name(). Currently, I have to write a 4-line wrapper around as_static just to make my API sane, but I still have a confusing AsStaticRef implementation in the documentation.

This is a small papercut, but I still want to bring it in.

I would prefer having AsEnumVariantName trait with as_enum_variant_name or as_variant_name method.

ToString: implement `Display`, std doc says "`ToString` shouldn't be implemented directly"

Rustdoc for ToString says:

ToString shouldn't be implemented directly: Display should be implemented instead, and you get the ToString implementation for free.

So derive(ToString) should implement std::fmt::Display instead of std::string::ToString (and by this, std::string::ToString would be automatically implemented).
Then derive(Display) or some other appropriate names would be preferable to derive(ToString).

This may be breaking changes (possibly rename ToString and to_string), but automatic derive for Display will be very useful.

Catchall for EnumString

Is there any way to provide a "catchall" option for EnumString that will store the parsed string into a variant?

Eg:

enum Fruit {
    Strawberry,
    Banana,
    Other(String),
}

Thanks!

Please update proc_macro2, quote, and syn to v1.0

hello!

we're currently updating proc-macro2, quote, and syn in Debian (which all recently reached 1.0). An update for strum-macros with those versions would be great (we're also able to cherrypick a patch if needed).

Thanks!

FromIndex and ToIndex traits

I'm interested in porting the FromIndex and ToIndex traits from enum_traits to this crate.

However I only care about the from_index and index methods. The other methods don't seem useful?

My reasoning is that enum_traits is unmaintained and its functionality seems similar enough to this crate.
What are your thoughts? Is this within scope of the project?

Release next version

Hiya! Thanks for this awesome crate ๐ŸŽ‰.
There are a number of fixes in master that help me along my quest โš”๏ธ.
Please could you release the crate ๐Ÿ“ฆ, or is there something that must first be done (like that open PR)?

EnumProperty: opting-in stronger guarantees on properties

Currently deriving EnumProperty results in a bunch of get*() -> Option<*>. This works quite well in general, but it moves some property checking to runtime option-handling.

What I'd like to see provided in this crate is some way of opting-in to stronger guarantees and typing of properties, such that I could:

  • annotate the enum to require that all variants declare some specific property
  • either annotate or infer the type of this mandatory property
  • generate specific getter for each mandatory property, such that there is a single get_prop() -> PropType generated

The usestory for this is: complex enums declarations (with attributes) can become quite long and some variants can end up with missing prop-attributes or with copy-paste type mistakes. Those would only be catched when unwrapping the Option at runtime, but the compiler should be able to sanity-check this at buildtime. Also it would make the getter more specifically named and remove the needs of Option wrapping.

Some hypotetical syntax (but feel free to design your one discarding this) could be:

#[derive(EnumProperty)]
#[strum(props(room: i32))]
enum Class {
    #[strum(props(teacher="foo", room=101))]
    History,
    #[strum(props(room=2))]
    Mathematics,
    #[strum(props(room=-1))]
    Science,
}

fn main() {
    let history = Class::History;
    assert_eq!(101, history.get_room());
}

Where adding a variant without the room prop or with a non-matching type would fail type-checking / compilation.

Derive enum with variants without fields

EnumIter and EnumString both work by using Default::default() values for any fields on an enum variant. I have a use case where I want to match on the enum's discriminant, but the fields are !Default.

To do this, I propose a #[derive(EnumDiscriminants)] as well as the attribute #[strum_discriminants(derive(..))], which will have the following effect:

struct NonDefault;

#[derive(EnumDiscriminants)]
#[strum_discriminants(
    name(HelloVariants),
    derive(EnumString, EnumIter),
    strum(serialize_all = "snake_case")
)]
enum Hello {
    Variant0,
    Variant1(NonDefault),
    Variant2 { a: NonDefault },
}

// produces:
/// Auto-generated discriminant variants for the `Hello` enum.
#[derive(Clone, Copy, Debug, PartialEq, Eq, EnumString, EnumIter)]
#[strum(serialize_all = "snake_case")]
enum HelloVariants {
    Variant0,
    Variant1,
    Variant2,
}

impl From<Hello> for HelloVariants {
    fn from(val: Hello) -> HelloVariants {
        match val {
            Hello::Variant0 => HelloVariants::Variant0,
            Hello::Variant1(..) => HelloVariants::Variant1,
            Hello::Variant2 { .. } => HelloVariants::Variant2,
        }
    }
}

impl<'_enum> From<&'_enum Hello> for HelloVariants {
    fn from(val: &'_enum Hello) -> HelloVariants {
        match *val {
            Hello::Variant0 => HelloVariants::Variant0,
            Hello::Variant1(..) => HelloVariants::Variant1,
            Hello::Variant2 { .. } => HelloVariants::Variant2,
        }
    }
}

Derived Display doesn't handle width and alignment parameters

For struct like:

#[derive(Display)]
enum Type {
    One,
    Two,
}

The call:

println!("_ {:<20} _", Type::One);

Will print:

_ One _

But this expected:

_ One                 _

The workaround today only to convert it to string first:

println!("_ {:<20} _", Type::One.as_ref()); // and derive `AsRefStr` for enum needed

Provide means to specify error string when matching variant is not found

Right now --when no matching variant is found-- (parsing a string into an enum using the derived from_str) a constant string error is returned saying "Matching variant not found". There are two improvements that can be done on this:

  • Better default: A better default would probably be something like "expected 'string1', 'string2', 'string3' or 'string4'". Even though it costs to iterate over the options, it doesn't matter, because it would only happen when no valid string is found.

  • Custom error: The user should be able to specify a custom error message, something like:

#[derive(EnumString)]
#[strum(onerror="We like you, but can't understand what you wrote, please use 'string1' or 'string2'")
enum Foo {
   #[strum(serialize="string1")]
   Option1,
   #[strum(serialize="string2")]
   Option2,
}

** special token: You could even provide a special token for the onerror keyword so that the user doesn't have to repeat the options all the time. Something like onerror="We like you, but can't understand what you wrote, please use {opts}".

I way to provide my own implementation.

Maybe I'm just dumb, but is there a way to do something like:

enum Compression {
Lz4,
Gzip(u8),
}

Compression::Gzip(9).to_string() # returns gzip-9
Compression::from_str("gzip-2") # returns Compression::Gzip(2)

Conflict with `display_derive`

The Display procedural macro unfortunately conflicts with @withoutboats' display_derive procedural macro. In some code I'm working with on a personal project, the following will compile when #[macro_use]ing only display_derive, but not in conjunction with strum_derive:

#[derive(Clone, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize)]
#[display(fmt = "{}", _0)]
pub struct MessageId(pub String);

Both of these crates are great additions to the ecosystem, in my opinion. It's a shame that we don't have macros as first-class items yet and that I have to choose between them. Perhaps disabling Display with a feature flag would be best for now?

EDIT: It's also possible to use the right crate's definition by making the desired derive be imported LAST...but that's a hacky workaround.

`serialize_all` should be "as-is"

rename_all from serde accepts kebab-case, camelCase, PascalCase, etc. The option string is just written in what itself representing to.

But serialize_all accepts all options in snake case, like kebab_case or shouty_snake_case, which can be sometimes misleading.

I think we should accept and prefer serde-like option string, while the snake case options can still be used for compatibility, maybe with a warning.

v0.14.0 missing from changelog

This project does have a CHANGELOG.md file (๐Ÿ‘), but it seems like the new v0.14.0 release is missing from it. What were the changes that went into that release? Were there any breaking changes?

0.15 breaks Display

The following piece of code:

#[macro_use]
extern crate strum_macros;

#[derive(Clone, Copy, Display, Debug, Serialize)]
#[strum(serialize_all = "snake_case")]
pub enum DataName {
    SecretHash,
    Expiry,
    RedeemIdentity,
    RefundIdentity,
    TokenQuantity,
    TokenContract,
}

Compiles with 0.14.0 but does not compile with 0.15.0:

error[E0658]: The attribute `strum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
  --> vendor/blockchain_contracts/src/lib.rs:16:3
   |
16 | #[strum(serialize_all = "snake_case")]
   |   ^^^^^
   |
   = help: add #![feature(custom_attribute)] to the crate attributes to enable
error: cannot find derive macro `Display` in this scope
  --> vendor/blockchain_contracts/src/lib.rs:15:23
   |
15 | #[derive(Clone, Copy, Display, Debug, Serialize)]
   |    

May I suggest to move the readme examples to rust-docs to avoid this kind of issue?

IntoEnumIterator should have a constraint on Iterator: Iterator<Item=Self>

IntoEnumIterator does not have a constraint on Iterator: Iterator<Item=Self>.
When writing generic code on any IntoEnumIterator, it forces us to write the very verbose:

where
	<Self as IntoEnumIterator>::Iterator: Iterator<Item = Self>,

though that behaviour could be enforced as it is documented on the trait.

We could avoid having to write this by adding an Iterator<Item=Self> bound on the associated type Iterator of IntoEnumIterator.

typo in docs

strum/strum/src/lib.rs

Lines 113 to 117 in b6e4e66

//! // It's simple to iterate over the variants of an enum.
//! fn debug_colors() {
//! let red = Color::Red;
//! assert_eq!(String::from("redred"), red.to_string());
//! }

Also the same type is in the Readme.

EnumString documentation lacking example

In the documentation and Wiki for EnumString , there is
//The generated code will look like:
but there is no actual code example how to use it.

Something like this:

use std::str::FromStr;  
let color_str="Red";  
let color_variant = Color ::from_str(color_str).unwrap();
assert!(Color:Red, color_variant);

Why is the documentation/examples using the old syntax:

extern crate strum;  
#[macro_use] extern crate strum_macros;

instead of the new:

use strum;  
use strum_macros

Join members of enum

Given that I have this enum:

enum SpecialSeries {
    DA,
    KT,
    LD,
}

Now I want to build this string

"DA|KT|LD"

in order to use as pattern for RegEx. How should I code with strum? (I don't write Rust often and always forget things when I try to learn Rust again).

Thank you.

Interaction between serde and strum that results in a compiler error

Hi!

I've noticed that using strum's derive EnumDiscriminants with some serde variant attributes, results in a compiler error.

I'm not sure of this is an issue in strum, in serde, or both.

Here's a program to reproduce the issue:

Cargo.toml

[dependencies]
serde = { version = "1.0", features = ["derive"] }
strum = "0.16.0"
strum_macros = "0.16.0"

src/main.rs

extern crate strum;
#[macro_use] extern crate strum_macros;
extern crate serde;

use std::str::FromStr;

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug, EnumDiscriminants)]
#[serde(tag = "type")]
enum Message {
    #[serde(rename = "request" )]
    Request { id: String, method: String, params: u8 },
    #[serde(rename = "response" )]
    Response { id: String, result: u8 },
}

fn main() {
    println!("Hello, world!");
}

Compiler error

error[E0658]: the attribute `serde` is currently unknown to the compiler and may have meaning added to it in the future
  --> src/main.rs:12:5
   |
12 |     #[serde(rename = "request" )]
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: for more information, see https://github.com/rust-lang/rust/issues/29642

error[E0658]: the attribute `serde` is currently unknown to the compiler and may have meaning added to it in the future
  --> src/main.rs:14:5
   |
14 |     #[serde(rename = "response" )]
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: for more information, see https://github.com/rust-lang/rust/issues/29642

warning: unused import: `std::str::FromStr`
 --> src/main.rs:5:5
  |
5 | use std::str::FromStr;
  |     ^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0658`.

Additional info

The program compiles successfully if the lines #[serde(rename = "response" )] are removed.

Minor version bump needed?

I noticed that the EnumVariantNames is shown in the README (and it is pretty useful!), but it is not available on the last release. Could a minor version bump be worth in order to use this feature in a stable release?

Reverse/DoubleEnded EnumIter

It would be nice to be able to iterate over enums in reverse order.

Currently I have to use the workaround my_enum::iter().collect::<Vec<_>>().iter().rev(), which is quite ugly and probably less performant.

This could be implemented by making the IntoEnumIter::iter function return a DoubleEndedIterator to allow code like this:

#[derive(EnumIter)]
enum Colors {Red, Green, Blue}

use strum::IntoEnumIterator;
for color in Colors::iter().rev() {
    // Do something with color.
}

This approach might incur a runtime cost, because we would have to add another field to the iterator struct (a second index for next_back similar to the existing idx) even if the user does not call next_back.

Another possible way to implement this is to add a new method, that returns a reverse or double-ended iterator.

Are you interested in adding this functionality?

Help with 2018 edition

Using strum with rust 2018 probably needs a use strum<something>::strum; because by default this error appears:

error[E0658]: The attribute `strum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
 --> /home/xav/lfgt/target/debug/build/lfgt-3925bf91df78c23d/out/equipments.rs:3:5
  |
3 |     #[strum(serialize = "agt")]
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^

Would it be possible to add the remedy to the README.md ?

how to round trip Display and EnumString with default="true"

I have some default variant that contains a string, like:

#[derive(Display, EnumString)]
FooEnum {
  #[strum(default="true")]
  Bar(String)
}

but if i do:

FooEnum::Bar("baz".into()).to_string();

i get "Bar" not "baz" so then there's no way to round trip it back into the original FooEnum

Publish v0.16.0

Hi,

Would be awesome if you could publish a v0.16.0 of Strum to https://crates.io/crates/strum, as the latest version there is v0.15.0 from March, which for example doesn't have EnumVariantNames (#56)

Right now I have to do this to get EnumVariantNames in my project:

[dependencies]
strum = { git = "https://github.com/Peternator7/strum", rev = "efed58502a40ac101691068bbc6c20a0b351f3fd" }
strum_macros = { git = "https://github.com/Peternator7/strum", rev = "efed58502a40ac101691068bbc6c20a0b351f3fd" }

(Also would be nice with tags in Github that corresponds to the releases on Crates.io.)

Thanks!

FromStr derive could support setting the error type

When you derive on an enum, sometimes you want to implement some From<XXXNotFound> for some other error types, with maybe more explicit messages. It would be great if we could have an attribute that enables us to set the function that would be used to build the error from the original &str.

e.g.

#[derive(EnumString)]
#[strum(parse_err_ty = "SomeEnumNotFound", parse_err_fn = "some_enum_not_found_err")]
pub enum SomeEnum {
	A,
	B,
}

pub struct SomeEnumNotFound;
fn some_enum_not_found_err(_not_found: &str) -> SomeEnumNotFound { SomeEnumNotFound }

generating

impl FromStr for SomeEnum {
    type Err = SomeEnumNotFound;
    fn from_str(s: &str) -> Result<SomeEnum, Self::Err> {
        match s {
            "A" => A,
            "B" => B,
            other => some_enum_not_found_err(other),
        }
    }
}

If parse_err_fn is not specified but parse_err_ty is, we could fallback on From<strum::ParseError>.

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.