Skip to content

Simplify split api #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 31, 2025
Merged

Simplify split api #151

merged 4 commits into from
Mar 31, 2025

Conversation

Ddystopia
Copy link
Contributor

@Ddystopia Ddystopia commented Mar 23, 2025

Shortly, this PR merged split and split_with into a single function and removed unsplit.

let (mut reader, mut writer) = tls.split();

std::thread::scope(|scope| {
    scope.spawn(|| {
        let mut buffer = [0; 4];
        reader.read_exact(&mut buffer).expect("Failed to read data");
    });
    scope.spawn(|| {
        writer.write(b"ping").expect("Failed to write data");
        writer.flush().expect("Failed to flush");
    });
});

tls.close()
    .map_err(|(_, e)| e)
    .expect("error closing session");

Instead of

let mut state = SplitConnectionState::default();
let (mut reader, mut writer) = tls.split_with(&mut state);

std::thread::scope(|scope| {
    scope.spawn(|| {
        let mut buffer = [0; 4];
        reader.read_exact(&mut buffer).expect("Failed to read data");
    });
    scope.spawn(|| {
        writer.write(b"ping").expect("Failed to write data");
        writer.flush().expect("Failed to flush");
    });
});

let tls = TlsConnection::unsplit(reader, writer);

tls.close()
    .map_err(|(_, e)| e)
    .expect("error closing session");

Splitting is a common pattern in Rust, but embedded-tls had implemented it in a peculiar way. Unfortunately, this way is not ergonomic and does not compose well.

Commonly, split exclusively borrows self and returns two sides which are using it's data. Original entity cannot be used because it is mutably borrow while children are alive. When both dropped, parent is automatically released by the borrow checker.

A good example is heapless::Queue::split

I tried to use embedded-tls with other, traditional, "split" APIs, but unsplit approach just doesn't work here due to variance issues - you need to have &mut to put back reader and writer, so you can use unsplit, but reader and writer are not static, thus lifetime becomes invariant, making it unusable. You can read more about variance in the corresponding rustonomicon section.

That PR converted split to the borrowing version and removed a number of not really needed types. Implementations of buffers became a little bit more explicit, to improve borrow checker's behavior.

@lulf lulf mentioned this pull request Mar 31, 2025
@lulf lulf merged commit a6f398a into drogue-iot:main Mar 31, 2025
3 of 7 checks passed
@lulf
Copy link
Member

lulf commented Mar 31, 2025

@Ddystopia Thanks for the PR, I merged it in #152.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants