Coder Social home page Coder Social logo

lua-cmsgpack's Introduction

README for lua-cmsgpack.c

Lua-cmsgpack is a MessagePack implementation and bindings for Lua 5.1/5.2/5.3 in a self contained C file without external dependencies.

This library is open source software licensed under the BSD two-clause license.

INSTALLATION

Using LuaRocks (http://luarocks.org):

  • Install current stable release:

    sudo luarocks install lua-cmsgpack

  • Install current Git master head from GitHub:

    sudo luarocks install lua-cmsgpack --from=rocks-cvs

  • Install from current working copy

    cd lua-cmsgpack/ sudo luarocks make rockspec/lua-cmsgpack-scm-1.rockspec

If you embed Lua and all modules into your C project, just add the lua_cmsgpack.c file and call the following function after creating the Lua interpreter:

luaopen_cmsgpack(L);

USAGE

The exported API is very simple, consisting of four functions:

Basic API:

msgpack = cmsgpack.pack(lua_object1, lua_object2, ..., lua_objectN)
lua_object1, lua_object2, ..., lua_objectN = cmsgpack.unpack(msgpack)

Detailed API giving you more control over unpacking multiple values:

resume_offset, lua_object1 = cmsgpack.unpack_one(msgpack)
resume_offset1, lua_object2 = cmsgpack.unpack_one(msgpack, resume_offset)
...
-1, lua_objectN = cmsgpack.unpack_one(msgpack, resume_offset_previous)

resume_offset, lua_object1, lua_object2 = cmsgpack.unpack_limit(msgpack, 2)
resume_offset2, lua_object3 = cmsgpack.unpack_limit(msgpack, 1, resume_offset1)

Functions:

  • pack(arg1, arg2, ..., argn) - pack any number of lua objects into one msgpack stream. returns: msgpack
  • unpack(msgpack) - unpack all objects in msgpack to individual return values. returns: object1, object2, ..., objectN
  • unpack_one(msgpack); unpack_one(msgpack, offset) - unpacks the first object after offset. returns: offset, object
  • unpack_limit(msgpack, limit); unpack_limit(msgpack, limit, offset) - unpacks the first limit objects and returns: offset, object1, objet2, ..., objectN (up to limit, but may return fewer than limit if not that many objects remain to be unpacked)

When you reach the end of your input stream with unpack_one or unpack_limit, an offset of -1 is returned.

You may require "msgpack" or you may require "msgpack.safe". The safe version returns errors as (nil, errstring).

However because of the nature of Lua numerical and table type a few behavior of the library must be well understood to avoid problems:

  • A table is converted into a MessagePack array type only if all the keys are composed of incrementing integers starting at 1 end ending at N, without holes, without additional non numerical keys. All the other tables are converted into maps.
  • An empty table is always converted into a MessagePack array, the rationale is that empty lists are much more common than empty maps (usually used to represent objects with fields).
  • A Lua number is converted into an integer type if floor(number) == number, otherwise it is converted into the MessagePack float or double value.
  • When a Lua number is converted to float or double, the former is preferred if there is no loss of precision compared to the double representation.
  • When a MessagePack big integer (64 bit) is converted to a Lua number it is possible that the resulting number will not represent the original number but just an approximation. This is unavoidable because the Lua numerical type is usually a double precision floating point type.

TESTING

Build and test:

mkdir build; cd build
cmake ..
make
lua ../test.lua

You can build a 32-bit module on a 64-bit platform with:

mkdir build; cd build
cmake -DBuild32Bit=ON ..
make
lua ../test.lua

NESTED TABLES

Nested tables are handled correctly up to LUACMSGPACK_MAX_NESTING levels of nesting (that is set to 16 by default). Every table that is nested at a greater level than the maxium is encoded as MessagePack nil value.

It is worth to note that in Lua it is possible to create tables that mutually refer to each other, creating a cycle. For example:

a = {x=nil,y=5}
b = {x=a}
a['x'] = b

This condition will simply make the encoder reach the max level of nesting, thus avoiding an infinite loop.

CREDITS

This library was written by Salvatore Sanfilippo for Redis, but is maintained as a separated project by the author.

Some of the test vectors in "test.lua" are obtained from the Javascript MessagePack-JS library.

lua-cmsgpack's People

Contributors

agladysh avatar antirez avatar dchest avatar dubek avatar fperrad avatar mattsta avatar moteus avatar seppo0010 avatar

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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lua-cmsgpack's Issues

@user_script:6: Bad data format in input.

Hi! I use Redis v2.8.4 and Ruby redis-rb v3.2.2 gem as client. I get this error if I want to pack and unpack messages: @user_script:6: Bad data format in input.

  • pack with Ruby msgpack v0.7.2 (all works fine with version 0.5.12)
  • unpack with cmsgpack in lua on Redis v2.8.4

Ruby msgpack v0.5.12

{ a: 'dc127424-e201-463c-9b41-f5b927ecd947' }.to_msgpack
=> "\x81\xA1a\xDA\x00$dc127424-e201-463c-9b41-f5b927ecd947" 

Ruby msgpack v0.7.2

{ a: 'dc127424-e201-463c-9b41-f5b927ecd947' }.to_msgpack
=> "\x81\xA1a\xD9$dc127424-e201-463c-9b41-f5b927ecd947" 

Here my Redis INFO output:

redis_version:2.8.4
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:a44a05d76f06a5d9
redis_mode:standalone
os:Linux 3.16.0-70-generic x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.8.2
...

I have read this #44 and seen that Redis v2.8.4 uses lua-cmsgpack 0.4.0 where this problem is solved (dec1810) but not in my case. Any idea?

Support for concatenated objects

MessagePack allows binary blobs composed of several valid MessagePack objects concatenated. This is the case of the official MessagePack test data for instance (https://github.com/msgpack/msgpack/tree/master/test).

To support this kind of data you need an interface that:

  • returns the first object of the blob and the byte offset where the decoding stopped,
  • (optionally) allows you to specify an offset where the decoding should start.

An advantage of implementing this is that it would make it possible to use the "official" test data to test this module.

Fix the license

Rockspec files specify MIT/X11, README — Two-clause BSD

MIT/X11 is almost idiomatic for Lua modules, but BSD is OK.

Nil as table index

If a key in a table is nil, the unpack will report an error. But it seems possible to create such an array in msgpack so maybe the Lua unpacker should just ignore it since it cannot be used this way.

Initially for me, the problems comes from the PHP msgpack extension that doesn't serialize sessions correctly and adds a nil indexed key in the array. I was trying to use redis as a session store to share sessions between Openresty (Lua) and PHP (I could do the same with Nodejs for example). The PHP unpack just ignores the nil indexed key/value. See the following issue for some details about the problem.
msgpack/msgpack-php#50

There is the same issue in the Lua MessagePack implementation as described here:
https://github.com/fperrad/lua-MessagePack/issues/14

Improve the LuaRock

  1. Use a zip file as release url instead of the git url. For example: https://github.com/antirez/lua-cmsgpack/archive/0.4.0.zip.
  2. Better to drop https in favor of http and add a digest, so that more clients are able to fetch but they can still verify the content.

Compile error with MSVC2010

Please swap lines 549/550 to

void mp_decode_to_lua_array(lua_State *L, mp_cur *c, size_t len) {
int index = 1;
assert(len <= UINT_MAX);

as VC2010 otherwise complains about a variable "index" defined in the middle of a C block.
Variables have to be declared in the first line - in a pure C program...

Regards,
Helmut

fix incompatibilities with lua 5.2 ?

Hi,

While packaging this library for nixos in order to run neovim tests, I stumbled upon this error which I believe is due to lua 5.2(.3) incompatibility. Would it be possible to fix it please ?

unpacking sources
unpacking source archive /nix/store/6jwp0g5bsswgv55azirwla8w3mmj8wyn-lua-iconv-7-3.src.rock
'/nix/store/6jwp0g5bsswgv55azirwla8w3mmj8wyn-lua-iconv-7-3.src.rock' -> 'lua-iconv-7-3.src.rock'
Warning: The directory '/homeless-shelter/.cache/luarocks' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing /nix/store/ksx0538jndaskhgwgh8vbj91fa4r4xr3-luarocks-2.4.3/bin/.luarocks-wrapped with sudo, you may want sudo's -H flag.
lua_cmsgpack.c: In function 'mp_encode_lua_table_as_array':
lua_cmsgpack.c:331:18: warning: implicit declaration of function 'lua_objlen' [-Wimplicit-function-declaration]
     size_t len = lua_objlen(L,-1), j;
                  ^~~~~~~~~~
lua_cmsgpack.c: At top level:
lua_cmsgpack.c:690:30: error: array type has incomplete element type 'struct luaL_reg'
 static const struct luaL_reg thislib[] = {
                              ^~~~~~~
lua_cmsgpack.c: In function 'luaopen_cmsgpack':
lua_cmsgpack.c:697:5: warning: implicit declaration of function 'luaL_register' [-Wimplicit-function-declaration]
     luaL_register(L, "cmsgpack", thislib);
     ^~~~~~~~~~~~~

Error: Build error: Failed compiling object lua_cmsgpack.o
gcc -O2 -fPIC -I/nix/store/bb68br3ravhcacg3hsnsjwqib3rj6b5s-lua-5.2.3/include -c lua_cmsgpack.c -o lua_cmsgpack.o
builder for ‘/nix/store/6wskmyg22i17jv7b38mznxk43my6cgpg-lua5.2-lua-cmsgpack-0.3-2.drv’ failed with ex

Fix compilation warnings

lua_cmsgpack.c: In function ‘mp_unpack_full’:
lua_cmsgpack.c:802:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     else if (offset > len)
                     ^
lua_cmsgpack.c: In function ‘luaopen_create’:
lua_cmsgpack.c:899:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for (i = 0; i < (sizeof(cmds)/sizeof(*cmds) - 1); i++) {
                   ^
lua_cmsgpack.c: In function ‘luaopen_cmsgpack_safe’:
lua_cmsgpack.c:934:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for (i = 0; i < (sizeof(cmds)/sizeof(*cmds) - 1); i++) {
                   ^

Lua stack corruption bug

On a "mp_pack()" call with a large depth of nested tables cmsgpack will crash Lua.

The function "mp_encode_lua_table()" grows the Lua stack by two per call. In a recursive situation (reaching the max allowed table depth) such as set in motion by the "test.lua" "Regression test for issue #4, cyclic references in tables.", the Lua stack space can and will usually get exhausted resulting in a crash/segfault/exception from Lua heap corruption.

It's particularly noticeable with a higher value than the default value of 16 for "LUACMSGPACK_MAX_NESTING" is set. Double that to 32 and "test.lua" will crash your Lua.
It doesn't crash currently at 16 because the default lua stack is 40 if you have a single argument or two.

#define LUA_MINSTACK 20
#define BASIC_STACK_SIZE  (2*LUA_MINSTACK)

Where to catch it:
In "mp_encode_lua_type()" put a breakpoint on the "t = LUA_TNIL;" line.
When hit look at the Lua stack size and you will see it equals (LUACMSGPACK_MAX_NESTING x 2) + arg size. Where arg is the current working stack size on entry to "mp_pack()".

A solution that fixes the problem, add to the top of "mp_pack()":
luaL_checkstack(L, (LUACMSGPACK_MAX_NESTING * 2), "Can't grow stack.");

This will ensure enough stack space when hitting the nested table limit.

Also I'm sure you could add a similar line (like you have in "mp_decode_to_lua_type()", except growing by two) at the top of "mp_encode_lua_table()" et al.

Update:
What you can do (and what I should have had) was to have "LUA_USE_APICHECK" defined for Lua debug builds. Doing so enables an internal stack overflow check in Lua that asserts on hit.

unpack method in release 0.3.0 returning an error with redis Redis 3.0.2

While unpacking a simple lua table returned by a redis script, the method is returning: [error] 5906#0: *1 lua entry thread aborted: runtime error: Bad data format in input.
stack traceback:
coroutine 0:
[C]: in function 'unpack'
I had to rollback to redis 3.0.1 to fix my environment.
Any plans to publish a new release (0.4.0?) compatible with the latest version of redis?
Thanks in advance...

Question about the separator of cmsgpack data

I want to store some lua table data in a file. I use cmsgpack.pack(table) to convert it into a binary string, and then write it into the file. But I encountered a separator problem. I tried to use '\n' as the separator at first, but I found that the binary string may also contain the separator '\n' , which made me unable to read the binary file correctly.

How should I store and use what delimiter to divide the data?

Version installed from luarocks vulnerable to CVE-2018-11218

I've made a fuzzer for lua: https://github.com/stevenjohnstone/afl-lua. I was trying it out on known vulnerabilities and verified that it could detect the issues flagged in CVE-2018-11218 with 0.4.0-0. I then tried to install the latest and greatest following the README instructions as a point of comparison and found the same bugs...because luarocks had installed the version 0.4.0-0 again 🤦

Turns out the README instructions need to be updated to install the correct version; luarocks probably should probably just fail when the specified source isn't found but that's another issue. See #62 for a build instruction fix.

Would it be possible to tag another release and push it to luarocks?

BTW, fuzzer hasn't found any issues with the latest and greatest 👍

Create release tarballs with consequent/predictable archive filename and subdir

I wonder if you please could create a traditional tarball(s) for releases:

git archive --prefix=lua-cmsgpack-$version/ \
    -o lua-cmsgpack-$version.tar.gz $releasetag

and use the upload feature in github and do that for future releases?

That way we package builders can predict the filename and subdir before the package is even downloaded.

A script like this:

pkgname=lua-cmsgpack
pkgver=0.3.0
source="https://..../lua-cmsgpack-$pkgver.tar.gz"

build() {
    cd "$srcdir"/lua-cmsgpack-$pkgver
    make
    ...
}

Can be almost completely automated to pick new releases with simply

sed "s/pkgver=.*/pkgver=$newver/"

The autogenerated github tarballs generated on the fly from git tags is painful for distro packagers that maintain over 1000 packages.

Thanks!

Table with string number as key is mistreated as array.

local mp = require 'cmsgpack'
local tbl = {['1']=1}
local s = mp.pack(tbl)
print('length:', #s)
print('first byte:', string.byte(s, 1))

The table {['1']=1} is encoded to \x90, which is for [].

The script above output like this:

length: 1
first byte: 144

README INSTALLATION section lacks proper installation

This should not be neither a preferred nor the only one documented way to install the module:

To include this library in your Lua project, just add the lua_msgpack.c file
and call the following function after creating the Lua interpreter:

luaopen_msgpack(L);

You need to support the other "half" of users, who use the stock interpreter. Even for people, who have built in Lua interpreter to their C program, it is unusual to prefer to directly compile module code into the program — shared libraries are the way to do it unless one has good reasons not to.

You should provide instructions like "build a shared library and put it somewhere in package.cpath, then call 'require "msgpack"'". If you do not want to bother, just write a rockspec file (#3) and mention sudo luarocks install lua-msgpack (stable release), sudo luarocks install lua-msgpack --from=rocks-cvs (for the Git master HEAD on GH) and sudo luarocks make rockspec/lua-msgpack-scm-1.rockspec (from local working copy) in the INSTALLATION section.

table_is_an_array BUG

int table_is_an_array(lua_State *L) {
int count = 0, max = 0;
#if LUA_VERSION_NUM < 503
lua_Number n;
#else
lua_Integer n;
#endif

/* Stack top on function entry */
int stacktop;

stacktop = lua_gettop(L);

lua_pushnil(L);
while(lua_next(L,-2)) {
    /* Stack: ... key value */
    lua_pop(L,1); /* Stack: ... key */
    /* The <= 0 check is valid here because we're comparing indexes. */

#if LUA_VERSION_NUM < 503
if ((LUA_TNUMBER != lua_type(L,-1)) || (n = lua_tonumber(L, -1)) <= 0 ||
!IS_INT_EQUIVALENT(n))
#else
if (!lua_isinteger(L,-1) || (n = lua_tointeger(L, -1)) <= 0)
#endif
{
lua_settop(L, stacktop);
return 0;
}
max = (n > max ? n : max);
count++;
}
/* We have the total number of elements in "count". Also we have
* the max index encountered in "max". We can't reach this code
* if there are indexes <= 0. If you also note that there can not be
* repeated keys into a table, you have that if max==count you are sure
* that there are all the keys form 1 to count (both included). */
lua_settop(L, stacktop);
return max == count;
}

int count = 0, max = 0; this should be int64_t count = 0, max = 0;

Rockspec doesn't build correctly

The rockspec declares the module as msgpack but in c you only declare luaopen_cmsgpack. Either rename the module in the rockspec to cmsgpack or rename the luaopen function to luaopen_msgpack.

cmsgpack.pack(t) got empty

local cmsgpack = require("cmsgpack")

local function to_readonly_table(input_table)
    if input_table == nil then
        return nil
    end
    assert(type(input_table) == 'table')
    local travelled_tables = {}
    local function __read_only(tbl)
        if not travelled_tables[tbl] then
            local tbl_mt = getmetatable(tbl)
            if not tbl_mt then
                tbl_mt = {}
                setmetatable(tbl, tbl_mt)
            end

            local proxy = tbl_mt.__read_only_proxy
            if not proxy then
                proxy = {}
                tbl_mt.__read_only_proxy = proxy
                local proxy_mt = {
                    __index = tbl,
                    __newindex = function(t, k, v)
                        error("error write to a read-only table with key = " .. tostring(k))
                    end,
                    __pairs = function(t)
                        return pairs(tbl)
                    end,
                    __len = function(t)
                        return #tbl
                    end,
                    __read_only_proxy = proxy
                }
                setmetatable(proxy, proxy_mt)
            end
            travelled_tables[tbl] = proxy
            for k, v in pairs(tbl) do
                if type(v) == "table" then
                    tbl[k] = __read_only(v)
                end
            end
        end
        return travelled_tables[tbl]
    end
    return __read_only(input_table)
end

local t = to_readonly_table({
        a = 1,
        b = 2
    })
local tmp = cmsgpack.pack(t)
local origin = cmsgpack.unpack(tmp) -- this one become empty

Extension type support

Any chance of adding hooks to support extension types? This would basically require an API where callers could specify two callback functions one for encoding and one for decoding. Then mp_encode_lua_type and mp_decode_to_lua_type would call these functions to produce the actual values to be used when serializing.

Examples of two different ways this can be done for msgpack-python are below

https://pypi.python.org/pypi/msgpack-python#packing-unpacking-of-custom-data-type
https://pypi.python.org/pypi/msgpack-python#extended-types

List project on msgpack.org

If you add msgpack.org[Lua] to the description of this project, their crawler will pick up lua-cmsgpack and add it to the list of implementations on their front page. See here for details.
I was pleased to see a testimonial from the author of this project on their website, and then surprised to see a different Lua implementation in their listing, but not this one.

linker issues: undefined symbol: lua_tointeger

> mkdir build; cd build
> cmake ..
-- The C compiler identification is GNU 4.8.4
-- Check for working C compiler: /home/ensonic/bin/cc
-- Check for working C compiler: /home/ensonic/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Found Lua51: /usr/lib/x86_64-linux-gnu/liblua5.1.so;/usr/lib/x86_64-linux-gnu/libm.so (found version "5.1.5") 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ensonic/projects/vitruvius/lua-cmsgpack/build
> make
Scanning dependencies of target cmsgpack
[100%] Building C object CMakeFiles/cmsgpack.dir/lua_cmsgpack.c.o
Linking C shared module cmsgpack.so
[100%] Built target cmsgpack
> lua ../test.lua 
lua: error loading module 'cmsgpack' from file './cmsgpack.so':
    ./cmsgpack.so: undefined symbol: lua_tointeger
stack traceback:
    [C]: in ?
    [C]: in function 'require'
    ../test.lua:5: in main chunk
    [C]: in ?
> ldd ./cmsgpack.so
    linux-vdso.so.1 =>  (0x00007ffeb3fe6000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fde16985000)
    /lib64/ld-linux-x86-64.so.2 (0x000055aa39fe4000)
> lua -v
Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio

Seems that the build is hardcoded to build against 5.1. Running under 5.1 works

lua5.1 ../test.lua 

License

Please add a license document and call out a specific license (MIT? Public Domain?). The copyright at the end of the file doesn't state the license, other than that all rights are reserved AND that anyone is free to do whatever they want with it.

If there is one and I'm not seeing it, please let me know. :)

-Andrew

Wrong size passed into realloc on delete of buf

In mp_buf_free in file lua_cmsgpack.c line 133 reads mp_realloc(buf->L, buf->b, buf->len, 0); when it should read mp_realloc(buf->L, buf->b, buf->len + buf->free, 0);

realloc is passed the wrong osize. That can be problematic if the implementation of realloc is sensitive to it.

mp_buf_append and sanitizing realloc

I noticed mp_buf_append and mp_buf_new are not sanitizing the result to mp_realloc.

The Lua documentation states that when the pointer is non-null is must behave like realloc (and in the default case it is: return realloc(ptr, nsize)). In turn, when realloc fails the original block is left untouched and NULL is returned, which paths into a memcpy (and likely segmenta.... fau.. or something else entirely dependent on buf->len).

While a minor issue, a bit of defensive programming here would not hurt.

warning: this decimal constant is unsigned only in ISO C90

$ sudo luarocks make rockspec/lua-msgpack-0.1-1.rockspec 
gcc -O2 -fPIC -I/usr/include/lua5.1 -c lua_msgpack.c -o lua_msgpack.o
lua_msgpack.c: In function ‘mp_encode_int’:
lua_msgpack.c:230:9: warning: this decimal constant is unsigned only in ISO C90
gcc -shared -o msgpack.so -L/usr/local/lib lua_msgpack.o
Updating manifest for /usr/local/lib/luarocks/rocks

Note that it is a good practice to write Lua modules that they build cleanly with C89, C99 and C++98 — as Lua itself.

If a module is not buildable as C++98 code, it is a good idea to explicitly mark it as such (for example with #error in code). It is not uncommon to embed Lua into C++ code (not that I endorse this questionable practice), and this would require Lua itself and all modules to be built as C++.

Support reading from FILE*

I have a large chunk of data in a file, encoded with msgpack, and I want to load it to Lua.

I do not want to pay for overhead of interning this file as a string into Lua state. Instead I want a lua-cmsgpack call that would load my data from file directly.

Is it possible?

I realize that this is somewhat a corner case for lua-cmsgpack, as it is persistence and not message passing, but anyway — would be quite useful.

Tag new version

Since lua-cmsgpack now supports lua 5.2, it'd be nice to have a new version so we can install it with luarocks or have package managers start working.

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.