Skip to content

Commit a51c769

Browse files
committed
feat: add parse_fd for file descriptor input
1 parent eda29d2 commit a51c769

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

librdb/src/parser.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{ffi::CString, marker::PhantomData, path::Path, ptr};
1+
use std::{ffi::CString, marker::PhantomData, os::fd::RawFd, path::Path, ptr};
22

33
use librdb_sys::{
44
self, RdbHandlersDataCallbacks, RdbStatus_RDB_STATUS_ERROR, RdbStatus_RDB_STATUS_OK,
@@ -116,6 +116,35 @@ impl<H: RdbHandlers> Parser<H> {
116116
self.run_parse()
117117
}
118118

119+
/// Attach a file-descriptor reader and parse the RDB data.
120+
///
121+
/// If `close_when_done` is true, librdb will close the fd after parsing.
122+
/// The fd must be in blocking mode.
123+
///
124+
/// # Errors
125+
/// Returns an error if the reader cannot be created, the RDB data is
126+
/// malformed, or a handler callback returns `Err`.
127+
pub fn parse_fd(&mut self, fd: RawFd, close_when_done: bool) -> Result<()> {
128+
if self.parsed {
129+
return Err(RdbError::Parser {
130+
code: 0,
131+
message: "parser already used; create a new Parser instance".into(),
132+
});
133+
}
134+
135+
// SAFETY: self.raw is a valid parser in CONFIGURING state. The caller
136+
// is responsible for providing a valid, blocking fd.
137+
let reader = unsafe {
138+
librdb_sys::RDBX_createReaderFileDesc(self.raw, fd, i32::from(close_when_done))
139+
};
140+
if reader.is_null() {
141+
return Err(self.extract_c_error("RDBX_createReaderFileDesc returned null"));
142+
}
143+
144+
self.parsed = true;
145+
self.run_parse()
146+
}
147+
119148
fn run_parse(&mut self) -> Result<()> {
120149
// SAFETY: parser and reader are valid, callbacks are wired.
121150
let status = unsafe { librdb_sys::RDB_parse(self.raw) };

librdb/tests/level2.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,3 +643,20 @@ fn empty_rdb() {
643643
assert!(events.contains(&Event::EndRdb));
644644
assert!(keys_of(&events).is_empty());
645645
}
646+
647+
#[test]
648+
fn parse_fd_single_key() {
649+
use std::fs::File;
650+
use std::os::fd::IntoRawFd;
651+
652+
let file = File::open(fixture("single_key.rdb")).expect("open fixture");
653+
let fd = file.into_raw_fd(); // transfer ownership to librdb
654+
655+
let mut parser = Parser::new(Collector::default()).expect("create parser");
656+
parser.parse_fd(fd, true).expect("parse");
657+
let events = parser.into_handler().events;
658+
659+
let keys = keys_of(&events);
660+
assert_eq!(keys, vec![b"xxx"]);
661+
assert!(events.contains(&Event::StringValue(b"111".to_vec())));
662+
}

0 commit comments

Comments
 (0)