offline_protocol_core/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
31#![deny(unsafe_code)]
32#![warn(missing_docs)]
33
34extern crate alloc;
35
36pub mod address;
37pub mod error;
38pub mod message;
39pub mod service;
40#[cfg(feature = "std")]
41pub mod sync;
42#[cfg(feature = "std")]
43pub mod time;
44pub mod types;
45pub mod username;
46pub mod wire;
47
48pub use address::{Address, AddressError};
49pub use error::{Error, Result};
50pub use message::{
51 ContentType, ForwardInfo, MediaMetadata, Message, MessageId, MessagePriority, ReplyContext,
52 WireCodec,
53};
54pub use service::{ServiceDescriptor, ServiceId};
55#[cfg(feature = "std")]
56pub use sync::{MutexExt, RwLockExt};
57#[cfg(feature = "std")]
58pub use types::LocalInstant;
59pub use types::{
60 validate_id_chars, AppId, HopCount, IdValidationError, LamportClock, MetadataMap, Timestamp,
61 UserId, WallClockTimestamp, MAX_ID_LEN, TTL,
62};
63pub use username::{contains_control_or_format, Username, UsernameError};
64pub use wire::{WIRE_V1_MAGIC, WIRE_VERSION_V1};
65
66#[cfg(all(test, feature = "std"))]
67mod manifest_guard_tests {
68 const LOCAL_DEPS: &[&str] = &[
73 "serde",
74 "serde_json",
75 "base64",
76 "unicode-normalization",
77 "thiserror",
78 "uuid",
79 "tracing",
80 "web-time",
81 ];
82
83 fn version_req(manifest: &str, name: &str) -> Option<String> {
88 let line = manifest
89 .lines()
90 .find(|l| l.starts_with(&format!("{name} = ")))?;
91 let rest = match line.find("version = \"") {
92 Some(i) => &line[i + "version = \"".len()..],
93 None => {
94 let i = line.find('"')?;
95 &line[i + 1..]
96 }
97 };
98 rest.find('"').map(|end| rest[..end].to_string())
99 }
100
101 #[test]
108 fn local_dep_versions_match_the_workspace_table() {
109 let dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
110 let root = dir.join("../../Cargo.toml");
111 let Ok(root_manifest) = std::fs::read_to_string(&root) else {
115 return;
116 };
117 let own_manifest =
118 std::fs::read_to_string(dir.join("Cargo.toml")).expect("own manifest is readable");
119
120 for dep in LOCAL_DEPS {
121 let workspace = version_req(&root_manifest, dep)
122 .unwrap_or_else(|| panic!("`{dep}` not found in the workspace dependency table"));
123 let own = version_req(&own_manifest, dep)
124 .unwrap_or_else(|| panic!("`{dep}` not found in this crate's manifest"));
125 assert_eq!(
126 workspace, own,
127 "`{dep}` version drifted: workspace says {workspace:?}, \
128 offline-protocol-core says {own:?}. Update both together."
129 );
130 }
131 }
132
133 fn workspace_version(root_manifest: &str) -> Option<String> {
135 let table = root_manifest.split("[workspace.package]").nth(1)?;
136 let table = table.split("\n[").next()?;
137 let line = table.lines().find(|l| l.starts_with("version = \""))?;
138 let rest = &line["version = \"".len()..];
139 rest.find('"').map(|end| rest[..end].to_string())
140 }
141
142 #[test]
149 fn local_internal_pins_name_the_workspace_version() {
150 let crates = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
151 let Ok(root_manifest) = std::fs::read_to_string(crates.join("../Cargo.toml")) else {
152 return;
153 };
154 let root_manifest = root_manifest.replace("\r\n", "\n");
156 let version = workspace_version(&root_manifest).expect("[workspace.package] version");
157 let pinned = format!("version = \"{version}\"");
158
159 let mut checked = 0;
160 let mut drifted = Vec::new();
161 for entry in std::fs::read_dir(&crates)
162 .expect("crates directory")
163 .flatten()
164 {
165 let manifest = entry.path().join("Cargo.toml");
166 let Ok(text) = std::fs::read_to_string(&manifest) else {
167 continue;
168 };
169 for line in text.lines() {
170 let internal = line.starts_with("offline-protocol")
171 && line.contains("path = \"../")
172 && line.contains("version = \"");
173 if !internal {
174 continue;
175 }
176 checked += 1;
177 if !line.contains(&pinned) {
178 drifted.push(format!("{}: {}", manifest.display(), line.trim()));
179 }
180 }
181 }
182 assert!(
183 checked > 0,
184 "found no hand-pinned internal dependency to check"
185 );
186 assert!(
187 drifted.is_empty(),
188 "these internal dependencies must name the workspace version {version}:\n{}",
189 drifted.join("\n")
190 );
191 }
192}