Skip to content

Commit dba391b

Browse files
committed
cbindgen: Add version defines
This will allow users to check the version of rustls-ffi without resorting to checking if functions are defined. Also add make rustls_version_match verify that defines are the correct. In addition to RUSTLS_VERSION_{MAJOR,MINOR,PATCH}, also define RUSTLS_VERSION_NUMBER, which includes each version part in it, bit shifted to the left. This is inspired by openssl[0], c-ares[1]. There are other options for this, for example zstd multiplies each part by a power of 100[2]. We might want to also have the entire version string here, which could help tools that need to parse the header file itself. [0] https://github.com/openssl/openssl/blob/cdd01b5e0734b0324251b32a8edd97f42ba90429/include/openssl/opensslv.h.in#L92-L102 [1] https://github.com/c-ares/c-ares/blob/42ddbc14ec008e738fa44aa2c16e74cad93742c2/include/ares_version.h#L43-L45 [2] https://github.com/facebook/zstd/blob/3c3b8274c517727952927c705940eb90c10c736f/lib/zstd.h#L115 Fixes #557
1 parent 9779eb7 commit dba391b

File tree

5 files changed

+80
-1
lines changed

5 files changed

+80
-1
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

librustls/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[package]
22
name = "rustls-ffi"
3+
# Keep in sync with defines in cbindgen.toml
34
version = "0.15.0"
45
license = "Apache-2.0 OR ISC OR MIT"
56
readme = "../README-crates.io.md"
@@ -42,6 +43,8 @@ crate-type = ["lib", "staticlib"]
4243
[dev-dependencies]
4344
regex = { workspace = true }
4445
toml = { workspace = true }
46+
tree-sitter = { workspace = true }
47+
tree-sitter-c = { workspace = true }
4548

4649
[package.metadata.capi.header]
4750
name = "rustls"

librustls/cbindgen.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,22 @@ language = "C"
33

44
usize_is_size_t = true
55

6+
# Keep in sync with "package.version" in Cargo.toml
7+
after_includes = """
8+
9+
#define RUSTLS_VERSION_MAJOR 0
10+
#define RUSTLS_VERSION_MINOR 15
11+
#define RUSTLS_VERSION_PATCH 0
12+
13+
/**
14+
* This gives each version part 8 bits, and leaves the 8 least significant bits
15+
* empty for future additions, for example pre-release versions.
16+
*/
17+
#define RUSTLS_VERSION_NUMBER ((RUSTLS_VERSION_MAJOR << 24) \\
18+
|(RUSTLS_VERSION_MINOR << 16) \\
19+
|(RUSTLS_VERSION_MINOR << 8))
20+
"""
21+
622
[enum]
723
prefix_with_name = true
824
rename_variants = "ScreamingSnakeCase"

librustls/src/rustls.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@
77
#include <stdint.h>
88
#include <stdlib.h>
99

10+
#define RUSTLS_VERSION_MAJOR 0
11+
#define RUSTLS_VERSION_MINOR 15
12+
#define RUSTLS_VERSION_PATCH 0
13+
14+
/**
15+
* This gives each version part 8 bits, and leaves the 8 least significant bits
16+
* empty for future additions, for example pre-release versions.
17+
*/
18+
#define RUSTLS_VERSION_NUMBER ((RUSTLS_VERSION_MAJOR << 24) \
19+
|(RUSTLS_VERSION_MINOR << 16) \
20+
|(RUSTLS_VERSION_MINOR << 8))
21+
22+
1023
/**
1124
* Describes which sort of handshake happened.
1225
*/

librustls/tests/rustls_version.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#![cfg(not(feature = "capi"))]
22
use std::fs::File;
3+
use std::fs::read_to_string;
34
use std::io::Read;
45
use std::path::PathBuf;
56

67
use toml::Table;
8+
use tree_sitter::{Parser, Query, QueryCursor};
79

810
use rustls_ffi::rustls_version;
911

@@ -12,8 +14,10 @@ use rustls_ffi::rustls_version;
1214
/// In particular this ensures that the Rustls version reported in the rustls-ffi version string
1315
/// matches the version of the Rustls dependency that rustls-ffi was built with.
1416
///
17+
/// It also ensures that the correct version parts defines are in src/rustls.h
18+
///
1519
/// If this test starts to fail, you probably forgot to update `RUSTLS_CRATE_VERSION` in
16-
/// `build.rs`.
20+
/// `build.rs`, or forgot to update cbindgen.toml with new version parts (or run cbindgen again).
1721
#[cfg_attr(miri, ignore)] // Requires file I/O
1822
#[test]
1923
fn rustls_version_match() {
@@ -71,4 +75,45 @@ fn rustls_version_match() {
7175
rustls_crypto_provider,
7276
]
7377
);
78+
let version_in_header = version_in_header();
79+
assert_eq!(crate_version, version_in_header, "Version in header (.h file) doesn't match version Cargo.toml");
80+
}
81+
82+
#[cfg_attr(miri, ignore)] // Requires file I/O
83+
fn version_in_header() -> String {
84+
// Create a C parser.
85+
let mut parser = Parser::new();
86+
let language = tree_sitter_c::LANGUAGE;
87+
parser.set_language(&language.into()).unwrap();
88+
89+
// Parse the .h into an AST.
90+
let header_file = read_to_string("src/rustls.h").expect("Couldn't read header file");
91+
92+
let header_file_bytes = header_file.as_bytes();
93+
let tree = parser
94+
.parse(&header_file, None)
95+
.ok_or("no tree parsed from input")
96+
.unwrap();
97+
let root_node = tree.root_node();
98+
let query = r#"( preproc_def name: (identifier) @define.name )"#;
99+
let query = Query::new(&language.into(), query).unwrap();
100+
let mut cursor = QueryCursor::new();
101+
let matches = cursor.matches(&query, root_node, header_file_bytes);
102+
let mut version_parts: [&str; 3] = Default::default();
103+
for query_match in matches {
104+
for preproc in query_match.nodes_for_capture_index(0) {
105+
let parent = preproc.parent().unwrap();
106+
if let Some(value_node) = parent.child_by_field_name("value") {
107+
let key = preproc.utf8_text(header_file_bytes).unwrap();
108+
let value = value_node.utf8_text(header_file_bytes).unwrap();
109+
match key {
110+
"RUSTLS_VERSION_MAJOR" => { version_parts[0] = value; }
111+
"RUSTLS_VERSION_MINOR" => { version_parts[1] = value; }
112+
"RUSTLS_VERSION_PATCH" => { version_parts[2] = value; }
113+
_ => (),
114+
}
115+
}
116+
}
117+
}
118+
return format!("{0}.{1}.{2}", version_parts[0], version_parts[1], version_parts[2]);
74119
}

0 commit comments

Comments
 (0)