Skip to content

Commit 0f3efe4

Browse files
committed
Add parse function to Rust RBS bindings (#53)
The `parse` function enables parsing RBS code from Rust. This provides a safe Rust interface to the C parser, handling memory management and encoding setup.
1 parent d60e030 commit 0f3efe4

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

rust/ruby-rbs/src/lib.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,44 @@
11
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
2+
use rbs_encoding_type_t::RBS_ENCODING_UTF_8;
23
use ruby_rbs_sys::bindings::*;
4+
use std::sync::Once;
5+
6+
static INIT: Once = Once::new();
7+
8+
/// Parse RBS code into an AST.
9+
///
10+
/// ```rust
11+
/// use ruby_rbs::parse;
12+
/// let rbs_code = r#"type foo = "hello""#;
13+
/// let signature = parse(rbs_code.as_bytes());
14+
/// assert!(signature.is_ok(), "Failed to parse RBS signature");
15+
/// ```
16+
pub fn parse(rbs_code: &[u8]) -> Result<*mut rbs_signature_t, String> {
17+
unsafe {
18+
INIT.call_once(|| {
19+
rbs_constant_pool_init(RBS_GLOBAL_CONSTANT_POOL, 26);
20+
});
21+
22+
let start_ptr = rbs_code.as_ptr() as *const i8;
23+
let end_ptr = start_ptr.add(rbs_code.len());
24+
25+
let raw_rbs_string_value = rbs_string_new(start_ptr, end_ptr);
26+
27+
let encoding_ptr = &rbs_encodings[RBS_ENCODING_UTF_8 as usize] as *const rbs_encoding_t;
28+
let parser = rbs_parser_new(raw_rbs_string_value, encoding_ptr, 0, rbs_code.len() as i32);
29+
30+
let mut signature: *mut rbs_signature_t = std::ptr::null_mut();
31+
let result = rbs_parse_signature(parser, &mut signature);
32+
33+
rbs_parser_free(parser);
34+
35+
if result {
36+
Ok(signature)
37+
} else {
38+
Err(String::from("Failed to parse RBS signature"))
39+
}
40+
}
41+
}
342

443
pub struct RBSString {
544
pointer: *const rbs_string_t,
@@ -17,3 +56,19 @@ impl RBSString {
1756
}
1857
}
1958
}
59+
60+
#[cfg(test)]
61+
mod tests {
62+
use super::*;
63+
64+
#[test]
65+
fn test_parse() {
66+
let rbs_code = r#"type foo = "hello""#;
67+
let signature = parse(rbs_code.as_bytes());
68+
assert!(signature.is_ok(), "Failed to parse RBS signature");
69+
70+
let rbs_code2 = r#"class Foo end"#;
71+
let signature2 = parse(rbs_code2.as_bytes());
72+
assert!(signature2.is_ok(), "Failed to parse RBS signature");
73+
}
74+
}

0 commit comments

Comments
 (0)