Skip to content

Commit

Permalink
Encoding contains a mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
Mallets committed Feb 20, 2024
1 parent cbda61a commit 39e4ac9
Show file tree
Hide file tree
Showing 15 changed files with 77 additions and 225 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion commons/zenoh-codec/src/core/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@ where
let zodec = Zenoh080Bounded::<EncodingPrefix>::new();
let prefix: EncodingPrefix = zodec.read(&mut *reader)?;
let suffix: String = zodec.read(&mut *reader)?;
let encoding = Encoding::new(prefix, suffix).map_err(|_| DidntRead)?;

let mut encoding: Encoding = Encoding::new(prefix);
if !suffix.is_empty() {
encoding = encoding.with_suffix(suffix).map_err(|_| DidntRead)?;
}

Ok(encoding)
}
}
1 change: 0 additions & 1 deletion commons/zenoh-protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ complete_n = []
const_format = { workspace = true }
hex = { workspace = true, features = ["alloc"] }
rand = { workspace = true, features = ["alloc", "getrandom"], optional = true }
phf = { workspace = true }
serde = { workspace = true, features = ["alloc"] }
uhlc = { workspace = true, default-features = false }
uuid = { workspace = true } # Needs a getrandom::getrandom() custom implementation on embedded (in root crate)
Expand Down
194 changes: 20 additions & 174 deletions commons/zenoh-protocol/src/core/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@
//
use crate::core::CowStr;
use alloc::{borrow::Cow, string::String};
use core::{
fmt::{self, Debug},
write,
};
use core::fmt::{self, Debug};
use zenoh_result::{bail, ZResult};

pub type EncodingPrefix = u8;
pub type EncodingPrefix = u64;

/// The encoding of a zenoh `zenoh::Value`.
///
Expand All @@ -31,101 +28,15 @@ pub struct Encoding {
suffix: CowStr<'static>,
}

pub mod prefix {
use crate::core::encoding::EncodingPrefix;
use phf::phf_ordered_map;

/// Prefixes from 0 to 63 are reserved by Zenoh
/// Users are free to use any prefix from 64 to 255
pub const EMPTY: EncodingPrefix = 0;
pub const APP_OCTET_STREAM: EncodingPrefix = 1;
pub const APP_CUSTOM: EncodingPrefix = 2;
pub const TEXT_PLAIN: EncodingPrefix = 3;
pub const APP_PROPERTIES: EncodingPrefix = 4;
pub const APP_JSON: EncodingPrefix = 5;
pub const APP_SQL: EncodingPrefix = 6;
pub const APP_INTEGER: EncodingPrefix = 7;
pub const APP_FLOAT: EncodingPrefix = 8;
pub const APP_XML: EncodingPrefix = 9;
pub const APP_XHTML_XML: EncodingPrefix = 10;
pub const APP_XWWW_FORM_URLENCODED: EncodingPrefix = 11;
pub const TEXT_JSON: EncodingPrefix = 12;
pub const TEXT_HTML: EncodingPrefix = 13;
pub const TEXT_XML: EncodingPrefix = 14;
pub const TEXT_CSS: EncodingPrefix = 15;
pub const TEXT_CSV: EncodingPrefix = 16;
pub const TEXT_JAVASCRIPT: EncodingPrefix = 17;
pub const IMAGE_JPEG: EncodingPrefix = 18;
pub const IMAGE_PNG: EncodingPrefix = 19;
pub const IMAGE_GIF: EncodingPrefix = 20;

// A perfect hashmap for fast lookup of prefixes
pub(super) const KNOWN: phf::OrderedMap<EncodingPrefix, &'static str> = phf_ordered_map! {
0u8 => "",
1u8 => "application/octet-stream",
2u8 => "application/custom", // non iana standard
3u8 => "text/plain",
4u8 => "application/properties", // non iana standard
5u8 => "application/json", // if not readable from casual users
6u8 => "application/sql",
7u8 => "application/integer", // non iana standard
8u8 => "application/float", // non iana standard
9u8 => "application/xml", // if not readable from casual users (RFC 3023, sec 3)
10u8 => "application/xhtml+xml",
11u8 => "application/x-www-form-urlencoded",
12u8 => "text/json", // non iana standard - if readable from casual users
13u8 => "text/html",
14u8 => "text/xml", // if readable from casual users (RFC 3023, section 3)
15u8 => "text/css",
16u8 => "text/csv",
17u8 => "text/javascript",
18u8 => "image/jpeg",
19u8 => "image/png",
20u8 => "image/gif",
};
}

impl Encoding {
/// The encoding is empty. It is equivalent to not being defined.
pub const EMPTY: Encoding = Encoding::exact(prefix::EMPTY);
pub const APP_OCTET_STREAM: Encoding = Encoding::exact(prefix::APP_OCTET_STREAM);
pub const APP_CUSTOM: Encoding = Encoding::exact(prefix::APP_CUSTOM);
pub const TEXT_PLAIN: Encoding = Encoding::exact(prefix::TEXT_PLAIN);
pub const APP_PROPERTIES: Encoding = Encoding::exact(prefix::APP_PROPERTIES);
pub const APP_JSON: Encoding = Encoding::exact(prefix::APP_JSON);
pub const APP_SQL: Encoding = Encoding::exact(prefix::APP_SQL);
pub const APP_INTEGER: Encoding = Encoding::exact(prefix::APP_INTEGER);
pub const APP_FLOAT: Encoding = Encoding::exact(prefix::APP_FLOAT);
pub const APP_XML: Encoding = Encoding::exact(prefix::APP_XML);
pub const APP_XHTML_XML: Encoding = Encoding::exact(prefix::APP_XHTML_XML);
pub const APP_XWWW_FORM_URLENCODED: Encoding =
Encoding::exact(prefix::APP_XWWW_FORM_URLENCODED);
pub const TEXT_JSON: Encoding = Encoding::exact(prefix::TEXT_JSON);
pub const TEXT_HTML: Encoding = Encoding::exact(prefix::TEXT_HTML);
pub const TEXT_XML: Encoding = Encoding::exact(prefix::TEXT_XML);
pub const TEXT_CSS: Encoding = Encoding::exact(prefix::TEXT_CSS);
pub const TEXT_CSV: Encoding = Encoding::exact(prefix::TEXT_CSV);
pub const TEXT_JAVASCRIPT: Encoding = Encoding::exact(prefix::TEXT_JAVASCRIPT);
pub const IMAGE_JPEG: Encoding = Encoding::exact(prefix::IMAGE_JPEG);
pub const IMAGE_PNG: Encoding = Encoding::exact(prefix::IMAGE_PNG);
pub const IMAGE_GIF: Encoding = Encoding::exact(prefix::IMAGE_GIF);

pub const fn exact(prefix: EncodingPrefix) -> Self {
/// Returns a new [`WireEncoding`] object provided the prefix ID.
pub const fn new(prefix: EncodingPrefix) -> Self {
Self {
prefix,
suffix: CowStr::borrowed(""),
}
}

/// Returns a new [`Encoding`] object.
/// This method will return an error when the suffix is longer than 255 characters.
pub fn new<IntoCowStr>(prefix: EncodingPrefix, suffix: IntoCowStr) -> ZResult<Self>
where
IntoCowStr: Into<Cow<'static, str>> + AsRef<str>,
{
Self::exact(prefix).with_suffix(suffix)
}

/// Sets the suffix of this encoding.
/// This method will return an error when the suffix is longer than 255 characters.
pub fn with_suffix<IntoCowStr>(mut self, suffix: IntoCowStr) -> ZResult<Self>
Expand All @@ -140,106 +51,41 @@ impl Encoding {
Ok(self)
}

pub fn as_ref<'a, T>(&'a self) -> T
where
&'a Self: Into<T>,
{
self.into()
}

/// Returns `true` if the string representation of this encoding starts with
/// the string representation of ther given encoding.
pub fn starts_with<T>(&self, with: T) -> bool
where
T: Into<Encoding>,
{
let with: Encoding = with.into();
self.prefix() == with.prefix() && self.suffix().starts_with(with.suffix())
/// Returns a new [`WireEncoding`] object with default empty prefix ID.
pub const fn empty() -> Self {
Self::new(0)
}

// Returns the numerical prefix ID
pub const fn prefix(&self) -> EncodingPrefix {
self.prefix
}

// Returns the suffix string
pub fn suffix(&self) -> &str {
self.suffix.as_str()
}
}

impl From<&EncodingPrefix> for Encoding {
fn from(e: &EncodingPrefix) -> Encoding {
Encoding::exact(*e)
}
}

impl From<EncodingPrefix> for Encoding {
fn from(e: EncodingPrefix) -> Encoding {
Encoding::exact(e)
/// Returns `true` if the string representation of this encoding starts with
/// the string representation of ther given encoding.
pub fn starts_with<T>(&self, with: T) -> bool
where
T: Into<Encoding>,
{
let with: Encoding = with.into();
self.prefix() == with.prefix() && self.suffix().starts_with(with.suffix())
}
}

impl fmt::Display for Encoding {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match prefix::KNOWN.get(&self.prefix) {
Some(s) => write!(f, "{}", s)?,
None => write!(f, "Unknown({})", self.prefix)?,
}
write!(f, "{}", self.suffix.as_str())
}
}

impl TryFrom<&'static str> for Encoding {
type Error = zenoh_result::Error;

fn try_from(s: &'static str) -> Result<Self, Self::Error> {
for (k, v) in prefix::KNOWN.entries().skip(1) {
if let Some(suffix) = s.strip_prefix(v) {
let e = Encoding::exact(*k);
if suffix.is_empty() {
return Ok(e);
} else {
return e.with_suffix(suffix);
}
}
}

let e = Encoding::EMPTY;
if s.is_empty() {
Ok(e)
} else {
e.with_suffix(s)
}
}
}

impl TryFrom<String> for Encoding {
type Error = zenoh_result::Error;

fn try_from(mut s: String) -> Result<Self, Self::Error> {
for (k, v) in prefix::KNOWN.entries().skip(1) {
if s.starts_with(v) {
s.replace_range(..v.len(), "");
let e = Encoding::exact(*k);
if s.is_empty() {
return Ok(e);
} else {
return e.with_suffix(s);
}
}
}

let e = Encoding::EMPTY;
if s.is_empty() {
Ok(e)
} else {
e.with_suffix(s)
}
f.write_fmt(format_args!("{}:{}", self.prefix, self.suffix.as_str()))
}
}

impl Default for Encoding {
fn default() -> Self {
Encoding::EMPTY
Self::empty()
}
}

Expand All @@ -263,6 +109,6 @@ impl Encoding {
} else {
String::new()
};
Encoding::new(prefix, suffix).unwrap()
Encoding::new(prefix).with_suffix(suffix).unwrap()
}
}
2 changes: 1 addition & 1 deletion commons/zenoh-protocol/src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub use wire_expr::*;
mod cowstr;
pub use cowstr::CowStr;
mod encoding;
pub use encoding::{prefix, Encoding, EncodingPrefix};
pub use encoding::{Encoding, EncodingPrefix};

pub mod locator;
pub use locator::*;
Expand Down
1 change: 1 addition & 0 deletions zenoh/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ log = { workspace = true }
ordered-float = { workspace = true }
paste = { workspace = true }
petgraph = { workspace = true }
phf = { workspace = true }
rand = { workspace = true, features = ["default"] }
regex = { workspace = true }
serde = { workspace = true, features = ["default"] }
Expand Down
6 changes: 2 additions & 4 deletions zenoh/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// Contributors:
// ZettaScale Zenoh Team, <[email protected]>
//
use crate::prelude::Encoding;
use crate::{
keyexpr,
prelude::sync::{KeyExpr, Locality, SampleKind},
Expand All @@ -25,10 +26,7 @@ use std::{
sync::Arc,
};
use zenoh_core::SyncResolve;
use zenoh_protocol::{
core::{Encoding, WireExpr},
network::NetworkMessage,
};
use zenoh_protocol::{core::WireExpr, network::NetworkMessage};
use zenoh_transport::{
TransportEventHandler, TransportMulticastEventHandler, TransportPeer, TransportPeerEventHandler,
};
Expand Down
1 change: 1 addition & 0 deletions zenoh/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ pub const FEATURES: &str = concat_enabled_features!(
mod admin;
#[macro_use]
mod session;
pub mod encoding;
pub use session::*;

pub mod key_expr;
Expand Down
9 changes: 6 additions & 3 deletions zenoh/src/net/runtime/adminspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ use super::Runtime;
use crate::key_expr::KeyExpr;
use crate::net::primitives::Primitives;
use crate::plugins::sealed::{self as plugins};
use crate::prelude::sync::{Sample, SyncResolve};
use crate::prelude::{
sync::{Sample, SyncResolve},
Encoding,
};
use crate::queryable::Query;
use crate::queryable::QueryInner;
use crate::value::Value;
Expand All @@ -33,7 +36,7 @@ use zenoh_plugin_trait::{PluginControl, PluginStatus};
use zenoh_protocol::{
core::{
key_expr::{keyexpr, OwnedKeyExpr},
Encoding, ExprId, WireExpr, ZenohId, EMPTY_EXPR_ID,
ExprId, WireExpr, ZenohId, EMPTY_EXPR_ID,
},
network::{
declare::{queryable::ext::QueryableInfo, subscriber::ext::SubscriberInfo},
Expand Down Expand Up @@ -422,7 +425,7 @@ impl Primitives for AdminSpace {
parameters,
value: query
.ext_body
.map(|b| Value::from(b.payload).encoding(b.encoding)),
.map(|b| Value::from(b.payload).encoding(b.encoding.into())),
qid: msg.id,
zid,
primitives,
Expand Down
4 changes: 2 additions & 2 deletions zenoh/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ pub(crate) mod common {

pub use crate::query::{QueryConsolidation, QueryTarget};

pub use crate::value::Value;
/// The encoding of a zenoh `Value`.
pub use zenoh_protocol::core::{prefix as EncodingPrefix, Encoding};
pub use crate::encoding::Encoding;
pub use crate::value::Value;

pub use crate::query::ConsolidationMode;
#[zenoh_macros::unstable]
Expand Down
4 changes: 2 additions & 2 deletions zenoh/src/publication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ fn resolve_put(
}
PushBody::Put(Put {
timestamp,
encoding: value.encoding.clone(),
encoding: value.encoding.clone().into(),
ext_sinfo: None,
#[cfg(feature = "shared-memory")]
ext_shm: None,
Expand Down Expand Up @@ -855,7 +855,7 @@ fn resolve_put(
if publisher.destination != Locality::Remote {
let data_info = DataInfo {
kind,
encoding: Some(value.encoding),
encoding: Some(value.encoding.clone()),
timestamp,
..Default::default()
};
Expand Down
Loading

0 comments on commit 39e4ac9

Please sign in to comment.