Skip to main content

waterui_cli/preview/
protocol.rs

1//! Preview command protocol types.
2//!
3//! This module defines the messages exchanged between:
4//! - CLI → Preview support app (render commands via TCP)
5//! - Preview support app → CLI (render results via TCP)
6
7/// Target platform for a native preview support app.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum PreviewPlatform {
10    /// Physical iOS device.
11    Ios,
12    /// iOS Simulator.
13    IosSimulator,
14    /// macOS.
15    Macos,
16    /// Android device or emulator.
17    Android,
18}
19
20impl std::str::FromStr for PreviewPlatform {
21    type Err = String;
22
23    fn from_str(s: &str) -> Result<Self, Self::Err> {
24        match s.to_lowercase().as_str() {
25            "ios" => Ok(Self::Ios),
26            "ios-simulator" | "iossimulator" => Ok(Self::IosSimulator),
27            "macos" => Ok(Self::Macos),
28            "android" => Ok(Self::Android),
29            _ => Err(format!("Unknown platform: {s}")),
30        }
31    }
32}
33
34pub use waterui_preview_protocol::{
35    DylibId, DylibSource, PREVIEW_PROTOCOL_COMMIT, PreviewError as AppError,
36    PreviewOutput as AppOutput, PreviewProtocolInfo, PreviewRequest as AppRequest,
37    PreviewResponse as AppResponse, PreviewRuntimePlatform, Size,
38};
39
40pub use waterui_preview_protocol::tcp::PreviewTcpConfig;
41
42/// Convert a function path to preview export symbol.
43///
44/// Example:
45/// - `sidebar` with crate `my-crate` -> `waterui_preview_my_crate_sidebar`
46/// - `dashboard::admin::card_preview` with crate `my-crate`
47///   -> `waterui_preview_my_crate_card_preview`
48///
49/// # Panics
50///
51/// Panics if `function_path` does not end with a function name.
52#[must_use]
53pub fn function_path_to_symbol(crate_name: &str, function_path: &str) -> String {
54    // Replace dashes with underscores (Cargo uses dashes, Rust uses underscores)
55    let crate_name = crate_name.replace('-', "_");
56    let function_name = function_path
57        .rsplit("::")
58        .next()
59        .expect("splitting a string always yields one segment");
60    assert!(
61        !function_name.is_empty(),
62        "preview function path must end with a function name"
63    );
64    format!("waterui_preview_{crate_name}_{function_name}")
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_function_path_to_symbol() {
73        assert_eq!(
74            function_path_to_symbol("my_crate", "sidebar"),
75            "waterui_preview_my_crate_sidebar"
76        );
77
78        assert_eq!(
79            function_path_to_symbol("my-crate", "dashboard::admin::card_preview"),
80            "waterui_preview_my_crate_card_preview"
81        );
82    }
83}