Skip to content

Commit

Permalink
Merge pull request #48 from KillTheMule/nobufw
Browse files Browse the repository at this point in the history
Nobufw
  • Loading branch information
KillTheMule authored Feb 3, 2024
2 parents 0d2b1c8 + 7ea91dc commit a9c6b1f
Show file tree
Hide file tree
Showing 15 changed files with 203 additions and 62 deletions.
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

0 comments on commit a9c6b1f

Please sign in to comment.