Skip to content

Commit

Permalink
doc(commons): improve documentation (#183)
Browse files Browse the repository at this point in the history
Signed-off-by: Julien Loudet <[email protected]>
  • Loading branch information
J-Loudet authored Feb 14, 2024
1 parent fd95d28 commit 03a4776
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 17 deletions.
10 changes: 5 additions & 5 deletions zenoh-flow-commons/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use crate::merge::IMergeOverwrite;
use serde::{Deserialize, Serialize};
use std::{ops::Deref, sync::Arc};

/// A `Configuration` is a recursive key-value structure that allows modifying the behavior of a
/// node without altering its implementation.
/// A `Configuration` is a recursive key-value structure that allows modifying the behavior of a node without altering
/// its implementation.
///
/// It is effectively a re-export of [serde_json::Value].
///
Expand Down Expand Up @@ -49,8 +49,8 @@ use std::{ops::Deref, sync::Arc};
//
// NOTE: we take the `serde_json` representation because:
// - JSON is the most supported representation when going online,
// - a `serde_json::Value` can be converted to a `serde_yaml::Value` whereas the opposite is not
// true (YAML introduces "tags" which are not supported by JSON).
// - a `serde_json::Value` can be converted to a `serde_yaml::Value` whereas the opposite is not true (YAML introduces
// "tags" which are not supported by JSON).
#[derive(Default, Deserialize, Debug, Serialize, Clone, PartialEq, Eq)]
pub struct Configuration(Arc<serde_json::Value>);

Expand Down Expand Up @@ -81,7 +81,7 @@ impl IMergeOverwrite for Configuration {
Configuration(Arc::new(other.into()))
}
(_, _) => unreachable!(
"We are checking, when deserializing, that a Configuration is a JSON object."
"We are checking, when deserialising, that a Configuration is a JSON object."
),
}
}
Expand Down
19 changes: 16 additions & 3 deletions zenoh-flow-commons/src/deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ use serde::Deserializer;
use std::{str::FromStr, sync::Arc};
use zenoh_keyexpr::OwnedKeyExpr;

/// Deserialise, from a [String], an `Arc<str>` that is guaranteed to be a valid Zenoh-Flow [NodeId](crate::NodeId) or
/// [PortId](crate::PortId).
///
/// To be valid, the following properties must be upheld:
/// - the String does not contain any of the symbols: * # $ ? >
/// - the String is a valid Zenoh key expression in its canonical form (see
/// [autocanonize](zenoh_keyexpr::OwnedKeyExpr::autocanonize)).
pub fn deserialize_id<'de, D>(deserializer: D) -> std::result::Result<Arc<str>, D::Error>
where
D: Deserializer<'de>,
Expand All @@ -33,10 +40,10 @@ Identifiers (for nodes or ports) in Zenoh-Flow must *not* contain any of the cha
The identifier < {} > does not satisfy that condition.
These characters, except for '>', have a special meaning in Zenoh and they could negatively impact Zenoh-Flow's
behavior.
behaviour.
The character '>' is used as a separator when flattening a composite operator. Allowing it could also negatively impact
Zenoh-Flow's behavior.
Zenoh-Flow's behaviour.
"#,
id
)));
Expand All @@ -58,6 +65,9 @@ Caused by:
Ok(id.into())
}

/// Deserialise a bytes size leveraging the [bytesize] crate.
///
/// This allows parsing, for instance, "1Ko" into "1024" bytes. For more example, see the [bytesize] crate.
pub fn deserialize_size<'de, D>(deserializer: D) -> std::result::Result<usize, D::Error>
where
D: Deserializer<'de>,
Expand All @@ -78,6 +88,9 @@ where
)))
}

/// Deserialise a duration in *microseconds* leveraging the [humantime] crate.
///
/// This allows parsing, for instance, "1ms" as 1000 microseconds.
pub fn deserialize_time<'de, D>(deserializer: D) -> std::result::Result<u64, D::Error>
where
D: Deserializer<'de>,
Expand All @@ -86,7 +99,7 @@ where
let time_u128 = buf
.parse::<humantime::Duration>()
.map_err(serde::de::Error::custom)?
.as_nanos();
.as_micros();

u64::try_from(time_u128).map_err(|e| {
serde::de::Error::custom(format!(
Expand Down
41 changes: 40 additions & 1 deletion zenoh-flow-commons/src/identifiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,15 @@ use serde::{Deserialize, Serialize};
use uuid::Uuid;
use zenoh_protocol::core::ZenohId;

/// A `NodeId` identifies a Node in a data flow.
/// A `NodeId` uniquely identifies a Node within a data flow.
///
/// A `NodeId` additionally satisfies the following constraints:
/// - it does *not* contain any of the symbols: * # $ ? >
/// - it is a valid [canonical Zenoh key expression](zenoh_keyexpr::OwnedKeyExpr::autocanonize).
///
/// # Performance
///
/// A `NodeId` is encapsulated in an [Arc] rendering clone operations almost cost-free.
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone, Hash)]
pub struct NodeId(#[serde(deserialize_with = "deserialize_id")] Arc<str>);

Expand Down Expand Up @@ -53,6 +61,20 @@ impl From<&str> for NodeId {
}

/// A `PortId` identifies an `Input` or an `Output` of a Node.
///
/// A `PortId` additionally satisfies the following constraints:
/// - it does *not* contain any of the symbols: * # $ ? >
/// - it is a valid [canonical Zenoh key expression](zenoh_keyexpr::OwnedKeyExpr::autocanonize).
///
/// # Uniqueness
///
/// A `PortId` does not need to be unique within a data flow. It should only be unique among the ports of the same node
/// and of the same type (i.e. `Input` or `Output`).
/// For instance, a node can have an `Input` and an `Output` with the same `PortId`.
///
/// # Performance
///
/// A `PortId` is encapsulated in an [Arc] rendering clone operations almost cost-free.
#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct PortId(#[serde(deserialize_with = "deserialize_id")] Arc<str>);

Expand Down Expand Up @@ -82,11 +104,21 @@ impl From<&str> for PortId {
}
}

/// A `RuntimeId` uniquely identifies a Zenoh-Flow runtime within a Zenoh network.
///
/// The `RuntimeId` structure simply wraps a [ZenohId]. Similar to a Uuid, this identifier is (with a high probability)
/// guaranteed to be unique within your infrastructure.
///
/// A Zenoh-Flow runtime will, by default, reuse the [ZenohId] of the Zenoh
/// [session](https://docs.rs/zenoh/0.10.1-rc/zenoh/struct.Session.html) it will create to connect to the Zenoh network.
#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize, Default)]
#[repr(transparent)]
pub struct RuntimeId(ZenohId);

impl RuntimeId {
/// Generate a new random identifier, guaranteed (with a high probability) to be unique.
///
/// This internally calls [ZenohId::rand].
pub fn rand() -> Self {
Self(ZenohId::rand())
}
Expand Down Expand Up @@ -122,6 +154,13 @@ impl FromStr for RuntimeId {
}
}

/// An `InstanceId` uniquely identifies a data flow instance.
///
/// A data flow instance is created every time Zenoh-Flow is tasked to run a data flow. Each instance of the same data
/// flow will have a different `InstanceId`.
///
/// Internally, it uses a [Uuid v4](uuid::Uuid::new_v4) that it wraps inside an [Arc]. This allows for almost cost-free
/// `clone` operations.
#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub struct InstanceId(Arc<Uuid>);

Expand Down
5 changes: 5 additions & 0 deletions zenoh-flow-commons/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
// ZettaScale Zenoh Team, <[email protected]>
//

//! This crate centralises structures that are shared across Zenoh-Flow.
//!
//! ⚠️ This crate is intended for internal usage within Zenoh-Flow. All structures that are exposed in public
//! facing API are re-exposed in the relevant crates.

mod configuration;
pub use configuration::Configuration;

Expand Down
6 changes: 6 additions & 0 deletions zenoh-flow-commons/src/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
// ZettaScale Zenoh Team, <[email protected]>
//

/// Types which can be combined with another instance of the same type and for which, in case there are common elements,
/// the elements of `self` would be kept over those held by `other`.
///
/// For instance, a map-like type with keys shared by both would see the associated values in `self` preserved.
///
/// This trait is leveraged in Zenoh-Flow for the [Configuration](crate::Configuration) and the [Vars](crate::Vars).
pub trait IMergeOverwrite {
fn merge_overwrite(self, other: Self) -> Self;
}
12 changes: 11 additions & 1 deletion zenoh-flow-commons/src/shared_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@ use std::fmt::Display;
use crate::deserialize::{deserialize_size, deserialize_time};
use serde::{Deserialize, Serialize};

/// Structure to configure how Zenoh-Flow uses the [shared memory](https://docs.rs/zenoh-shm/0.10.1-rc/zenoh_shm/)
/// feature provided by Zenoh.
///
/// This configuration is applied on a link basis
///
/// A Zenoh-Flow runtime can be configured to always attempt to send data through shared-memory first. When this feature
/// is enabled this structure allows tweaking two aspects: (i) the size of the shared memory buffer Zenoh should
/// allocate and (ii) the back-off period.
///
///
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SharedMemoryConfiguration {
/// Size, converted in bytes, of the shared memory buffer.
/// Size, converted in bytes, of the entire shared memory buffer.
#[serde(deserialize_with = "deserialize_size")]
pub size: usize,
/// Duration, converted in nanoseconds, to wait before retrying the last operation.
Expand Down
9 changes: 9 additions & 0 deletions zenoh-flow-commons/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ Currently supported file extensions are:
}
}

/// Attempts to parse an instance of `N` from the content of the file located at `path`, overwriting (or complementing)
/// the [Vars] declared in said file with the provided `vars`.
///
/// This function is notably used to parse a data flow descriptor. Two file types are supported, identified by their
/// extension:
/// - JSON (`.json` file extension)
/// - YAML (`.yaml` or `.yml` extensions)
///
/// This function does not impose writing *all* descriptor file, within the same data flow, in the same format.
pub fn try_load_from_file<N>(path: impl AsRef<Path>, vars: Vars) -> Result<(N, Vars)>
where
N: for<'a> Deserialize<'a>,
Expand Down
31 changes: 24 additions & 7 deletions zenoh-flow-commons/src/vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,33 @@ use std::error::Error;
use std::ops::Deref;
use std::rc::Rc;

/// `Vars` is an internal structure that we use to expand the "mustache variables" in a descriptor
/// file.
/// `Vars` is an internal structure that we use to expand the "moustache variables" in a descriptor file.
///
/// Mustache variables take the form: "{{ var }}..." where the number of spaces after the '{{' and
/// before the '}}' do not matter.
/// Moustache variables take the form: `{{ var }}` where the number of spaces after the `{{` and before the `}}` do
/// not matter.
///
/// We first parse the descriptor file to only extract the `vars` section and build a `HashMap` out of it.
///
/// We then load the descriptor file as a template and "render" it, substituting every "mustache
/// variable" with its corresponding value in the HashMap.
/// We then load the descriptor file as a template and "render" it, substituting every "moustache variable" with its
/// corresponding value in the HashMap.
///
/// # Example (YAML)
///
/// Declaration within a descriptor:
///
/// ```yaml
/// vars:
/// BUILD: debug
/// DLL_EXT: so
/// ```
///
/// Its usage within the descriptor:
///
/// ```yaml
/// sources:
/// - id: my-source
/// library: "file:///zenoh-flow/target/{{ BUILD }}/libmy_source.{{ DLL_EXT }}"
/// ```
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
pub struct Vars {
#[serde(default)]
Expand Down Expand Up @@ -80,7 +97,7 @@ impl<T: AsRef<str>, U: AsRef<str>> From<Vec<(T, U)>> for Vars {
}
}

/// Parse a Vars from a string of the format "KEY=VALUE".
/// Parse a single [Var](Vars) from a string of the format "KEY=VALUE".
pub fn parse_vars<T, U>(
s: &str,
) -> std::result::Result<(T, U), Box<dyn Error + Send + Sync + 'static>>
Expand Down

0 comments on commit 03a4776

Please sign in to comment.