Skip to content
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

Nobufw #48

Merged
merged 7 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ async-std = { version = "1.12.0", features = ["attributes"], optional = true }
neovim-lib = { version = "0.6.1", optional = true }
parity-tokio-ipc = { version = "0.9.0", optional = true }

[target.'cfg(windows)'.dependencies]
winapi = { version = '*', features = ["winerror"] }

[dev-dependencies]
tempfile = "3.8.0"
# TODO: if changing tempfile: the rand version is based on whatever version
Expand Down Expand Up @@ -109,3 +112,15 @@ required-features = ["use_tokio"]

[[test]]
name = "basic"

[[test]]
name = "regression"
path = "tests/regression/mod.rs"

[[bin]]
name = "linebuffercrash"
required-features = ["use_tokio"]

[[bin]]
name = "linebuffercrash_as"
required-features = ["use_async-std"]
8 changes: 4 additions & 4 deletions examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use async_trait::async_trait;

use rmpv::Value;

use tokio::io::Stdout;
use tokio::fs::File as TokioFile;

use nvim_rs::{
compat::tokio::Compat, create::tokio as create, rpc::IntoVal, Handler, Neovim,
Expand All @@ -17,13 +17,13 @@ struct NeovimHandler {}

#[async_trait]
impl Handler for NeovimHandler {
type Writer = Compat<Stdout>;
type Writer = Compat<TokioFile>;

async fn handle_request(
&self,
name: String,
_args: Vec<Value>,
_neovim: Neovim<Compat<Stdout>>,
_neovim: Neovim<Compat<TokioFile>>,
) -> Result<Value, Value> {
match name.as_ref() {
"ping" => Ok(Value::from("pong")),
Expand All @@ -35,7 +35,7 @@ impl Handler for NeovimHandler {
#[tokio::main]
async fn main() {
let handler: NeovimHandler = NeovimHandler {};
let (nvim, io_handler) = create::new_parent(handler).await;
let (nvim, io_handler) = create::new_parent(handler).await.unwrap();
let curbuf = nvim.get_current_buf().await.unwrap();

let mut envargs = env::args();
Expand Down
26 changes: 11 additions & 15 deletions examples/bench_async-std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,22 @@ use async_trait::async_trait;

use rmpv::Value;

use async_std::io::Stdout;
use async_std;
use async_std::{self, fs::File as ASFile};

use nvim_rs::{
create::async_std as create, Handler, Neovim,
};
use nvim_rs::{create::async_std as create, Handler, Neovim};

#[derive(Clone)]
struct NeovimHandler{}
struct NeovimHandler {}

#[async_trait]
impl Handler for NeovimHandler {
type Writer =Stdout;
type Writer = ASFile;

async fn handle_request(
&self,
name: String,
_args: Vec<Value>,
neovim: Neovim<Stdout>,
neovim: Neovim<ASFile>,
) -> Result<Value, Value> {
match name.as_ref() {
"file" => {
Expand All @@ -31,30 +28,29 @@ impl Handler for NeovimHandler {
let _x = c.get_lines(0, -1, false).await;
}
Ok(Value::Nil)
},
}
"buffer" => {
for _ in 0..10_000_usize {
let _ = neovim.get_current_buf().await.unwrap();
}
Ok(Value::Nil)
},
}
"api" => {
for _ in 0..1_000_usize {
let _ = neovim.get_api_info().await.unwrap();
}
Ok(Value::Nil)
},
_ => Ok(Value::Nil)
}
_ => Ok(Value::Nil),
}
}
}

#[async_std::main]
async fn main() {
let handler: NeovimHandler = NeovimHandler {};

let handler: NeovimHandler = NeovimHandler{};

let (nvim, io_handler) = create::new_parent(handler).await;
let (nvim, io_handler) = create::new_parent(handler).await.unwrap();

// Any error should probably be logged, as stderr is not visible to users.
match io_handler.await {
Expand Down
21 changes: 10 additions & 11 deletions examples/bench_tokio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@ use async_trait::async_trait;

use rmpv::Value;

use tokio::io::Stdout;
use tokio::fs::File as TokioFile;

use nvim_rs::{
compat::tokio::Compat, create::tokio as create, Handler, Neovim,
};

#[derive(Clone)]
struct NeovimHandler{}
struct NeovimHandler {}

#[async_trait]
impl Handler for NeovimHandler {
type Writer = Compat<Stdout>;
type Writer = Compat<TokioFile>;

async fn handle_request(
&self,
name: String,
_args: Vec<Value>,
neovim: Neovim<Compat<Stdout>>,
neovim: Neovim<Compat<TokioFile>>,
) -> Result<Value, Value> {
match name.as_ref() {
"file" => {
Expand All @@ -30,30 +30,29 @@ impl Handler for NeovimHandler {
let _x = c.get_lines(0, -1, false).await;
}
Ok(Value::Nil)
},
}
"buffer" => {
for _ in 0..10_000_usize {
let _ = neovim.get_current_buf().await.unwrap();
}
Ok(Value::Nil)
},
}
"api" => {
for _ in 0..1_000_usize {
let _ = neovim.get_api_info().await.unwrap();
}
Ok(Value::Nil)
},
_ => Ok(Value::Nil)
}
_ => Ok(Value::Nil),
}
}
}

#[tokio::main]
async fn main() {
let handler: NeovimHandler = NeovimHandler {};

let handler: NeovimHandler = NeovimHandler{};

let (nvim, io_handler) = create::new_parent(handler).await;
let (nvim, io_handler) = create::new_parent(handler).await.unwrap();

// Any error should probably be logged, as stderr is not visible to users.
match io_handler.await {
Expand Down
8 changes: 4 additions & 4 deletions examples/scorched_earth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use async_trait::async_trait;
use rmpv::Value;

use futures::lock::Mutex;
use tokio::io::Stdout;
use tokio::fs::File as TokioFile;

use nvim_rs::{
compat::tokio::Compat, create::tokio as create, Handler, Neovim,
Expand Down Expand Up @@ -44,13 +44,13 @@ struct NeovimHandler(Arc<Mutex<Posis>>);

#[async_trait]
impl Handler for NeovimHandler {
type Writer = Compat<Stdout>;
type Writer = Compat<TokioFile>;

async fn handle_notify(
&self,
name: String,
args: Vec<Value>,
neovim: Neovim<Compat<Stdout>>,
neovim: Neovim<Compat<TokioFile>>,
) {
match name.as_ref() {
"cursor-moved-i" => {
Expand Down Expand Up @@ -102,7 +102,7 @@ async fn main() {
};
let handler: NeovimHandler = NeovimHandler(Arc::new(Mutex::new(p)));

let (nvim, io_handler) = create::new_parent(handler).await;
let (nvim, io_handler) = create::new_parent(handler).await.unwrap();

// Any error should probably be logged, as stderr is not visible to users.
match io_handler.await {
Expand Down
12 changes: 5 additions & 7 deletions examples/scorched_earth_as.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@ use rmpv::Value;

use futures::lock::Mutex;

use nvim_rs::{
create::async_std as create, Handler, Neovim,
};
use nvim_rs::{create::async_std as create, Handler, Neovim};

use async_std::{self, io::Stdout};
use async_std::{self, fs::File as ASFile};

struct Posis {
cursor_start: Option<(u64, u64)>,
Expand Down Expand Up @@ -45,13 +43,13 @@ struct NeovimHandler(Arc<Mutex<Posis>>);

#[async_trait]
impl Handler for NeovimHandler {
type Writer = Stdout;
type Writer = ASFile;

async fn handle_notify(
&self,
name: String,
args: Vec<Value>,
neovim: Neovim<Stdout>,
neovim: Neovim<ASFile>,
) {
match name.as_ref() {
"cursor-moved-i" => {
Expand Down Expand Up @@ -103,7 +101,7 @@ async fn main() {
};
let handler: NeovimHandler = NeovimHandler(Arc::new(Mutex::new(p)));

let (nvim, io_handler) = create::new_parent(handler).await;
let (nvim, io_handler) = create::new_parent(handler).await.unwrap();

// Any error should probably be logged, as stderr is not visible to users.
match io_handler.await {
Expand Down
24 changes: 24 additions & 0 deletions src/bin/linebuffercrash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

use nvim_rs::{
create::tokio as create,
rpc::handler::Dummy as DummyHandler
};


#[tokio::main]
async fn main() {
let handler = DummyHandler::new();
let (nvim, _io_handler) = create::new_parent(handler).await.unwrap();
let curbuf = nvim.get_current_buf().await.unwrap();

// If our Stdout is linebuffered, this has a high chance of crashing neovim
// Should probably befixed in neovim itself, but for now, let's just make
// sure we're not using linebuffering, or at least don't crash neovim with
// this.
for i in 0..20 {
curbuf.set_name(&format!("a{i}")).await.unwrap();
}

let _ = nvim.command("quit!").await;

}
24 changes: 24 additions & 0 deletions src/bin/linebuffercrash_as.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

use nvim_rs::{
create::async_std as create,
rpc::handler::Dummy as DummyHandler
};


#[async_std::main]
async fn main() {
let handler = DummyHandler::new();
let (nvim, _io_handler) = create::new_parent(handler).await.unwrap();
let curbuf = nvim.get_current_buf().await.unwrap();

// If our Stdout is linebuffered, this has a high chance of crashing neovim
// Should probably befixed in neovim itself, but for now, let's just make
// sure we're not using linebuffering, or at least don't crash neovim with
// this.
for i in 0..20 {
curbuf.set_name(&format!("a{i}")).await.unwrap();
}

let _ = nvim.command("quit!").await;

}
19 changes: 13 additions & 6 deletions src/create/async_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use std::{future::Future, io};
use async_std::os::unix::net::UnixStream;

use async_std::{
io::{stdin, stdout, Stdout},
fs::File as ASFile,
io::stdin,
net::{TcpStream, ToSocketAddrs},
task::{spawn, JoinHandle},
};
Expand All @@ -16,7 +17,12 @@ use async_std::path::Path;

use futures::io::{AsyncReadExt, WriteHalf};

use crate::{create::Spawner, error::LoopError, neovim::Neovim, Handler};
use crate::{
create::{unbuffered_stdout, Spawner},
error::LoopError,
neovim::Neovim,
Handler,
};

impl<H> Spawner for H
where
Expand Down Expand Up @@ -78,12 +84,13 @@ where
/// Connect to the neovim instance that spawned this process over stdin/stdout
pub async fn new_parent<H>(
handler: H,
) -> (Neovim<Stdout>, JoinHandle<Result<(), Box<LoopError>>>)
) -> io::Result<(Neovim<ASFile>, JoinHandle<Result<(), Box<LoopError>>>)>
where
H: Handler<Writer = Stdout>,
H: Handler<Writer = ASFile>,
{
let (neovim, io) = Neovim::<Stdout>::new(stdin(), stdout(), handler);
let sout: ASFile = unbuffered_stdout()?.into();
let (neovim, io) = Neovim::<ASFile>::new(stdin(), sout, handler);
let io_handle = spawn(io);

(neovim, io_handle)
Ok((neovim, io_handle))
}
18 changes: 18 additions & 0 deletions src/create/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod tokio;
pub mod async_std;

use core::future::Future;
use std::{fs::File, io};

use crate::rpc::handler::Handler;

Expand All @@ -36,3 +37,20 @@ pub trait Spawner: Handler {
where
Fut: Future<Output = ()> + Send + 'static;
}

/// Create a std::io::File for stdout, which is not line-buffered, as
/// opposed to std::io::Stdout.
#[cfg(unix)]
pub fn unbuffered_stdout() -> io::Result<File> {
use std::{io::stdout, os::fd::AsFd};

let owned_sout_fd = stdout().as_fd().try_clone_to_owned()?;
Ok(File::from(owned_sout_fd))
}
#[cfg(windows)]
pub fn unbuffered_stdout() -> io::Result<File> {
use std::{io::stdout, os::windows::io::AsHandle};

let owned_sout_handle = stdout().as_handle().try_clone_to_owned()?;
Ok(File::from(owned_sout_handle))
}
Loading
Loading