feat: add a new sender property to the DDS payload (#855)

This commit is contained in:
三咲雅 · Misaki Masa 2024-03-31 22:29:52 +08:00 committed by GitHub
parent fd455a1ae4
commit bfcf401b40
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 90 additions and 111 deletions

View file

@ -8,7 +8,7 @@ use crate::Payload;
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Body<'a> {
Hi(BodyHi),
Hi(BodyHi<'a>),
Hey(BodyHey),
Tabs(BodyTabs<'a>),
Cd(BodyCd<'a>),

View file

@ -32,12 +32,7 @@ impl<'a> From<BodyBulk<'a>> for Body<'a> {
impl IntoLua<'_> for BodyBulk<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
lua
.create_any_userdata(BodyBulkIter {
tab: self.tab,
inner: self.changes.into_owned().into_iter(),
})?
.into_lua(lua)
BodyBulkIter { tab: self.tab, inner: self.changes.into_owned().into_iter() }.into_lua(lua)
}
}

View file

@ -8,22 +8,23 @@ use super::Body;
#[derive(Debug, Serialize, Deserialize)]
pub struct BodyCd<'a> {
pub owned: bool,
pub tab: usize,
pub url: Cow<'a, Url>,
pub tab: usize,
pub url: Cow<'a, Url>,
#[serde(skip)]
dummy: bool,
}
impl<'a> BodyCd<'a> {
#[inline]
pub fn borrowed(tab: usize, url: &'a Url) -> Body<'a> {
Self { owned: false, tab, url: Cow::Borrowed(url) }.into()
Self { tab, url: Cow::Borrowed(url), dummy: false }.into()
}
}
impl BodyCd<'static> {
#[inline]
pub fn owned(tab: usize) -> Body<'static> {
Self { owned: false, tab, url: Default::default() }.into()
pub fn dummy(tab: usize) -> Body<'static> {
Self { tab, url: Default::default(), dummy: true }.into()
}
}
@ -33,10 +34,10 @@ impl<'a> From<BodyCd<'a>> for Body<'a> {
impl IntoLua<'_> for BodyCd<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if self.owned {
if let Some(Cow::Owned(url)) = Some(self.url).filter(|_| !self.dummy) {
lua.create_table_from([
("tab", self.tab.into_lua(lua)?),
("url", lua.create_any_userdata(self.url.into_owned())?.into_lua(lua)?),
("url", lua.create_any_userdata(url)?.into_lua(lua)?),
])?
} else {
lua.create_table_from([("tab", self.tab)])?

View file

@ -1,4 +1,4 @@
use std::collections::HashSet;
use std::{borrow::Cow, collections::HashSet};
use mlua::{ExternalResult, IntoLua, Lua, Value};
use serde::{Deserialize, Serialize};
@ -6,16 +6,22 @@ use serde::{Deserialize, Serialize};
use super::Body;
#[derive(Debug, Serialize, Deserialize)]
pub struct BodyHi {
pub id: u64,
pub abilities: HashSet<String>,
pub struct BodyHi<'a> {
pub abilities: HashSet<Cow<'a, String>>,
}
impl From<BodyHi> for Body<'_> {
fn from(value: BodyHi) -> Self { Self::Hi(value) }
impl<'a> BodyHi<'a> {
#[inline]
pub fn borrowed(abilities: HashSet<&'a String>) -> Body<'a> {
Self { abilities: abilities.into_iter().map(Cow::Borrowed).collect() }.into()
}
}
impl IntoLua<'_> for BodyHi {
impl<'a> From<BodyHi<'a>> for Body<'a> {
fn from(value: BodyHi<'a>) -> Self { Self::Hi(value) }
}
impl IntoLua<'_> for BodyHi<'_> {
fn into_lua(self, _: &Lua) -> mlua::Result<Value<'_>> {
Err("BodyHi cannot be converted to Lua").into_lua_err()
}

View file

@ -8,21 +8,20 @@ use super::Body;
#[derive(Debug, Serialize, Deserialize)]
pub struct BodyHover<'a> {
pub owned: bool,
pub tab: usize,
pub url: Option<Cow<'a, Url>>,
pub tab: usize,
pub url: Option<Cow<'a, Url>>,
}
impl<'a> BodyHover<'a> {
#[inline]
pub fn borrowed(tab: usize, url: Option<&'a Url>) -> Body<'a> {
Self { owned: false, tab, url: url.map(Cow::Borrowed) }.into()
Self { tab, url: url.map(Cow::Borrowed) }.into()
}
}
impl BodyHover<'static> {
#[inline]
pub fn owned(tab: usize) -> Body<'static> { Self { owned: false, tab, url: None }.into() }
pub fn dummy(tab: usize) -> Body<'static> { Self { tab, url: None }.into() }
}
impl<'a> From<BodyHover<'a>> for Body<'a> {
@ -31,10 +30,10 @@ impl<'a> From<BodyHover<'a>> for Body<'a> {
impl IntoLua<'_> for BodyHover<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if self.owned && self.url.is_some() {
if let Some(Cow::Owned(url)) = self.url {
lua.create_table_from([
("tab", self.tab.into_lua(lua)?),
("url", lua.create_any_userdata(self.url.unwrap().into_owned())?.into_lua(lua)?),
("url", lua.create_any_userdata(url)?.into_lua(lua)?),
])?
} else {
lua.create_table_from([("tab", self.tab)])?

View file

@ -22,7 +22,7 @@ impl<'a> BodyRename<'a> {
impl BodyRename<'static> {
#[inline]
pub fn owned(tab: usize, from: &Url, to: &Url) -> Body<'static> {
pub fn dummy(tab: usize, from: &Url, to: &Url) -> Body<'static> {
Self { tab, from: Cow::Owned(from.clone()), to: Cow::Owned(to.clone()) }.into()
}
}

View file

@ -1,6 +1,6 @@
use std::borrow::Cow;
use mlua::{IntoLua, Lua, MetaMethod, UserData, Value};
use mlua::{MetaMethod, UserData};
use serde::{Deserialize, Serialize};
use yazi_shared::fs::Url;
@ -8,7 +8,6 @@ use super::Body;
#[derive(Debug, Serialize, Deserialize)]
pub struct BodyTabs<'a> {
pub owned: bool,
pub cursor: usize,
pub items: Vec<BodyTabsItem<'a>>,
}
@ -16,59 +15,20 @@ pub struct BodyTabs<'a> {
impl<'a> BodyTabs<'a> {
#[inline]
pub fn borrowed(cursor: usize, urls: &[&'a Url]) -> Body<'a> {
Self {
owned: false,
cursor,
items: urls.iter().map(|&u| BodyTabsItem { url: Cow::Borrowed(u) }).collect(),
}
.into()
Self { cursor, items: urls.iter().map(|&u| BodyTabsItem::from(u)).collect() }.into()
}
}
impl BodyTabs<'static> {
#[inline]
pub fn owned(cursor: usize) -> Body<'static> {
Self { owned: false, cursor, items: Default::default() }.into()
}
pub fn dummy(cursor: usize) -> Body<'static> { Self { cursor, items: Default::default() }.into() }
}
impl<'a> From<BodyTabs<'a>> for Body<'a> {
fn from(value: BodyTabs<'a>) -> Self { Self::Tabs(value) }
}
impl IntoLua<'_> for BodyTabs<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value<'_>> {
if self.owned {
BodyTabsIter::from(self).into_lua(lua)
} else {
lua.create_table_from([("cursor", self.cursor)])?.into_lua(lua)
}
}
}
// --- Item
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BodyTabsItem<'a> {
pub url: Cow<'a, Url>,
}
impl UserData for BodyTabsItem<'static> {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("url", |lua, me| lua.create_any_userdata(me.url.clone()));
}
}
// --- Iterator
pub struct BodyTabsIter {
pub cursor: usize,
pub items: Vec<BodyTabsItem<'static>>,
}
impl From<BodyTabs<'static>> for BodyTabsIter {
fn from(value: BodyTabs<'static>) -> Self { Self { cursor: value.cursor, items: value.items } }
}
impl UserData for BodyTabsIter {
impl UserData for BodyTabs<'static> {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("cursor", |_, me| Ok(me.cursor));
}
@ -81,3 +41,19 @@ impl UserData for BodyTabsIter {
});
}
}
// --- Item
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BodyTabsItem<'a> {
pub url: Cow<'a, Url>,
}
impl<'a> From<&'a Url> for BodyTabsItem<'a> {
fn from(value: &'a Url) -> Self { Self { url: Cow::Borrowed(value) } }
}
impl UserData for BodyTabsItem<'static> {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("url", |lua, me| lua.create_any_userdata(me.url.clone()));
}
}

View file

@ -8,23 +8,20 @@ use super::Body;
#[derive(Debug, Serialize, Deserialize)]
pub struct BodyYank<'a> {
pub owned: bool,
pub cut: bool,
pub urls: Cow<'a, HashSet<Url>>,
pub cut: bool,
pub urls: Cow<'a, HashSet<Url>>,
}
impl<'a> BodyYank<'a> {
#[inline]
pub fn borrowed(cut: bool, urls: &'a HashSet<Url>) -> Body<'a> {
Self { owned: false, cut, urls: Cow::Borrowed(urls) }.into()
Self { cut, urls: Cow::Borrowed(urls) }.into()
}
}
impl BodyYank<'static> {
#[inline]
pub fn owned(cut: bool) -> Body<'static> {
Self { owned: false, cut, urls: Default::default() }.into()
}
pub fn dummy(cut: bool) -> Body<'static> { Self { cut, urls: Default::default() }.into() }
}
impl<'a> From<BodyYank<'a>> for Body<'a> {
@ -33,8 +30,8 @@ impl<'a> From<BodyYank<'a>> for Body<'a> {
impl IntoLua<'_> for BodyYank<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value<'_>> {
if self.owned {
BodyYankIter::from(self).into_lua(lua)
if let Cow::Owned(urls) = self.urls {
BodyYankIter { cut: self.cut, urls: urls.into_iter().collect() }.into_lua(lua)
} else {
lua.create_table_from([("cut", self.cut)])?.into_lua(lua)
}
@ -47,12 +44,6 @@ pub struct BodyYankIter {
pub urls: Vec<Url>,
}
impl From<BodyYank<'static>> for BodyYankIter {
fn from(value: BodyYank) -> Self {
Self { cut: value.cut, urls: value.urls.into_owned().into_iter().collect() }
}
}
impl UserData for BodyYankIter {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("is_cut", |_, me| Ok(me.cut));

View file

@ -4,18 +4,19 @@ use anyhow::{anyhow, Result};
use yazi_boot::BOOT;
use yazi_shared::{emit, event::Cmd, Layer};
use crate::body::Body;
use crate::{body::Body, ID};
#[derive(Debug)]
pub struct Payload<'a> {
pub receiver: u64,
pub severity: u8,
pub sender: u64,
pub body: Body<'a>,
}
impl<'a> Payload<'a> {
#[inline]
pub(super) fn new(body: Body<'a>) -> Self { Self { receiver: 0, severity: 0, body } }
pub(super) fn new(body: Body<'a>) -> Self { Self { receiver: 0, severity: 0, sender: *ID, body } }
#[inline]
pub(super) fn with_receiver(mut self, receiver: u64) -> Self {
@ -56,7 +57,7 @@ impl FromStr for Payload<'_> {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s.splitn(4, ',');
let mut parts = s.splitn(5, ',');
let kind = parts.next().ok_or_else(|| anyhow!("empty kind"))?;
@ -66,9 +67,12 @@ impl FromStr for Payload<'_> {
let severity =
parts.next().and_then(|s| s.parse().ok()).ok_or_else(|| anyhow!("invalid severity"))?;
let sender =
parts.next().and_then(|s| s.parse().ok()).ok_or_else(|| anyhow!("invalid sender"))?;
let body = parts.next().ok_or_else(|| anyhow!("empty body"))?;
Ok(Self { receiver, severity, body: Body::from_str(kind, body)? })
Ok(Self { receiver, severity, sender, body: Body::from_str(kind, body)? })
}
}
@ -87,7 +91,7 @@ impl Display for Payload<'_> {
};
if let Ok(s) = result {
write!(f, "{},{},{},{s}", self.body.kind(), self.receiver, self.severity)
write!(f, "{},{},{},{},{s}", self.body.kind(), self.receiver, self.severity, self.sender)
} else {
Err(std::fmt::Error)
}

View file

@ -88,69 +88,70 @@ impl Pubsub {
}
pub fn pub_from_hi() -> bool {
Client::push(Payload::new(
BodyHi { id: *ID, abilities: REMOTE.read().keys().cloned().collect() }.into(),
));
let abilities = REMOTE.read().keys().cloned().collect();
let abilities = BOOT.remote_events.union(&abilities).collect();
Client::push(BodyHi::borrowed(abilities).upgrade());
true
}
pub fn pub_from_tabs(tab: usize, urls: &[&Url]) {
if LOCAL.read().contains_key("tabs") {
Self::pub_(BodyTabs::owned(tab));
Self::pub_(BodyTabs::dummy(tab));
}
if PEERS.read().values().any(|p| p.able("tabs")) {
Client::push(BodyTabs::borrowed(tab, urls).upgrade());
}
if BOOT.local_events.contains("tabs") {
BodyTabs::borrowed(tab, urls).upgrade().flush(true);
BodyTabs::borrowed(tab, urls).upgrade().with_receiver(*ID).flush(true);
}
}
pub fn pub_from_cd(tab: usize, url: &Url) {
if LOCAL.read().contains_key("cd") {
Self::pub_(BodyCd::owned(tab));
Self::pub_(BodyCd::dummy(tab));
}
if PEERS.read().values().any(|p| p.able("cd")) {
Client::push(BodyCd::borrowed(tab, url).upgrade());
}
if BOOT.local_events.contains("cd") {
BodyCd::borrowed(tab, url).upgrade().flush(true);
BodyCd::borrowed(tab, url).upgrade().with_receiver(*ID).flush(true);
}
}
pub fn pub_from_hover(tab: usize, url: Option<&Url>) {
if LOCAL.read().contains_key("hover") {
Self::pub_(BodyHover::owned(tab));
Self::pub_(BodyHover::dummy(tab));
}
if PEERS.read().values().any(|p| p.able("hover")) {
Client::push(BodyHover::borrowed(tab, url).upgrade());
}
if BOOT.local_events.contains("hover") {
BodyHover::borrowed(tab, url).upgrade().flush(true);
BodyHover::borrowed(tab, url).upgrade().with_receiver(*ID).flush(true);
}
}
pub fn pub_from_rename(tab: usize, from: &Url, to: &Url) {
if LOCAL.read().contains_key("rename") {
Self::pub_(BodyRename::owned(tab, from, to));
Self::pub_(BodyRename::dummy(tab, from, to));
}
if PEERS.read().values().any(|p| p.able("rename")) {
Client::push(BodyRename::borrowed(tab, from, to).upgrade());
}
if BOOT.local_events.contains("rename") {
BodyRename::borrowed(tab, from, to).upgrade().flush(true);
BodyRename::borrowed(tab, from, to).upgrade().with_receiver(*ID).flush(true);
}
}
pub fn pub_from_yank(cut: bool, urls: &HashSet<Url>) {
if LOCAL.read().contains_key("yank") {
Self::pub_(BodyYank::owned(cut));
Self::pub_(BodyYank::dummy(cut));
}
if PEERS.read().values().any(|p| p.able("yank")) {
Client::push(BodyYank::borrowed(cut, urls).upgrade());
}
if BOOT.local_events.contains("yank") {
BodyYank::borrowed(cut, urls).upgrade().flush(true);
BodyYank::borrowed(cut, urls).upgrade().with_receiver(*ID).flush(true);
}
}
}

View file

@ -92,16 +92,21 @@ impl Server {
}
fn handle_hi(s: String, id: &mut Option<u64>, tx: mpsc::UnboundedSender<String>) {
let Ok(Body::Hi(hi)) = Payload::from_str(&s).map(|p| p.body) else { return };
let Ok(payload) = Payload::from_str(&s) else { return };
let Body::Hi(hi) = payload.body else { return };
let mut clients = CLIENTS.write();
id.replace(hi.id).and_then(|id| clients.remove(&id));
id.replace(payload.sender).and_then(|id| clients.remove(&id));
if let Some(ref state) = *STATE.read() {
state.values().for_each(|s| _ = tx.send(format!("{s}\n")));
}
clients.insert(hi.id, Client { id: hi.id, tx, abilities: hi.abilities });
clients.insert(payload.sender, Client {
id: payload.sender,
tx,
abilities: hi.abilities.into_iter().map(|s| s.into_owned()).collect(),
});
Self::handle_hey(&clients);
}

View file

@ -36,10 +36,11 @@ impl State {
let mut inner = HashMap::new();
while buf.read_line(&mut line).await? > 0 {
let mut parts = line.splitn(4, ',');
let mut parts = line.splitn(5, ',');
let Some(kind) = parts.next() else { continue };
let Some(_) = parts.next() else { continue };
let Some(severity) = parts.next().and_then(|s| s.parse::<u8>().ok()) else { continue };
let Some(_) = parts.next() else { continue };
let Some(body) = parts.next() else { continue };
inner.insert(format!("{}_{severity}_{kind}", Body::tab(kind, body)), mem::take(&mut line));
}