feat(owlry-core): define IPC message types with serde

This commit is contained in:
2026-03-26 12:17:16 +01:00
parent 1bce5850a3
commit 71d78ce7df
3 changed files with 176 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Request {
Query {
text: String,
#[serde(skip_serializing_if = "Option::is_none")]
modes: Option<Vec<String>>,
},
Launch {
item_id: String,
provider: String,
},
Providers,
Refresh {
provider: String,
},
Toggle,
Submenu {
plugin_id: String,
data: String,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Response {
Results {
items: Vec<ResultItem>,
},
Providers {
list: Vec<ProviderDesc>,
},
SubmenuItems {
items: Vec<ResultItem>,
},
Ack,
Error {
message: String,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ResultItem {
pub id: String,
pub title: String,
pub description: String,
pub icon: String,
pub provider: String,
pub score: i64,
#[serde(skip_serializing_if = "Option::is_none")]
pub command: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub tags: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ProviderDesc {
pub id: String,
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub prefix: Option<String>,
pub icon: String,
pub position: String,
}

View File

@@ -1,6 +1,7 @@
pub mod config;
pub mod data;
pub mod filter;
pub mod ipc;
pub mod notify;
pub mod paths;
pub mod plugins;

View File

@@ -0,0 +1,109 @@
use owlry_core::ipc::{ProviderDesc, Request, Response, ResultItem};
#[test]
fn test_query_request_roundtrip() {
let req = Request::Query {
text: "fire".into(),
modes: Some(vec!["app".into(), "cmd".into()]),
};
let json = serde_json::to_string(&req).unwrap();
let parsed: Request = serde_json::from_str(&json).unwrap();
assert_eq!(req, parsed);
}
#[test]
fn test_query_request_without_modes() {
let req = Request::Query {
text: "fire".into(),
modes: None,
};
let json = serde_json::to_string(&req).unwrap();
assert!(!json.contains("modes"));
let parsed: Request = serde_json::from_str(&json).unwrap();
assert_eq!(req, parsed);
}
#[test]
fn test_launch_request_roundtrip() {
let req = Request::Launch {
item_id: "firefox.desktop".into(),
provider: "app".into(),
};
let json = serde_json::to_string(&req).unwrap();
let parsed: Request = serde_json::from_str(&json).unwrap();
assert_eq!(req, parsed);
}
#[test]
fn test_results_response_roundtrip() {
let resp = Response::Results {
items: vec![ResultItem {
id: "firefox.desktop".into(),
title: "Firefox".into(),
description: "Web Browser".into(),
icon: "firefox".into(),
provider: "app".into(),
score: 95,
command: Some("firefox".into()),
tags: vec![],
}],
};
let json = serde_json::to_string(&resp).unwrap();
let parsed: Response = serde_json::from_str(&json).unwrap();
assert_eq!(resp, parsed);
}
#[test]
fn test_providers_response() {
let resp = Response::Providers {
list: vec![ProviderDesc {
id: "app".into(),
name: "Applications".into(),
prefix: Some(":app".into()),
icon: "application-x-executable".into(),
position: "normal".into(),
}],
};
let json = serde_json::to_string(&resp).unwrap();
let parsed: Response = serde_json::from_str(&json).unwrap();
assert_eq!(resp, parsed);
}
#[test]
fn test_error_response() {
let resp = Response::Error {
message: "plugin not found".into(),
};
let json = serde_json::to_string(&resp).unwrap();
let parsed: Response = serde_json::from_str(&json).unwrap();
assert_eq!(resp, parsed);
}
#[test]
fn test_toggle_request() {
let req = Request::Toggle;
let json = serde_json::to_string(&req).unwrap();
let parsed: Request = serde_json::from_str(&json).unwrap();
assert_eq!(req, parsed);
}
#[test]
fn test_submenu_request() {
let req = Request::Submenu {
plugin_id: "systemd".into(),
data: "docker.service".into(),
};
let json = serde_json::to_string(&req).unwrap();
let parsed: Request = serde_json::from_str(&json).unwrap();
assert_eq!(req, parsed);
}
#[test]
fn test_refresh_request() {
let req = Request::Refresh {
provider: "clipboard".into(),
};
let json = serde_json::to_string(&req).unwrap();
let parsed: Request = serde_json::from_str(&json).unwrap();
assert_eq!(req, parsed);
}