Skip to content

Commit 1da96d7

Browse files
Merge pull request #42 from simdjson/add_rust_serd
fix Rust through CMake
2 parents c3ac24e + fcfaf09 commit 1da96d7

File tree

12 files changed

+473
-6
lines changed

12 files changed

+473
-6
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ ARG GROUP_ID
2727
LABEL maintainer "LLVM Developers"
2828
# Install packages for minimal useful image.
2929
RUN apt-get update && \
30-
apt-get install -y --no-install-recommends build-essential ca-certificates libcurl4-openssl-dev cmake make wget python3 python3-dev sudo curl ninja-build vim git binutils && \
30+
apt-get install -y --no-install-recommends build-essential ca-certificates rust-all libcurl4-openssl-dev cmake make wget python3 python3-dev sudo curl ninja-build vim git binutils && \
3131
rm -rf /var/lib/apt/lists/*
3232
# Copy build results of stage 1 to /usr/local.
3333
COPY --from=builder /tmp/clang-install/ /usr/local/

benchmarks/CMakeLists.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,40 @@ CPMAddPackage(
77
PATCHES reflect-cpp.patch
88
GIT_TAG v0.13.0
99
)
10+
11+
12+
13+
if(NOT WIN32)
14+
# We want the check whether Rust is available before trying to build a crate.
15+
CPMAddPackage(
16+
NAME corrosion
17+
GITHUB_REPOSITORY corrosion-rs/corrosion
18+
VERSION 0.4.4
19+
DOWNLOAD_ONLY ON
20+
OPTIONS "Rust_FIND_QUIETLY OFF"
21+
)
22+
include("${corrosion_SOURCE_DIR}/cmake/FindRust.cmake")
23+
endif()
24+
25+
if(RUST_FOUND)
26+
message(STATUS "Rust found: " ${Rust_VERSION} )
27+
add_subdirectory("${corrosion_SOURCE_DIR}" "${PROJECT_BINARY_DIR}/_deps/corrosion" EXCLUDE_FROM_ALL)
28+
# Important: we want to build in release mode!
29+
corrosion_import_crate(MANIFEST_PATH "competitors/serde-benchmark/Cargo.toml" NO_LINKER_OVERRIDE PROFILE release)
30+
else()
31+
message(STATUS "Rust/Cargo is unavailable." )
32+
message(STATUS "We will not benchmark serde-benchmark." )
33+
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
34+
message(STATUS "Under macOS, you may be able to install rust with")
35+
message(STATUS "curl https://sh.rustup.rs -sSf | sh")
36+
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
37+
message(STATUS "Under Linux, you may be able to install rust with a command such as")
38+
message(STATUS "apt-get install cargo" )
39+
message(STATUS "or" )
40+
message(STATUS "curl https://sh.rustup.rs -sSf | sh")
41+
endif()
42+
endif()
43+
44+
1045
add_subdirectory(simpleparser)
1146
add_subdirectory(src)

benchmarks/competitors/serde-benchmark/Cargo.lock

Lines changed: 103 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "serde-benchmark"
3+
version = "0.1.0"
4+
5+
[lib]
6+
path = "lib.rs"
7+
crate-type = ["cdylib"]
8+
9+
[dependencies]
10+
serde = { version = "1.0", features = ["derive"] }
11+
libc = "0.2"
12+
serde_json = "1.0"
13+
14+
[profile.release]
15+
opt-level = 3
16+
debug = false
17+
lto = true
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
## Rust Serde FFI
2+
3+
This folder includes FFI bindings for rust/serde.
4+
5+
### Links
6+
7+
- https://github.com/eqrion/cbindgen/blob/master/docs.md
8+
- https://gist.github.com/zbraniecki/b251714d77ffebbc73c03447f2b2c69f
9+
- https://michael-f-bryan.github.io/rust-ffi-guide/setting_up.html
10+
11+
### Building
12+
13+
- Generating cbindgen output
14+
- Install dependencies with `brew install cbindgen` or `apt-get install cbindgen` or `cargo install cbindgen` or the equivalent: we used `cargo install --version 0.23.0 cbindgen`.
15+
- Go to the directory where this README.md file is located
16+
- Generate with `cbindgen --config cbindgen.toml --crate serde-benchmark --output serde_benchmark.h`
17+
- Building
18+
- Run with `cargo build --release`
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
2+
include_version = true
3+
braces = "SameLine"
4+
line_length = 100
5+
tab_width = 2
6+
language = "C++"
7+
namespaces = ["serde_benchmark"]
8+
include_guard = "serde_benchmark_ffi_h"
9+
10+
[parse]
11+
parse_deps = true
12+
include = ["serde_json", "serde"]
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
extern crate serde;
2+
extern crate serde_json;
3+
extern crate libc;
4+
use std::slice;
5+
6+
use libc::{c_char, size_t};
7+
use serde::{Serialize, Deserialize};
8+
9+
/******************************************************/
10+
/******************************************************/
11+
/**
12+
* Warning: the C++ code may not generate the same JSON.
13+
*/
14+
/******************************************************/
15+
/******************************************************/
16+
17+
// This has no equivalent in C++:
18+
#[derive(Serialize, Deserialize)]
19+
pub struct Metadata {
20+
result_type: String,
21+
iso_language_code: String,
22+
}
23+
24+
#[derive(Serialize, Deserialize)]
25+
pub struct User {
26+
id: i64,
27+
id_str: String,
28+
name: String,
29+
screen_name: String,
30+
location: String,
31+
description: String,
32+
// C++ does not have those:
33+
// url: Option<String>,
34+
//protected: bool,
35+
//listed_count: i64,
36+
//created_at: String,
37+
//favourites_count: i64,
38+
//utc_offset: Option<i64>,
39+
//time_zone: Option<String>,
40+
//geo_enabled: bool,
41+
verified: bool,
42+
followers_count: i64,
43+
friends_count: i64,
44+
statuses_count: i64,
45+
// C++ does not have those:
46+
//lang: String,
47+
//profile_background_color: String,
48+
//profile_background_image_url: String,
49+
//profile_background_image_url_https: String,
50+
//profile_background_tile: bool,
51+
//profile_image_url: String,
52+
//profile_image_url_https: String,
53+
//profile_banner_url: Option<String>,
54+
//profile_link_color: String,
55+
//profile_sidebar_border_color: String,
56+
//profile_sidebar_fill_color: String,
57+
//profile_text_color: String,
58+
//profile_use_background_image: bool,
59+
//default_profile: bool,
60+
//default_profile_image: bool,
61+
//following: bool,
62+
//follow_request_sent: bool,
63+
//notifications: bool,
64+
}
65+
66+
#[derive(Serialize, Deserialize)]
67+
pub struct Hashtag {
68+
text: String,
69+
70+
// C++ has those but D. Lemire does not know what they are, they don't appear in the JSON:
71+
// int64_t indices_start;
72+
// int64_t indices_end;
73+
}
74+
75+
#[derive(Serialize, Deserialize)]
76+
pub struct Url {
77+
url: String,
78+
expanded_url: String,
79+
display_url: String,
80+
// C++ has those but D. Lemire does not know what they are, they don't appear in the JSON:
81+
// int64_t indices_start;
82+
// int64_t indices_end;
83+
}
84+
85+
#[derive(Serialize, Deserialize)]
86+
pub struct UserMention {
87+
id: i64,
88+
name: String,
89+
screen_name: String,
90+
// Not in the C++ equivalent:
91+
//id_str: String,
92+
//indices: Vec<i64>,
93+
// C++ has those but D. Lemire does not know what they are, they don't appear in the JSON:
94+
// int64_t indices_start;
95+
// int64_t indices_end;
96+
}
97+
98+
#[derive(Serialize, Deserialize)]
99+
pub struct Entities {
100+
hashtags: Vec<Hashtag>,
101+
urls: Vec<Url>,
102+
user_mentions: Vec<UserMention>,
103+
}
104+
105+
#[derive(Serialize, Deserialize)]
106+
pub struct Status {
107+
created_at: String,
108+
id: i64,
109+
text: String,
110+
user: User,
111+
entities: Entities,
112+
retweet_count: i64,
113+
favorite_count: i64,
114+
favorited: bool,
115+
retweeted: bool,
116+
// None of these are in the C++ equivalent:
117+
/*
118+
metadata: Metadata,
119+
id_str: String,
120+
source: String,
121+
truncated: bool,
122+
in_reply_to_status_id: Option<i64>,
123+
in_reply_to_status_id_str: Option<String>,
124+
in_reply_to_user_id: Option<i64>,
125+
in_reply_to_user_id_str: Option<String>,
126+
in_reply_to_screen_name: Option<String>,
127+
geo: Option<String>,
128+
coordinates: Option<String>,
129+
place: Option<String>,
130+
contributors: Option<String>,
131+
lang: String,
132+
*/
133+
}
134+
135+
#[derive(Serialize, Deserialize)]
136+
pub struct TwitterData {
137+
statuses: Vec<Status>,
138+
}
139+
140+
#[no_mangle]
141+
pub unsafe extern "C" fn twitter_from_str(raw_input: *const c_char, raw_input_length: size_t) -> *mut TwitterData {
142+
let input = std::str::from_utf8_unchecked(slice::from_raw_parts(raw_input as *const u8, raw_input_length));
143+
match serde_json::from_str(&input) {
144+
Ok(result) => Box::into_raw(Box::new(result)),
145+
Err(_) => std::ptr::null_mut(),
146+
}
147+
}
148+
149+
#[no_mangle]
150+
pub unsafe extern "C" fn str_from_twitter(raw: *mut TwitterData) -> *const c_char {
151+
let twitter_thing = { &*raw };
152+
let serialized = serde_json::to_string(&twitter_thing).unwrap();
153+
return std::ffi::CString::new(serialized.as_str()).unwrap().into_raw()
154+
}
155+
156+
157+
#[no_mangle]
158+
pub unsafe extern "C" fn free_twitter(raw: *mut TwitterData) {
159+
if raw.is_null() {
160+
return;
161+
}
162+
163+
drop(Box::from_raw(raw))
164+
}
165+
166+
167+
#[no_mangle]
168+
pub unsafe extern fn free_string(ptr: *const c_char) {
169+
let _ = std::ffi::CString::from_raw(ptr as *mut _);
170+
}

0 commit comments

Comments
 (0)