Skip to content

Commit 1e1655a

Browse files
committed
Lib.rs got fixed
1 parent 34d7276 commit 1e1655a

File tree

1 file changed

+71
-181
lines changed

1 file changed

+71
-181
lines changed

src/lib.rs

Lines changed: 71 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -14,217 +14,107 @@ It exposes two areas:
1414
The examples below mirror common usage: creating a
1515
manifest, sending/receiving JSON messages, and running an async loop.
1616
17-
---
17+
## Encode a JSON message into a native-messaging frame
1818
19-
## Quick start
20-
21-
Add deps:
22-
23-
```toml
24-
[dependencies]
25-
native_messaging = { path = "." } # this crate, if you're developing locally
26-
tokio = { version = "1", features = ["full"] }
27-
serde = { version = "1", features = ["derive"] }
28-
serde_json = "1"
29-
```
30-
31-
---
32-
33-
## The wire format (tl;dr)
34-
35-
```text
36-
[0..4) : 32-bit length (native-endian)
37-
[4..N) : UTF-8 JSON payload of that length
38-
```
39-
40-
Browsers spawn your program and connect **stdin/stdout**; you read frames from
41-
stdin and write frames to stdout.
42-
43-
---
44-
45-
## Messaging examples
46-
47-
### Read a single message
48-
49-
```no_run
50-
use native_messaging::host::get_message;
51-
52-
#[tokio::main]
53-
async fn main() {
54-
match get_message().await {
55-
Ok(json) => println!("Received: {json}"),
56-
Err(e) => eprintln!("Error receiving message: {e}"),
57-
}
58-
}
59-
```
60-
61-
### Send a single message
62-
63-
```no_run
64-
use native_messaging::host::send_message;
65-
use serde::Serialize;
66-
67-
#[derive(Serialize)]
68-
struct MyMessage { content: String }
69-
70-
#[tokio::main]
71-
async fn main() -> std::io::Result<()> {
72-
let msg = MyMessage { content: "Hello, world!".into() };
73-
send_message(&msg).await
74-
}
75-
```
76-
77-
### Encode a message to a native-messaging frame
78-
79-
```no_run
19+
```rust
8020
use native_messaging::host::encode_message;
8121
use serde::Serialize;
8222
8323
#[derive(Serialize)]
84-
struct Msg { hello: String }
85-
86-
fn main() {
87-
let frame = encode_message(&Msg { hello: "world".into() })
88-
.expect("serialize");
89-
assert!(frame.len() >= 4);
24+
struct Msg {
25+
hello: &'static str,
9026
}
91-
```
92-
93-
### Run an async event loop
9427
95-
```no_run
96-
use native_messaging::host::{event_loop, send_message};
97-
98-
#[tokio::main]
99-
async fn main() {
100-
event_loop(|raw: String| async move {
101-
// Echo the raw JSON back to the browser
102-
send_message(&raw).await
103-
}).await;
104-
}
28+
// Encode to a 4-byte-length-prefixed frame:
29+
let frame = encode_message(&Msg { hello: "world" }).unwrap();
30+
assert!(frame.len() >= 4);
10531
```
10632
107-
### Structured messages (enums)
33+
## Read a message and reply on stdout (async)
10834
10935
```no_run
110-
use native_messaging::host::{event_loop, send_message};
36+
use native_messaging::host::{get_message, send_message};
11137
use serde::{Deserialize, Serialize};
11238
11339
#[derive(Deserialize)]
114-
#[serde(tag="type", rename_all="snake_case")]
115-
enum In {
116-
Ping { id: u64, payload: String },
117-
}
40+
struct In { ping: String }
11841
11942
#[derive(Serialize)]
120-
struct Out { id: u64, echo: String, ok: bool }
121-
122-
#[tokio::main]
123-
async fn main() {
124-
event_loop(|raw: String| async move {
125-
match serde_json::from_str::<In>(&raw) {
126-
Ok(In::Ping { id, payload }) => {
127-
send_message(&Out { id, echo: payload, ok: true }).await
128-
}
129-
Err(e) => {
130-
eprintln!("bad json: {e}");
131-
Ok(())
132-
}
133-
}
134-
}).await;
135-
}
136-
```
137-
138-
---
43+
struct Out { pong: String }
13944
140-
## Host manifest management
45+
// Create a minimal Tokio runtime just for the example:
46+
let rt = tokio::runtime::Runtime::new().unwrap();
47+
rt.block_on(async {
48+
// Your API returns a raw String
49+
let raw = get_message().await.unwrap();
14150
142-
> On macOS/Linux the manifest `path` **must be absolute** (use your built
143-
> binary path). Chrome/Edge use `allowed_origins`; Firefox uses
144-
> `allowed_extensions`. This crate abstracts the placement logic per browser.
51+
// Parse to your input type
52+
let incoming: In = serde_json::from_str(&raw).unwrap();
14553
146-
### Install for multiple browsers
147-
148-
```ignore
149-
// This is marked `ignore` so rustdoc won't try to compile it, because the exact
150-
// signature of `install` (browsers/enums/scope) depends on your crate version.
151-
// Use this as a template and adjust types to your API.
152-
153-
use std::path::Path;
154-
use native_messaging::install::manifest::{install, Browser, Scope};
155-
156-
fn main() -> std::io::Result<()> {
157-
let path = Path::new("/absolute/path/to/target/release/host-binary");
158-
let allowed_origins: Vec<String> = vec![
159-
"chrome-extension://your_ext_id/".to_string(),
160-
"chrome-extension://another_id/".to_string(),
161-
];
162-
163-
let browsers = &[Browser::Chrome, Browser::Firefox];
164-
165-
// Adjust arguments to match your `install` signature exactly.
166-
install("com.example.host", "Example Host", path, &allowed_origins, browsers, Scope::User)
167-
}
54+
// Build and send a reply
55+
let reply = Out { pong: incoming.ping };
56+
send_message(&reply).await.unwrap();
57+
});
16858
```
16959
170-
### Verify / Remove
60+
## Run the event loop
17161
172-
```ignore
173-
// Marked `ignore` to avoid signature drift across versions.
174-
// Adapt to your actual function signatures.
175-
176-
use native_messaging::install::manifest::{verify, remove, Browser, Scope};
177-
178-
fn main() -> std::io::Result<()> {
179-
// Some versions take only `name`, others also take browsers/scope.
180-
if verify("com.example.host")? {
181-
// Adjust remove signature as needed (browsers/scope).
182-
remove("com.example.host", &[Browser::Firefox], Scope::User)?;
183-
}
184-
Ok(())
185-
}
186-
```
187-
188-
---
189-
190-
## Extension-side (Chrome/Edge MV3)
62+
```no_run
63+
use native_messaging::host::{event_loop, send_message};
64+
use serde::Serialize;
65+
use std::io;
19166
192-
```javascript
193-
// background.js
194-
const port = chrome.runtime.connectNative("com.example.host");
195-
port.onMessage.addListener(msg => console.log("host:", msg));
196-
port.postMessage({ type: "ping", payload: "hello", id: 1 });
67+
#[derive(Serialize)]
68+
struct Out { pong: String }
69+
70+
// The event loop receives raw String messages and expects the handler future to
71+
// resolve to io::Result<()>.
72+
let rt = tokio::runtime::Runtime::new().unwrap();
73+
rt.block_on(async {
74+
event_loop(|msg: String| async move {
75+
// In real code, you'd parse `msg` into a structured type first.
76+
let reply = Out { pong: msg };
77+
send_message(&reply).await?;
78+
Ok::<(), io::Error>(())
79+
})
80+
.await;
81+
});
19782
```
19883
199-
Ensure your host manifest lists the extension (origin for Chrome/Edge or
200-
extension ID for Firefox).
201-
202-
---
203-
204-
## Troubleshooting
84+
## Create and install a manifest
20585
206-
- **No response?** Make sure you write to **stdout** (native messaging uses stdio).
207-
- **Absolute path**: on macOS/Linux the `path` in the manifest must be **absolute**.
208-
- Use `verify("com.example.host")` (or your version’s signature) to check install status.
209-
210-
---
211-
212-
## About these docs
213-
214-
This file provides a comprehensive crate-level guide (what you see now) and
215-
then **inlines** the function-level items from your implementation using
216-
`#[doc(inline)] pub use …` so everything appears in one place in `cargo doc`.
217-
218-
Run:
86+
```no_run
87+
use std::path::Path;
88+
use native_messaging::install::manifest::{install, Browser, Scope};
21989
220-
```sh
221-
cargo doc --no-deps --open
90+
let name = "com.example.host";
91+
let description = "Example native messaging host";
92+
let path = Path::new("/absolute/path/to/target/release/host-binary");
93+
let allowed_origins: Vec<String> = vec![
94+
"chrome-extension://your_ext_id/".to_string(),
95+
"chrome-extension://another_id/".to_string(),
96+
];
97+
// List of Chrome/Firefox extension IDs that can talk to your host (if applicable)
98+
let allowed_extensions: Vec<String> = vec![];
99+
100+
let browsers = &[Browser::Chrome, Browser::Firefox];
101+
102+
// Adjust arguments to your needs; Scope::User for per-user install.
103+
// NOTE: This matches the signature hinted by the compiler:
104+
// install(name: &str, description: &str, path: &Path, allowed_origins: &[String],
105+
// allowed_extensions: &[String], browsers: &[Browser], scope: Scope)
106+
install(
107+
name,
108+
description,
109+
path,
110+
&allowed_origins,
111+
&allowed_extensions,
112+
browsers,
113+
Scope::User
114+
).unwrap();
222115
```
223116
"#]
224117

225-
// ========= Re-export the public API so it appears inline in these docs =========
226-
227-
// Keep using on-disk modules (e.g., src/host.rs, src/install/manifest.rs)
228118
pub mod host;
229119
pub mod install;
230120

0 commit comments

Comments
 (0)