pub struct ProtocolConfig {
pub app_id: String,
pub profile: String,
pub transport: TransportConfig,
pub dors: DorsConfig,
pub relay: RelayConfig,
pub mesh_relay: MeshRelayConfig,
pub reliability: ReliabilityConfig,
pub encryption: EncryptionConfig,
pub initial_ttl: u8,
pub group: GroupConfig,
pub security: SecurityConfig,
pub data: DataConfig,
}Expand description
Main configuration for the Offline Protocol.
Fields§
§app_id: StringApplication identifier (required).
profile: StringLocal profile selector (required).
Selects which stored identity this instance runs as — one namespace per
(app_id, profile) pair — so an app hosting several accounts gives each
its own value, and an app hosting one can pass a constant like
"default".
It is not the device’s identity. The wire identity is the
self-certifying address derived from the identity key held in this
profile’s storage: it is minted on first start, reported by
crate::OfflineProtocol::local_address, and it is what gets stamped
as Message.sender, what peers see as NeighborDiscovered.peer_id,
and what others use as recipient. An app cannot choose it, because
choosing it would mean claiming a key one does not hold.
Under any configuration that reaches the wire the profile stays local.
The one exception is the explicit
EncryptionConfig::require_encryption = false opt-out, which lets a
plaintext send go out with MLS never initialized — no address has been
derived at that point, so the frame carries the profile as its sender
and the send emits
crate::events::SecurityWarningCode::PlaintextSend. The default
(require_encryption = true) fails such a send closed instead. Treat
the profile as private if that opt-out is in use.
transport: TransportConfigTransport configuration.
dors: DorsConfigDORS (Dynamic Offline Relay Switch) configuration.
relay: RelayConfigRelay management configuration: whether this device carries traffic for other people at all, and the battery floors under which it stops.
mesh_relay: MeshRelayConfigHow this device carries traffic for other people: how far frames travel, how many neighbors each is handed to, and the ceilings that keep forwarding from crowding the radio out.
Whether to forward is Self::relay’s decision; this is the shape of
it once the answer is yes.
reliability: ReliabilityConfigReliability layer configuration.
encryption: EncryptionConfigEncryption configuration for automatic MLS handling.
initial_ttl: u8Initial TTL (Time-To-Live) for messages.
group: GroupConfigMesh group messaging configuration.
security: SecurityConfigSecurity configuration for transport and control-message hardening.
data: DataConfigReplicated-document data layer configuration.
Implementations§
Source§impl ProtocolConfig
impl ProtocolConfig
Sourcepub fn new(app_id: impl Into<String>, profile: impl Into<String>) -> Self
pub fn new(app_id: impl Into<String>, profile: impl Into<String>) -> Self
Creates a new protocol configuration.
§Arguments
app_id- Application identifierprofile- Local profile selector (storage namespace, never on the wire)
Sourcepub fn builder(
app_id: impl Into<String>,
profile: impl Into<String>,
) -> ProtocolConfigBuilder
pub fn builder( app_id: impl Into<String>, profile: impl Into<String>, ) -> ProtocolConfigBuilder
Creates a builder for more granular configuration.
Examples found in repository?
74fn main() -> Result<(), Box<dyn std::error::Error>> {
75 // Both stores outlive the engine below, which is what makes the reopen at
76 // the end a reopen rather than a fresh start. The secure store matters as
77 // much as the record store: documents are sealed with a key that lives in
78 // it, so dropping only that half looks exactly like data loss.
79 let secure = Arc::new(InMemoryStorage::default());
80 let records = Arc::new(MemoryStateStorage::default());
81
82 // `data.enabled` defaults to true, so nothing here switches the layer on.
83 let config = ProtocolConfig::builder("com.example.notes", "default").build()?;
84 let mut protocol = OfflineProtocol::new(config)?;
85
86 // Documents are sealed at rest and the record key is minted here, so this
87 // call is the prerequisite for every method below.
88 protocol.initialize_mls(secure.clone(), records.clone())?;
89
90 // A space is an MLS scope: a peer's address for a 1:1 space, or the group
91 // id for a group. Nothing replicates in this example, so the name only
92 // has to be a valid one.
93 let space = "demo-space";
94
95 protocol.data_create_doc(space, "trip")?;
96
97 // A map: last writer wins per key, and different keys never conflict.
98 protocol.data_map_set(
99 space,
100 "trip",
101 "meta",
102 "title",
103 DataValue::Text {
104 value: "Coast road".to_string(),
105 },
106 )?;
107
108 // A list: concurrent insertions both survive, in a deterministic order.
109 for item in ["water", "map", "torch"] {
110 protocol.data_list_push(
111 space,
112 "trip",
113 "packing",
114 DataValue::Text {
115 value: item.to_string(),
116 },
117 )?;
118 }
119
120 // Text: character-level merge, so two people typing in one paragraph keep
121 // both sets of words. Positions are character offsets, not byte offsets.
122 protocol.data_text_insert(space, "trip", "notes", 0, "Meet at the bridge")?;
123
124 // A counter: increments add up rather than overwriting each other.
125 protocol.data_counter_increment(space, "trip", "opened", 1.0)?;
126
127 // Edits batch before they reach storage. This is the call that makes them
128 // durable, and `data_changed` fires after the same point, never before.
129 protocol.data_flush(space, "trip")?;
130
131 println!("spaces: {:?}", protocol.data_list_spaces()?);
132 println!("documents: {:?}", protocol.data_list_docs(space)?);
133 println!(
134 "compacted: {} bytes",
135 protocol.data_doc_size(space, "trip")?
136 );
137 println!(
138 "history: {} bytes",
139 protocol.data_export_raw(space, "trip")?.len()
140 );
141 println!("json: {}", protocol.data_doc_json(space, "trip")?);
142
143 // Both halves of the escape hatch are above: `data_doc_json` is the plain
144 // JSON of the current state, `data_export_raw` the engine-native history.
145 // An application can always take its data and leave.
146
147 // Reopen: a new engine over the same two stores. The records were sealed
148 // by the first one and are read back by the second, which is the property
149 // an application depends on across a restart.
150 drop(protocol);
151 let config = ProtocolConfig::builder("com.example.notes", "default").build()?;
152 let mut reopened = OfflineProtocol::new(config)?;
153 reopened.initialize_mls(secure, records)?;
154
155 println!("after reopen");
156 println!(
157 " title: {:?}",
158 reopened.data_map_get(space, "trip", "meta", "title")?
159 );
160 println!(
161 " packing: {}",
162 reopened.data_list_len(space, "trip", "packing")?
163 );
164 println!(
165 " notes: {:?}",
166 reopened.data_text_value(space, "trip", "notes")?
167 );
168 println!(
169 " opened: {}",
170 reopened.data_counter_value(space, "trip", "opened")?
171 );
172
173 Ok(())
174}Trait Implementations§
Source§impl Clone for ProtocolConfig
impl Clone for ProtocolConfig
Auto Trait Implementations§
impl !RefUnwindSafe for ProtocolConfig
impl !UnwindSafe for ProtocolConfig
impl Freeze for ProtocolConfig
impl Send for ProtocolConfig
impl Sync for ProtocolConfig
impl Unpin for ProtocolConfig
impl UnsafeUnpin for ProtocolConfig
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Declassify for T
impl<T> Declassify for T
type Declassified = T
fn declassify(self) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);