Rust bindings for LMDB
LMDB is bundled as submodule so update submodules first:
git submodule update --init
And then
cargo build
Feel free to ping me if you have a question or a suggestion how to make it better and idiomatic.
Rust bindings for LMDB
License: MIT License
Rust bindings for LMDB
LMDB is bundled as submodule so update submodules first:
git submodule update --init
And then
cargo build
Feel free to ping me if you have a question or a suggestion how to make it better and idiomatic.
I wonder if core::Environment
is supposed to be thread-safe and should be marked as Sync
?
It seems so from db_cache: Mutex
. Also LMDB says that it's "thread-aware" and forbids opening the database twice ("Do not have open an LMDB database twice in the same process at the same time" - http://symas.com/mdb/doc/) so I gather the MDB_env
should be thread-safe.
Transaction methods are immutable—including state-changing ones—which leads to surprising and dangerous results.
The problem is that Database
methods that change values in the database are not mutable—i.e., they have a &self
parameter, not a &mut self
parameter.
Take the following program as an example, which obtains an immutable reference to an LMDB value that changes while that reference is held. I would expect this program to not compile.
extern crate lmdb_rs;
extern crate tempdir;
fn main() {
let tdir = tempdir::TempDir::new("lmdb-test").unwrap();
let env = lmdb_rs::Environment::new().open(&tdir, 0o666).unwrap();
let db_handle = env.get_default_db(lmdb_rs::core::DbFlags::empty()).unwrap();
let tx = env.new_transaction().unwrap();
let db = tx.bind(&db_handle);
db.set(&"alpha", &"bravo").unwrap();
let v: &str = db.get(&"alpha").unwrap();
assert_eq!(v, "bravo");
db.set(&"alpha", &"charlie").unwrap(); // <-- should be a compiler borrow-check error
println!("Got: {:?}", v);
}
Instead, the program compilers and, when run, produces this output:
Got: "arlie"
Suppose the database value had been overwritten with invalid UTF8, in which case we would have had a &str
referencing invalid UTF8. This is classic memory corruption, and it occurs without the application using an unsafe
block.
Broadly speaking, there are two possible fixes here. The first is to simply mark the database-modifying methods as unsafe
so that applications must explicitly mark their use of these methods as being memory-unsafe.
The second fix—and the one that I prefer—is to change the database-modifying methods to be mutable—i.e., to have a &mut self
parameter instead of &self
. Such a change would force the application in the example above to scope the v
reference such that it goes out of scope before the call to Database::set
—otherwise the application would trigger a borrow-check error in the compiler.
If, for some reason, an application needs to hold a reference to a key or value while modifying the content of the database, then that application could resort to using raw pointers and unsafe
blocks. This is extra work for the application programmer, sure, but it reflects how the underlying operation is fundamentally memory-unsafe. This is idiomatic Rust: memory-unsafe code is wrapped within an unsafe
block.
Another idea is to combine these two fixes and for lmdb-rs to provide two related methods: one that's memory-safe and another that's not.
impl Database {
fn set(&mut self, key: &ToMdbValue, value: &ToMdbValue) -> MdbResult<()> {}
unsafe fn set_unchecked(&self, key: &ToMdbValue, value: &ToMdbValue) -> MdbResult<()> {}
}
The following methods are memory-unsafe:
Database::set
Database::append
Database::append_duplicate
Database::insert
Database::del
Database::del_item
Database::clear
Additionally, the following two methods are memory-unsafe—but in a way dissimilar from the problem described in this ticket:
Database::set_compare
Database::set_dupsort
The lmdb-rs documentation explicitly describes these methods as dangerous, but that danger is not propagated through the Rust type system. I'm not sure what should be done about these two methods and am leaving them out of this discussion other than to suggest they should be marked as unsafe
.
lmdb is segment faulting in the function mdb_freelist_save
When debugging with rust-gdb:
[New Thread 0x7ffff47df700 (LWP 18986)]
mdb/libraries/liblmdb/mdb.c:3067: Assertion 'pglast <= env->me_pglast' failed in mdb_freelist_save()
Thread 62 "worker_0" received signal SIGABRT, Aborted.
[Switching to Thread 0x7ffff47df700 (LWP 18986)]
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb)
anyone had the same problem?
https://docs.rs/lmdb-rs/0.7.6/lmdb_rs/core/constant.EnvCreataMapAsync.html
Shouldn't that be "CreateMapAsync"?
Just a heads up in case somebody else is struggling with the same issue.
After a recent upgrade I've started seeing crashes in LMDB, they looked like this
#0 0x00007fad06517cfc in mdb_cursor_put () from /usr/local/lib/libbyzon.so
#1 0x00007fad0651af53 in mdb_put () from /usr/local/lib/libbyzon.so
#2 0x00007fad06506698 in set_value_with_flags (self=<optimized out>, db=<optimized out>, key=...,
value=..., flags=<optimized out>)
at /home/grank/.cargo/registry/src/github.com-1ecc6299db9ec823/lmdb-rs-0.7.2/src/core.rs:1069
#3 set_value (self=<optimized out>, db=<optimized out>, key=..., value=...)
at /home/grank/.cargo/registry/src/github.com-1ecc6299db9ec823/lmdb-rs-0.7.2/src/core.rs:1061
#4 set (self=<optimized out>, db=2, key=..., value=...)
at /home/grank/.cargo/registry/src/github.com-1ecc6299db9ec823/lmdb-rs-0.7.2/src/core.rs:1079
#5 lmdb_rs::core::{{impl}}::set (self=<optimized out>, key=..., value=...)
at /home/grank/.cargo/registry/src/github.com-1ecc6299db9ec823/lmdb-rs-0.7.2/src/core.rs:414
and only happened in the release builds. I've tried a couple of things, like adding global locks around LMDB operations and such, I've upgraded LMDB, but to no avail.
Finally I've lovered the optimization level in order to better debug the issue and voila, the problem vanished.
My conjecture is that LMDB is normally tested with -O2 optimization (cf), but the Rust package uses -O3 (cf), the level which is not supported by the LMDB code base and triggers some kind of a bug.
LMDB 0.9.16 Release (2015/08/14)
Fix cursor EOF bug (ITS#8190)
Fix handling of subDB records (ITS#8181)
Fix mdb_midl_shrink() usage (ITS#8200)
How about it? 😄
there is already a pull request, please press the merge button, currently this crate does not compile on crates.io (apparently a backwards incompatible compiler change)
#43
Should be https://vhbit.github.io/lmdb-rs/lmdb_rs/index.html but is set to https://vhbit.github.io/lmdb-rs/lmdb-rs
Reference: https://crates.io/crates/lmdb-rs
Lines 135 to 142 in 3a4bd66
from_mdb_value
is implemented through macro on several primitive types including integers, float numbers, and bool. However, it is unsound to transmute data with arbitrary bit patterns to bool.
use lmdb_rs_m::core::MdbValue;
use lmdb_rs_m::FromMdbValue;
fn main() {
let a: i32 = 3;
let mdbval = MdbValue::new_from_sized(&a);
let res = bool::from_mdb_value(&mdbval);
println!("{:?}", res);
}
run with Miri would show that UB happen.
|
157 | mdb_for_primitive!(bool);
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
|
UB should not happen with safe function in Rust.
I've encountered a rather bizarre segfault occurrence that is somehow linked to lmdb-rs. The segfault is odd and manifests in strangle places. In my project that I currently am experiencing issues with this it generally manifests when trying to transform data read from the db or move an Arc
to the environment into a new thread. You can check out the code here.
I created a repository purely for reference in helping solve this issue, which you can find here. I'm happy to help in fixing this if you can point me in the right direction. I've really enjoyed using this library and need it to work to complete my senior project.
It would be nice to be able to insert and retrieve values more easily, therefore i propose to include a (extremly trivial) blanket implementation for ToMdbValue and/or FromMdbValue for everything that implements the serde Serialize and/or Deserialize trait using for examble bincode for serialisation.
Unfortunalty, the libmbd Makefile does not allow to override CC
and AR
: https://github.com/LMDB/lmdb/blob/ad8488cfac644d7a289e428ab3c403c859d844cb/libraries/liblmdb/Makefile#L21-L22.
I am still a novice to Rust. Maybe it's possible to patch the Makefile with build.rs
?
Clicking the link to the Github pages documentation http://vhbit.github.io/lmdb-rs/lmdb-rs/ leads to a 404. Google Cache results still work, though they are a bit dated.
Hello,
is there a nice way to iterate over keys starting with a given "from" key (including that) while ending the iteration at a given "end" key (this is, excluding that key from the iteration)? While keyrange_from/_to
individually provide what I need, it seems that keyrange
includes the "end" key on purpose. However, I fail to find a strong reason for this.
P.
Hey! I have the following issue, when trying to create an environment with EnvCreateFlags, I get this error:
thread '<main>' panicked at 'error opening environment: 22: Invalid argument', src/main.rs:38
An unknown error occurred
Code extract is:
use lmdb::core::{EnvCreateReadOnly};
let env_builder = EnvBuilder::new()
.map_size(256 * 1024 * 1024)
.max_dbs(5)
.flags(EnvCreateReadOnly);
let env = env_builder.open(&path, 0o664).unwrap();
Do you find anything wrong with that ?
Thanks !
Btw, great lib! I tried to discover the issue by myself but I'm still learning Rust :)
I was attempting to store stale read transactions to prevent allocating a new one.
When ever a ReadonlyTransaction<'a>
is abort(&mut self)
or reset(&mut self)
when ever renew(&mut self)
was called after I'd receive the error that it was in Normal
state.
May i ask what the status of the project ist? Will those bindings eventually be supported again for Rust 1.0 or are they pretty much abandoned?
As the title, here is the output of the cargo build
Compiling lmdb-sys v0.8.0 (/home/matt_jan/lmdb-rs/lmdb-sys)
The following warnings were emitted during compilation:
warning: In file included from /usr/local/include/linux/stat.h:6,
warning: from /usr/include/x86_64-linux-gnu/bits/statx.h:31,
warning: from /usr/include/x86_64-linux-gnu/sys/stat.h:465,
warning: from /home/matt_jan/lmdb-rs/lmdb-sys/lmdb/libraries/liblmdb/mdb.c:66:
warning: /usr/local/include/asm/stat.h:8:10: fatal error: uapi/asm/stat.h: No such file or directory
warning: 8 | #include <uapi/asm/stat.h>
warning: | ^~~~~~~~~~~~~~~~~
warning: compilation terminated.
error: failed to run custom build command for `lmdb-sys v0.8.0 (/home/matt_jan/lmdb-rs/lmdb-sys)`
Caused by:
process didn't exit successfully: `/home/matt_jan/lmdb-rs/target/debug/build/lmdb-sys-f54e38c03d94593e/build-script-build` (exit status: 1)
--- stdout
cargo:rerun-if-env-changed=LIBLMDB_NO_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-gnu
cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_gnu
cargo:rerun-if-env-changed=HOST_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG
cargo:rerun-if-env-changed=LIBLMDB_STATIC
cargo:rerun-if-env-changed=LIBLMDB_DYNAMIC
cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-unknown-linux-gnu
cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_unknown_linux_gnu
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_PATH
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-unknown-linux-gnu
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_unknown_linux_gnu
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-gnu
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu
cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
TARGET = Some("x86_64-unknown-linux-gnu")
HOST = Some("x86_64-unknown-linux-gnu")
cargo:rerun-if-env-changed=CC_x86_64-unknown-linux-gnu
CC_x86_64-unknown-linux-gnu = None
cargo:rerun-if-env-changed=CC_x86_64_unknown_linux_gnu
CC_x86_64_unknown_linux_gnu = None
cargo:rerun-if-env-changed=HOST_CC
HOST_CC = None
cargo:rerun-if-env-changed=CC
CC = Some("gcc")
cargo:rerun-if-env-changed=CRATE_CC_NO_DEFAULTS
CRATE_CC_NO_DEFAULTS = None
DEBUG = Some("true")
CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse2")
cargo:rerun-if-env-changed=CFLAGS_x86_64-unknown-linux-gnu
CFLAGS_x86_64-unknown-linux-gnu = None
cargo:rerun-if-env-changed=CFLAGS_x86_64_unknown_linux_gnu
CFLAGS_x86_64_unknown_linux_gnu = None
cargo:rerun-if-env-changed=HOST_CFLAGS
HOST_CFLAGS = None
cargo:rerun-if-env-changed=CFLAGS
CFLAGS = None
running: "gcc" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "-gdwarf-4" "-fno-omit-frame-pointer" "-m64" "-Wall" "-Wextra" "-o" "/home/matt_jan/lmdb-rs/target/debug/build/lmdb-sys-a4f65797694572cc/out/f78d8cd4c37051d3-mdb.o" "-c" "/home/matt_jan/lmdb-rs/lmdb-sys/lmdb/libraries/liblmdb/mdb.c"
cargo:warning=In file included from /usr/local/include/linux/stat.h:6,
cargo:warning= from /usr/include/x86_64-linux-gnu/bits/statx.h:31,
cargo:warning= from /usr/include/x86_64-linux-gnu/sys/stat.h:465,
cargo:warning= from /home/matt_jan/lmdb-rs/lmdb-sys/lmdb/libraries/liblmdb/mdb.c:66:
cargo:warning=/usr/local/include/asm/stat.h:8:10: fatal error: uapi/asm/stat.h: No such file or directory
cargo:warning= 8 | #include <uapi/asm/stat.h>
cargo:warning= | ^~~~~~~~~~~~~~~~~
cargo:warning=compilation terminated.
exit status: 1
--- stderr
error occurred: Command "gcc" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "-gdwarf-4" "-fno-omit-frame-pointer" "-m64" "-Wall" "-Wextra" "-o" "/home/matt_jan/lmdb-rs/target/debug/build/lmdb-sys-a4f65797694572cc/out/f78d8cd4c37051d3-mdb.o" "-c" "/home/matt_jan/lmdb-rs/lmdb-sys/lmdb/libraries/liblmdb/mdb.c" with args "gcc" did not execute successfully (status code exit status: 1).
I am using WSL2, the following is output of lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.3 LTS
Release: 22.04
Codename: jammy
Are there any suggestion?
Howdy!
Once #36 is merged I'd like to submit a PR for this commit: https://github.com/photex/lmdb_rs/commit/de3056ce1abe605d747295f9b910085f54dbc484
Using msvc and rust 1.10 I can build and all tests pass. Haven't dug into it other than that.
This seems likely to be caused by the bug listed here https://www.openldap.org/lists/openldap-bugs/201604/msg00046.html which has been since resolved. A new version of LMDB should correct it. It looks like lmdb-rs uses LMDB 0.9.18, but this was fixed in 0.9.19 (also visible in this PowerDNS ticket).
Just FYI, I've encountered a persevering early termination problem iterating keys with keyrange_to
.
With the database defined as follows:
let expiration_idx = try! (env.create_db ("expiration_idx", DbFlags::from_bits_truncate (lmdb_sys::MDB_DUPSORT | lmdb_sys::MDB_INTEGERKEY)));
I had to rewrite the loop as follows:
let mut hashes_found: Vec<u64> = Vec::new(); // NB: Must not change the index while iterating it.
let till = time::get_time().sec as u64;
// NB: Using `iter` because `keyrange_to` doesn't work as expected (misses some keys).
for rec in try! (expiration_idx.iter()) {
if rec.get_key::<u64>() > till {break}
hashes_found.push (rec.get_value::<u64>());}
Because the keyrange_to
version terminated early and have been missing some keys.
The problematic keyrange_to
version:
let till = time::get_time().sec as u64 + 1;
for rec in try! (expiration_idx.keyrange_to (&till)) {
hashes_found.push (rec.get_value::<u64>());}
While compilation got this error.
error[E0195]: lifetime parameters or bounds on method `to_mdb_value` do not match the trait declaration
--> /home/comfix/.cargo/registry/src/github.com-1ecc6299db9ec823/lmdb-rs-0.7.1/src/traits.rs:55:5
|
55 | / fn to_mdb_value<'b, 's>(&'s self) -> MdbValue<'b> {
56 | | unsafe {
57 | | MdbValue::new(mem::transmute(self.as_ptr()),
58 | | self.len())
59 | | }
60 | | }
| |_____^ lifetimes do not match trait
Hey,
I'm a total noob in all regards 'rust', so it's very well possible that I'm doing something totally dumb here, but I'd nevertheless like to give you a heads up about the following error after git submodule update --init; cargo build:
msp-hh-nb22:lmdb-rs $ rustc --version
rustc 0.13.0-nightly (fea5aa656 2014-12-30 00:42:13 +0000)
Compiling lmdb-rs v0.1.0 (file://$HOME/Documents/workspace/jan/lmdb-rs)
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:674:13: 674:19 error: mismatched types: expected std::sync::mutex::MutexGuard<'_, core::cell::UnsafeCell<std::collections::hash::map::HashMap<collections::string::String, u32>>>
, found core::result::Result<_, _>
(expected struct std::sync::mutex::MutexGuard, found enum core::result::Result)
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:674 Err() => Err(MdbError::CacheError),
^~~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:675:13: 675:22 error: mismatched types: expected std::sync::mutex::MutexGuard<'_, core::cell::UnsafeCell<std::collections::hash::map::HashMap<collections::string::String, u32>>>
, foundcore::result::Result<_, _>
(expected struct std::sync::mutex::MutexGuard, found enum core::result::Result)
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:675 Ok(guard) => {
^~~~~~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:676:32: 676:38 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:676 let ref cell = *guard;
^~~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:677:34: 677:39 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:677 let cache = cell.get();
^~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:680:39: 680:60 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:680 if let Some(db) = (*cache).get(db_name) {
^~~~~~~~~~~~~~~~~~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:681:68: 681:71 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:681 debug!("Cached value for {}: {}", db_name, *db);
^~~
note: in expansion of format_args!
:10:35: 10:58 note: expansion site
:1:1: 13:2 note: in expansion of log!
:2:46: 2:76 note: expansion site
:1:1: 3:2 note: in expansion of debug!
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:681:25: 681:73 note: expansion site
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:705:21: 705:60 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:705 (*cache).insert(db_name.to_owned(), db);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:732:13: 732:19 error: mismatched types: expectedstd::sync::mutex::MutexGuard<'_, core::cell::UnsafeCell<std::collections::hash::map::HashMap<collections::string::String, u32>>>
, foundcore::result::Result<_, _>
(expected struct std::sync::mutex::MutexGuard, found enum core::result::Result)
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:732 Err() => (),
^~~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:733:13: 733:22 error: mismatched types: expected std::sync::mutex::MutexGuard<'_, core::cell::UnsafeCell<std::collections::hash::map::HashMap<collections::string::String, u32>>>
, found core::result::Result<_, _>
(expected struct std::sync::mutex::MutexGuard, found enum core::result::Result)
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:733 Ok(guard) => {
^~~~~~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:734:32: 734:38 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:734 let ref cell = _guard;
^~~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:737:38: 737:43 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:737 let cache = cell.get();
^~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:740:35: 740:50 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:740 for (k, v) in (_cache).iter() {
^~~~~~~~~~~~~~~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:741:28: 741:30 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:741 if _v == handle {
^~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:741:28: 741:30 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:741 if *v == handle {
^~
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:748:25: 748:45 error: the type of this value must be known in this context
$HOME/Documents/workspace/jan/lmdb-rs/src/core.rs:748 (_cache).remove(key);
^~~~~~~~~~~~~~~~~~~~
error: aborting due to 15 previous errors
Could not compile lmdb-rs
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.