ronantakizawa/codereview-bench huggingface dataset:
Repository: sxyazi/yazi
File: yazi-plugin/src/elements/elements.rs (Rust)

Code before:
use mlua::{AnyUserData, IntoLua, Lua, Table, Value};
use tracing::error;

use super::Renderable;
use crate::Composer;

pub fn compose(lua: &Lua) -> mlua::Result<Value> {
	Composer::make(lua, 20, |lua, key| {
		match key {
			b"Bar" => super::Bar::compose(lua)?,
			b"Border" => super::Border::compose(lua)?,
			b"Clear" => super::Clear::compose(lua)?,
			b"Constraint" => super::Constraint::compose(lua)?,
			b"Gauge" => super::Gauge::compose(lua)?,
			b"Layout" => super::Layout::compose(lua)?,
			b"Line" => super::Line::compose(lua)?,
			b"List" => super::List::compose(lua)?,
			b"Pad" => super::Pad::compose(lua)?,
			b"Pos" => super::Pos::compose(lua)?,
			b"Rect" => super::Rect::compose(lua)?,
			b"Row" => super::Row::compose(lua)?,
			b"Span" => super::Span::compose(lua)?,
			b"Style" => super::Style::compose(lua)?,
			b"Table" => super::Table::compose(lua)?,
			b"Text" => super::Text::compose(lua)?,

			b"width" => super::Utils::width(lua)?,
			_ => return Ok(Value::Nil),
		}
		.into_lua(lua)
	})
}

pub fn render_once<F>(widgets: Table, buf: &mut ratatui::buffer::Buffer, trans: F)
where
	F: Fn(yazi_config::popup::Position) -> ratatui::layout::Rect + Copy,
{
	for widget in widgets.sequence_values::<AnyUserData>() {
		let Ok(widget) = widget else {
			error!("Failed to convert to renderable UserData: {}", widget.unwrap_err());
			continue;
		};

		match Renderable::try_from(widget) {
			Ok(w) => w.render(buf, trans),
			Err(e) => error!("{e}"),
		}
	}
}


Review comment (bug):
The fallback error message could include more context (e.g., the parent widget or its ID) and consider explicitly handling `Value::Nil` to aid in debugging when nothing is returned.
```suggestion
		Value::Nil => error!("Expected a renderable UserData or a table of them, but got Nil. This might indicate a missing or uninitialized value."),
		_ => error!("Expected a renderable UserData, or a table of them, but got an unexpected value: {value:?}. Please check the input or the parent widget for issues."),
```

Code after:
	})
}

pub fn render_once<F>(value: Value, buf: &mut ratatui::buffer::Buffer, trans: F)
where
	F: Fn(yazi_config::popup::Position) -> ratatui::layout::Rect + Copy,
{
	match value {
		Value::Table(tbl) => {
			for widget in tbl.sequence_values::<AnyUserData>() {
				let Ok(widget) = widget else {
					error!("Failed to convert to renderable UserData: {}", widget.unwrap_err());
					continue;
				};

				match Renderable::try_from(widget) {
					Ok(w) => w.render(buf, trans),
					Err(e) => error!("{e}"),
				}
			}
		}
		Value::UserData(ud) => match Renderable::try_from(ud) {
			Ok(w) => w.render(buf, trans),
			Err(e) => error!("{e}"),
		},
		_ => error!("Expected a renderable UserData, or a table of them, got: {value:?}"),
	}
}
Repository: sxyazi/yazi
File: yazi-plugin/src/elements/utils.rs (Rust)

Code before:
use mlua::{ExternalError, IntoLua, Lua, Value};
use unicode_width::UnicodeWidthStr;

use super::{Line, Span};

pub(super) struct Utils;

impl Utils {
	pub(super) fn width(lua: &Lua) -> mlua::Result<Value> {
		let f = lua.create_function(|_, v: Value| match v {
			Value::String(s) => {
				let (mut acc, b) = (0, s.as_bytes());
				for c in b.utf8_chunks() {
					acc += c.valid().width();
					if !c.invalid().is_empty() {
						acc += 1;
					}
				}
				Ok(acc)
			}
			Value::UserData(ud) => {
				if let Ok(line) = ud.borrow::<Line>() {
					Ok(line.inner.width())
				} else if let Ok(span) = ud.borrow::<Span>() {
					Ok(span.0.width())
				} else {
					Err("expected a string, Line, or Span".into_lua_err())?
				}
			}
			_ => Err("expected a string, Line, or Span".into_lua_err())?,
		})?;

		f.into_lua(lua)
	}
}


Review comment (refactor):
[nitpick] The layout‐field assignment logic for `current`, `preview`, and `progress` is hardcoded here; extracting this into a small helper would reduce duplication and simplify future updates.
```suggestion
			Utils::update_layout_field(&id, &c)?;
```

Code after:
					Ok(line.inner.width())
				} else if let Ok(span) = ud.borrow::<Span>() {
					Ok(span.0.width())
				} else {
					Err("expected a string, Line, or Span".into_lua_err())?
				}
			}
			_ => Err("expected a string, Line, or Span".into_lua_err())?,
		})?;

		f.into_lua(lua)
	}

	pub(super) fn redraw(lua: &Lua) -> mlua::Result<Value> {
		let f = lua.create_function(|lua, c: Table| {
			let id: mlua::String = c.get("_id")?;

			let mut layout = LAYOUT.get();
			match id.as_bytes().as_ref() {
				b"current" => layout.current = *c.raw_get::<crate::elements::Rect>("_area")?,
				b"preview" => layout.preview = *c.raw_get::<crate::elements::Rect>("_area")?,
				b"progress" => layout.progress = *c.raw_get::<crate::elements::Rect>("_area")?,
				_ => {}
			}

			LAYOUT.set(layout);
			match c.call_method::<Value>("redraw", ())? {
				Value::Table(tbl) => Ok(tbl),
				Value::UserData(ud) => lua.create_sequence_from([ud]),
				_ => {
					error!(
						"Failed to `redraw()` the `{}` component: expected a table or UserData",
						id.display(),
					);
					lua.create_table()
				}
			}
		})?;

		f.into_lua(lua)
	}
}
Repository: sxyazi/yazi
File: yazi-plugin/preset/components/progress.lua (Lua)

Code before:
		h = math.min(1, self._area.h),
	}
end

function Progress:reflow() return { self } end

function Progress:redraw()
	local progress = cx.tasks.progress
	if progress.total == 0 then
		return {}
	end

	local gauge = ui.Gauge():area(self._area)
	if progress.fail == 0 then
		gauge = gauge:gauge_style(th.status.progress_normal)
	else
		gauge = gauge:gauge_style(th.status.progress_error)
	end

	local percent = 99
	if progress.found ~= 0 then
		percent = math.min(99, ya.round(progress.processed * 100 / progress.found))
	end

	local left = progress.total - progress.succ
	return {
		gauge
			:percent(percent)
			:label(ui.Span(string.format("%3d%%, %d left", percent, left)):style(th.status.progress_label)),
	}
end


Review comment (suggestion):
Changing `Progress:redraw` from returning a table to a single widget is a breaking change for existing themes. Please document this adjustment in the changelog or migration guide.

Code after:
		h = math.min(1, self._area.h),
	}
end

function Progress:reflow() return { self } end

function Progress:redraw()
	local progress = cx.tasks.progress
	if progress.total == 0 then
		return {}
	end

	local gauge = ui.Gauge():area(self._area)
	if progress.fail == 0 then
		gauge = gauge:gauge_style(th.status.progress_normal)
	else
		gauge = gauge:gauge_style(th.status.progress_error)
	end

	local percent = 99
	if progress.found ~= 0 then
		percent = math.min(99, ya.round(progress.processed * 100 / progress.found))
	end

	local left = progress.total - progress.succ
	return gauge
		:percent(percent)
		:label(ui.Span(string.format("%3d%%, %d left", percent, left)):style(th.status.progress_label))
end
Repository: sxyazi/yazi
File: scripts/build.sh (Shell)

Code before:
#!/usr/bin/env bash
set -euo pipefail

export ARTIFACT_NAME="yazi-$1"
export YAZI_GEN_COMPLETIONS=1

# Build for the target
git config --global --add safe.directory "*"
cargo build --release --locked --target "$1"

# Create the artifact
mkdir -p "$ARTIFACT_NAME/completions"
cp "target/$1/release/ya" "$ARTIFACT_NAME"
cp "target/$1/release/yazi" "$ARTIFACT_NAME"
cp yazi-cli/completions/* "$ARTIFACT_NAME/completions"
cp yazi-boot/completions/* "$ARTIFACT_NAME/completions"
cp README.md LICENSE "$ARTIFACT_NAME"

# Zip the artifact
if ! command -v zip &> /dev/null; then
	apt-get update && apt-get install -yq zip
fi
zip -r "$ARTIFACT_NAME.zip" "$ARTIFACT_NAME"

# Package deb
cargo deb -p yazi-packing --no-build -o "$ARTIFACT_NAME.deb"


Review comment (bug):
[nitpick] Consider adding a check for the `cargo-deb` tool (e.g., `command -v cargo-deb`) and installing it if missing to avoid build failures on environments without `cargo-deb` installed.
```suggestion
# Package deb
if ! command -v cargo-deb &> /dev/null; then
    echo "cargo-deb not found. Installing..."
    cargo install cargo-deb
fi
```

Code after:
#!/usr/bin/env bash
set -euo pipefail

export ARTIFACT_NAME="yazi-$1"
export YAZI_GEN_COMPLETIONS=1

# Build for the target
git config --global --add safe.directory "*"
cargo build --release --locked --target "$1"

# Create the artifact
mkdir -p "$ARTIFACT_NAME/completions"
cp "target/$1/release/ya" "$ARTIFACT_NAME"
cp "target/$1/release/yazi" "$ARTIFACT_NAME"
cp yazi-cli/completions/* "$ARTIFACT_NAME/completions"
cp yazi-boot/completions/* "$ARTIFACT_NAME/completions"
cp README.md LICENSE "$ARTIFACT_NAME"

# Zip the artifact
if ! command -v zip &> /dev/null; then
	apt-get update && apt-get install -yq zip
fi
zip -r "$ARTIFACT_NAME.zip" "$ARTIFACT_NAME"

# Package deb
cargo install cargo-deb
cargo deb -p yazi-packing --no-build -o "$ARTIFACT_NAME.deb"
Repository: sxyazi/yazi
File: yazi-cli/src/package/package.rs (Rust)

Code before:
		})
	}

	pub(crate) async fn add_many(&mut self, uses: &[String]) -> Result<()> {
		for u in uses {
			let r = self.add(u).await;
			self.save().await?;
			r?;
		}
		Ok(())
	}

	pub(crate) async fn delete_many(&mut self, uses: &[String]) -> Result<()> {
		for u in uses {
			let r = self.delete(u).await;
			self.save().await?;
			r?;
		}
		Ok(())
	}

	pub(crate) async fn install(&mut self, upgrade: bool) -> Result<()> {
		for i in 0..self.plugins.len() {
			let r =
				if upgrade { self.plugins[i].upgrade().await } else { self.plugins[i].install().await };
			self.save().await?;
			r?;
		}
		for i in 0..self.flavors.len() {
			let r =
				if upgrade { self.flavors[i].upgrade().await } else { self.flavors[i].install().await };
			self.save().await?;
			r?;
		}
		Ok(())
	}

	pub(crate) fn print(&self) -> Result<()> {
		outln!("Plugins:")?;
		for d in &self.plugins {
			if d.rev.is_empty() {
				outln!("\t{}", d.r#use)?;
			} else {
				outln!("\t{} ({})", d.r#use, d.rev)?;
			}
		}

		outln!("Flavors:")?;
		for d in &self.flavors {
			if d.rev.is_empty() {
				outln!("\t{}", d.r#use)?;

Review comment (suggestion):
[nitpick] Saving state after each dependency operation leads to multiple I/O calls; consider saving once after processing all plugins and flavors.
```suggestion

```

Code after:
		})
	}

	pub(crate) async fn add_many(&mut self, uses: &[String]) -> Result<()> {
		for u in uses {
			let r = self.add(u).await;
			self.save().await?;
			r?;
		}
		Ok(())
	}

	pub(crate) async fn delete_many(&mut self, uses: &[String]) -> Result<()> {
		for u in uses {
			let r = self.delete(u).await;
			self.save().await?;
			r?;
		}
		Ok(())
	}

	pub(crate) async fn install(&mut self) -> Result<()> {
		macro_rules! go {
			($dep:expr) => {
				let r = $dep.install().await;
				self.save().await?;
				r?;
			};
		}

		for i in 0..self.plugins.len() {
			go!(self.plugins[i]);
		}
		for i in 0..self.flavors.len() {
			go!(self.flavors[i]);
		}
		Ok(())
	}

	pub(crate) async fn upgrade_many(&mut self, uses: &[String]) -> Result<()> {
		macro_rules! go {
			($dep:expr) => {
				if uses.contains(&$dep.r#use) {
					let r = $dep.upgrade().await;
					self.save().await?;
					r?;
				}
			};
		}

		for i in 0..self.plugins.len() {
Repository: sxyazi/yazi
File: yazi-cli/src/args.rs (Rust)

Code before:
	#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
	pub(super) args:     Vec<String>,
}

#[derive(Subcommand)]
pub(super) enum CommandPkg {
	/// Add packages.
	#[command(arg_required_else_help = true)]
	Add {
		/// The packages to add.
		#[arg(index = 1, num_args = 1..)]
		ids: Vec<String>,
	},
	/// Delete packages.
	#[command(arg_required_else_help = true)]
	Delete {
		/// The packages to delete.
		#[arg(index = 1, num_args = 1..)]
		ids: Vec<String>,
	},
	/// Install all packages.
	Install,
	/// List all packages.
	List,
	/// Upgrade all packages.
	Upgrade,
}

#[derive(clap::Args)]
#[command(arg_required_else_help = true)]
pub(super) struct CommandPack {
	/// Add packages.
	#[arg(short = 'a', long, num_args = 1..)]
	pub(super) add:     Option<Vec<String>>,
	/// Delete packages.
	#[arg(short = 'd', long, num_args = 1..)]
	pub(super) delete:  Option<Vec<String>>,
	/// Install all packages.
	#[arg(short = 'i', long)]
	pub(super) install: bool,
	/// List all packages.
	#[arg(short = 'l', long)]
	pub(super) list:    bool,
	/// Upgrade all packages.
	#[arg(short = 'u', long)]
	pub(super) upgrade: bool,
}

#[derive(clap::Args)]
pub(super) struct CommandPub {
	/// The kind of message.

Review comment (suggestion):
@sxyazi was this intentional? not sure on the codebase here but looking at the name, it does break if no IDs given. Just tested on `main` and found it.

Code after:
	#[arg(allow_hyphen_values = true, trailing_var_arg = true)]
	pub(super) args:     Vec<String>,
}

#[derive(Subcommand)]
pub(super) enum CommandPkg {
	/// Add packages.
	#[command(arg_required_else_help = true)]
	Add {
		/// The packages to add.
		#[arg(index = 1, num_args = 1..)]
		ids: Vec<String>,
	},
	/// Delete packages.
	#[command(arg_required_else_help = true)]
	Delete {
		/// The packages to delete.
		#[arg(index = 1, num_args = 1..)]
		ids: Vec<String>,
	},
	/// Install all packages.
	Install,
	/// List all packages.
	List,
	/// Upgrade all packages.
	#[command(arg_required_else_help = true)]
	Upgrade {
		/// The packages to delete.
		#[arg(index = 1, num_args = 1..)]
		ids: Vec<String>,
	},
}

#[derive(clap::Args)]
#[command(arg_required_else_help = true)]
pub(super) struct CommandPack {
	/// Add packages.
	#[arg(short = 'a', long, num_args = 1..)]
	pub(super) add:     Option<Vec<String>>,
	/// Delete packages.
	#[arg(short = 'd', long, num_args = 1..)]
	pub(super) delete:  Option<Vec<String>>,
	/// Install all packages.
	#[arg(short = 'i', long)]
	pub(super) install: bool,
	/// List all packages.
	#[arg(short = 'l', long)]
	pub(super) list:    bool,
	/// Upgrade all packages.
	#[arg(short = 'u', long)]
	pub(super) upgrade: bool,
Repository: sxyazi/yazi
File: yazi-fm/src/app/app.rs (Rust)

Code before:
	pub(crate) async fn serve() -> Result<()> {
		let term = Term::start()?;
		let (mut rx, signals) = (Event::take(), Signals::start()?);

		let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
		app.render();

		let mut times = 0;
		let mut events = Vec::with_capacity(200);
		while rx.recv_many(&mut events, 50).await > 0 {
			for event in events.drain(..) {
				times += 1;
				app.dispatch(event)?;
			}

			if !NEED_RENDER.swap(false, Ordering::Relaxed) {
				continue;
			}

			if times >= 50 {
				times = 0;
				app.render();
			} else if let Ok(event) = rx.try_recv() {
				events.push(event);
				emit!(Render);
			} else {
				times = 0;
				app.render();
			}
		}
		Ok(())
	}

	#[inline]
	fn dispatch(&mut self, event: Event) -> Result<()> {
		match event {
			Event::Call(cmd) => self.dispatch_call(cmd),
			Event::Seq(cmds) => self.dispatch_seq(cmds),
			Event::Render => self.dispatch_render(),
			Event::Key(key) => self.dispatch_key(key),
			Event::Mouse(mouse) => self.mouse(mouse),
			Event::Resize => self.resize(()),
			Event::Paste(str) => self.dispatch_paste(str),
			Event::Quit(opt) => self.quit(opt),
		}
		Ok(())
	}

	#[inline]
	fn dispatch_call(&mut self, cmd: CmdCow) { Executor::new(self).execute(cmd); }


Review comment (suggestion):
After calling `app.render()`, the `NEED_RENDER` flag isn't reset, which can lead to continuous rendering. Consider swapping or clearing the flag (e.g., `NEED_RENDER.swap(false, Ordering::Relaxed)`) after a render.
```suggestion
						app.render();
						NEED_RENDER.store(false, Ordering::Relaxed);
```

Code after:
impl App {
	pub(crate) async fn serve() -> Result<()> {
		let term = Term::start()?;
		let (mut rx, signals) = (Event::take(), Signals::start()?);

		let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
		app.render();

		let mut events = Vec::with_capacity(50);
		macro_rules! drain_events {
			() => {
				for event in events.drain(..) {
					app.dispatch(event)?;
					try_render!();
				}
			};
		}

		let (mut timeout, mut last_render) = (None, Instant::now());
		macro_rules! try_render {
			() => {
				if NEED_RENDER.load(Ordering::Relaxed) {
					if let Some(sub) = Duration::from_millis(10).checked_sub(last_render.elapsed()) {
						timeout = Some(sleep(sub));
					} else {
						app.render();
						(timeout, last_render) = (None, Instant::now());
					}
				}
			};
		}

		loop {
			if let Some(t) = timeout.take() {
				select! {
					_ = t => {
						app.render();
						last_render = Instant::now();
					}
					n = rx.recv_many(&mut events, 50) => {
						if n == 0 { break }
						drain_events!();
					}
				}
			} else if rx.recv_many(&mut events, 50).await > 0 {
				drain_events!();
			} else {
				break;
			}
		}
		Ok(())
Repository: sxyazi/yazi
File: yazi-fm/src/app/app.rs (Rust)

Code before:
		let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
		app.render();

		let mut times = 0;
		let mut events = Vec::with_capacity(200);
		while rx.recv_many(&mut events, 50).await > 0 {
			for event in events.drain(..) {
				times += 1;
				app.dispatch(event)?;
			}

			if !NEED_RENDER.swap(false, Ordering::Relaxed) {
				continue;
			}

			if times >= 50 {
				times = 0;
				app.render();
			} else if let Ok(event) = rx.try_recv() {
				events.push(event);
				emit!(Render);
			} else {
				times = 0;
				app.render();
			}
		}
		Ok(())
	}

	#[inline]
	fn dispatch(&mut self, event: Event) -> Result<()> {
		match event {
			Event::Call(cmd) => self.dispatch_call(cmd),
			Event::Seq(cmds) => self.dispatch_seq(cmds),
			Event::Render => self.dispatch_render(),
			Event::Key(key) => self.dispatch_key(key),
			Event::Mouse(mouse) => self.mouse(mouse),
			Event::Resize => self.resize(()),
			Event::Paste(str) => self.dispatch_paste(str),
			Event::Quit(opt) => self.quit(opt),
		}
		Ok(())
	}

	#[inline]
	fn dispatch_call(&mut self, cmd: CmdCow) { Executor::new(self).execute(cmd); }

	#[inline]
	fn dispatch_seq(&mut self, mut cmds: Vec<CmdCow>) {
		if let Some(last) = cmds.pop() {
			Executor::new(self).execute(last);

Review comment (refactor):
[nitpick] Defining macros inline within the function body can obscure control flow. Consider extracting these macros to the module level or converting them into helper functions to improve readability.

Code after:

		let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
		app.render();

		let mut events = Vec::with_capacity(50);
		macro_rules! drain_events {
			() => {
				for event in events.drain(..) {
					app.dispatch(event)?;
					try_render!();
				}
			};
		}

		let (mut timeout, mut last_render) = (None, Instant::now());
		macro_rules! try_render {
			() => {
				if NEED_RENDER.load(Ordering::Relaxed) {
					if let Some(sub) = Duration::from_millis(10).checked_sub(last_render.elapsed()) {
						timeout = Some(sleep(sub));
					} else {
						app.render();
						(timeout, last_render) = (None, Instant::now());
					}
				}
			};
		}

		loop {
			if let Some(t) = timeout.take() {
				select! {
					_ = t => {
						app.render();
						last_render = Instant::now();
					}
					n = rx.recv_many(&mut events, 50) => {
						if n == 0 { break }
						drain_events!();
					}
				}
			} else if rx.recv_many(&mut events, 50).await > 0 {
				drain_events!();
			} else {
				break;
			}
		}
		Ok(())
	}

	#[inline]
	fn dispatch(&mut self, event: Event) -> Result<()> {
Repository: sxyazi/yazi
File: yazi-fm/src/app/app.rs (Rust)

Code before:
}

impl App {
	pub(crate) async fn serve() -> Result<()> {
		let term = Term::start()?;
		let (mut rx, signals) = (Event::take(), Signals::start()?);

		let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
		app.render();

		let mut events = Vec::with_capacity(50);
		macro_rules! drain_events {
			() => {
				for event in events.drain(..) {
					app.dispatch(event)?;
					try_render!();
				}
			};
		}

		let (mut timeout, mut last_render) = (None, Instant::now());
		macro_rules! try_render {
			() => {
				if NEED_RENDER.load(Ordering::Relaxed) {
					if let Some(sub) = Duration::from_millis(10).checked_sub(last_render.elapsed()) {
						timeout = timeout.or_else(|| Some(sleep(sub)));
					} else {
						app.render();
						(timeout, last_render) = (None, Instant::now());
					}
				}
			};
		}

		loop {
			if let Some(t) = timeout.take() {
				select! {
					_ = t => {
						app.render();
						last_render = Instant::now();
					}
					n = rx.recv_many(&mut events, 50) => {
						if n == 0 { break }
						drain_events!();
					}
				}
			} else if rx.recv_many(&mut events, 50).await > 0 {
				drain_events!();
			} else {
				break;
			}

Review comment (suggestion):
Using `timeout = timeout.or_else(...)` means once `timeout` is set it never gets refreshed with a shorter duration; this could stall subsequent renders. Consider replacing with always updating, e.g., `timeout = Some(sleep(sub));` or conditionally resetting based on a comparison.
```suggestion
						timeout = Some(sleep(sub));
```

Code after:
}

impl App {
	pub(crate) async fn serve() -> Result<()> {
		let term = Term::start()?;
		let (mut rx, signals) = (Event::take(), Signals::start()?);

		let mut app = Self { cx: Ctx::make(), term: Some(term), signals };
		app.render();

		let mut events = Vec::with_capacity(50);
		let (mut timeout, mut last_render) = (None, Instant::now());
		macro_rules! drain_events {
			() => {
				for event in events.drain(..) {
					app.dispatch(event)?;
					if !NEED_RENDER.load(Ordering::Relaxed) {
						continue;
					}

					timeout = Duration::from_millis(10).checked_sub(last_render.elapsed());
					if timeout.is_none() {
						app.render();
						last_render = Instant::now();
					}
				}
			};
		}

		loop {
			if let Some(t) = timeout.take() {
				select! {
					_ = sleep(t) => {
						app.render();
						last_render = Instant::now();
					}
					n = rx.recv_many(&mut events, 50) => {
						if n == 0 { break }
						drain_events!();
					}
				}
			} else if rx.recv_many(&mut events, 50).await > 0 {
				drain_events!();
			} else {
				break;
			}
		}
		Ok(())
	}

	#[inline]