Skip to content

Commit

Permalink
lost code restored
Browse files Browse the repository at this point in the history
  • Loading branch information
milyin committed Jun 3, 2024
1 parent fcaf185 commit eea9d74
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 3 deletions.
279 changes: 279 additions & 0 deletions commons/zenoh-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,285 @@ fn is_doc_attribute(attr: &Attribute) -> bool {
.is_some_and(|ident| &ident.to_string() == "doc")
}

fn keformat_support(source: &str) -> proc_macro2::TokenStream {
let format = match KeFormat::new(&source) {
Ok(format) => format,
Err(e) => panic!("{}", e),
};
let specs = unsafe { macro_support::specs(&format) };
let len = specs.len();
let setters = specs.iter().map(|spec| {
let id = &source[spec.spec_start..(spec.spec_start + spec.id_end as usize)];
let set_id = quote::format_ident!("{}", id);
quote! {
pub fn #set_id <S: ::core::fmt::Display>(&mut self, value: S) -> Result<&mut Self, ::zenoh::key_expr::format::FormatSetError> {
match self.0.set(#id, value) {
Ok(_) => Ok(self),
Err(e) => Err(e)
}
}
}
});
let getters = specs.iter().map(|spec| {
let source = &source[spec.spec_start..spec.spec_end];
let id = &source[..(spec.id_end as usize)];
let get_id = quote::format_ident!("{}", id);
let pattern = unsafe {
keyexpr::from_str_unchecked(if spec.pattern_end != u16::MAX {
&source[(spec.id_end as usize + 1)..(spec.spec_start + spec.pattern_end as usize)]
} else {
&source[(spec.id_end as usize + 1)..]
})
};
let doc = format!("Get the parsed value for `{id}`.\n\nThis value is guaranteed to be a valid key expression intersecting with `{pattern}`");
if pattern.as_bytes() == b"**" {
quote! {
#[doc = #doc]
/// Since the pattern is `**`, this may return `None` if the pattern didn't consume any chunks.
pub fn #get_id (&self) -> Option<& ::zenoh::key_expr::keyexpr> {
unsafe {
let s =self._0.get(#id).unwrap_unchecked();
(!s.is_empty()).then(|| ::zenoh::key_expr::keyexpr::from_str_unchecked(s))
}
}
}
} else {
quote! {
#[doc = #doc]
pub fn #get_id (&self) -> &::zenoh::key_expr::keyexpr {
unsafe {::zenoh::key_expr::keyexpr::from_str_unchecked(self._0.get(#id).unwrap_unchecked())}
}
}
}
});
let segments = specs.iter().map(|spec| {
let SegmentBuilder {
segment_start,
prefix_end,
spec_start,
id_end,
pattern_end,
spec_end,
segment_end,
} = spec;
quote! {
::zenoh::key_expr::format::macro_support::SegmentBuilder {
segment_start: #segment_start,
prefix_end: #prefix_end,
spec_start: #spec_start,
id_end: #id_end,
pattern_end: #pattern_end,
spec_end: #spec_end,
segment_end: #segment_end,
},
}
});

let format_doc = format!("The `{source}` format, as a zero-sized-type.");
let formatter_doc = format!("And instance of a formatter for `{source}`.");

quote! {
use ::zenoh::core::Result as ZResult;
const FORMAT_INNER: ::zenoh::key_expr::format::KeFormat<'static, [::zenoh::key_expr::format::Segment<'static>; #len]> = unsafe {
::zenoh::key_expr::format::macro_support::const_new(#source, [#(#segments)*])
};
#[doc = #format_doc]
#[derive(Copy, Clone, Hash)]
pub struct Format;

#[doc = #formatter_doc]
#[derive(Clone)]
pub struct Formatter(::zenoh::key_expr::format::KeFormatter<'static, [::zenoh::key_expr::format::Segment<'static>; #len]>);
impl ::core::fmt::Debug for Format {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Debug::fmt(&FORMAT_INNER, f)
}
}
impl ::core::fmt::Debug for Formatter {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Debug::fmt(&self.0, f)
}
}
impl ::core::fmt::Display for Format {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Display::fmt(&FORMAT_INNER, f)
}
}
impl ::core::ops::Deref for Format {
type Target = ::zenoh::key_expr::format::KeFormat<'static, [::zenoh::key_expr::format::Segment<'static>; #len]>;
fn deref(&self) -> &Self::Target {&FORMAT_INNER}
}
impl ::core::ops::Deref for Formatter {
type Target = ::zenoh::key_expr::format::KeFormatter<'static, [::zenoh::key_expr::format::Segment<'static>; #len]>;
fn deref(&self) -> &Self::Target {&self.0}
}
impl ::core::ops::DerefMut for Formatter {
fn deref_mut(&mut self) -> &mut Self::Target {&mut self.0}
}
impl Formatter {
#(#setters)*
}
pub struct Parsed<'s>{_0: ::zenoh::key_expr::format::Parsed<'s, [::zenoh::key_expr::format::Segment<'s>; #len]>}
impl<'s> ::core::ops::Deref for Parsed<'s> {
type Target = ::zenoh::key_expr::format::Parsed<'s, [::zenoh::key_expr::format::Segment<'s>; #len]>;
fn deref(&self) -> &Self::Target {&self._0}
}
impl Parsed<'_> {
#(#getters)*
}
impl Format {
pub fn formatter() -> Formatter {
Formatter(Format.formatter())
}
pub fn parse<'s>(target: &'s ::zenoh::key_expr::keyexpr) -> ZResult<Parsed<'s>> {
Ok(Parsed{_0: Format.parse(target)?})
}
pub fn into_inner(self) -> ::zenoh::key_expr::format::KeFormat<'static, [::zenoh::key_expr::format::Segment<'static>; #len]> {
FORMAT_INNER
}
}
pub fn formatter() -> Formatter {
Format::formatter()
}
pub fn parse<'s>(target: &'s ::zenoh::key_expr::keyexpr) -> ZResult<Parsed<'s>> {
Format::parse(target)
}
}
}

struct FormatDeclaration {
vis: syn::Visibility,
name: syn::Ident,
lit: syn::LitStr,
}
impl syn::parse::Parse for FormatDeclaration {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let vis = input.parse()?;
let name = input.parse()?;
let _: syn::Token!(:) = input.parse()?;
let lit = input.parse()?;
Ok(FormatDeclaration { vis, name, lit })
}
}
struct FormatDeclarations(syn::punctuated::Punctuated<FormatDeclaration, syn::Token!(,)>);
impl syn::parse::Parse for FormatDeclarations {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
Ok(Self(input.parse_terminated(
FormatDeclaration::parse,
syn::Token![,],
)?))
}
}

/// Create format modules from a format specification.
///
/// `kedefine!($($vis $ident: $lit),*)` will validate each `$lit` to be a valid KeFormat, and declare a module called `$ident` with `$vis` visibility at its call-site for each format.
/// The modules contain the following elements:
/// - `Format`, a zero-sized type that represents your format.
/// - `formatter()`, a function that constructs a `Formatter` specialized for your format:
/// - for every spec in your format, `Formatter` will have a method named after the spec's `id` that lets you set a value for that field of your format. These methods will return `Result<&mut Formatter, FormatError>`.
/// - `parse(target: &keyexpr) -> ZResult<Parsed<'_>>` will parse the provided key expression according to your format. Just like `KeFormat::parse`, parsing is lazy: each field will match the smallest subsection of your `target` that is included in its pattern.
/// - like `Formatter`, `Parsed` will have a method named after each spec's `id` that returns `&keyexpr`; except for specs whose pattern was `**`, these will return an `Option<&keyexpr>`, where `None` signifies that the pattern was matched by an empty list of chunks.
#[proc_macro]
pub fn kedefine(tokens: TokenStream) -> TokenStream {
let declarations: FormatDeclarations = syn::parse(tokens).unwrap();
let content = declarations.0.into_iter().map(|FormatDeclaration { vis, name, lit }|
{
let source = lit.value();
let docstring = format!(
r"The module associated with the `{source}` format, it contains:
- `Format`, a zero-sized type that represents your format.
- `formatter()`, a function that constructs a `Formatter` specialized for your format:
- for every spec in your format, `Formatter` will have a method named after the spec's `id` that lets you set a value for that field of your format. These methods will return `Result<&mut Formatter, FormatError>`.
- `parse(target: &keyexpr) -> ZResult<Parsed<'_>>` will parse the provided key expression according to your format. Just like `KeFormat::parse`, parsing is lazy: each field will match the smallest subsection of your `target` that is included in its pattern.
- like `Formatter`, `Parsed` will have a method named after each spec's `id` that returns `&keyexpr`; except for specs whose pattern was `**`, these will return an `Option<&keyexpr>`, where `None` signifies that the pattern was matched by an empty list of chunks."
);
let support = keformat_support(&source);
quote! {
#[doc = #docstring]
#vis mod #name{
#support
}
}});
quote!(#(#content)*).into()
}

struct FormatUsage {
id: syn::Expr,
assigns: Vec<(syn::Expr, syn::Expr)>,
}
impl syn::parse::Parse for FormatUsage {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let id = input.parse()?;
let mut assigns = Vec::new();
if !input.is_empty() {
input.parse::<syn::Token!(,)>()?;
}
assigns.extend(
input
.parse_terminated(syn::Expr::parse, syn::Token![,])?
.into_iter()
.map(|a| match a {
syn::Expr::Assign(a) => (*a.left, *a.right),
a => (a.clone(), a),
}),
);
Ok(FormatUsage { id, assigns })
}
}

/// Write a set of values into a `Formatter`, stopping as soon as a value doesn't fit the specification for its field.
/// Contrary to `keformat` doesn't build the Formatter into a Key Expression.
///
/// `kewrite!($formatter, $($ident [= $expr]),*)` will attempt to write `$expr` into their respective `$ident` fields for `$formatter`.
/// `$formatter` must be an expression that dereferences to `&mut Formatter`.
/// `$expr` must resolve to a value that implements `core::fmt::Display`.
/// `$expr` defaults to `$ident` if omitted.
///
/// This macro always results in an expression that resolves to `Result<&mut Formatter, FormatSetError>`.
#[proc_macro]
pub fn kewrite(tokens: TokenStream) -> TokenStream {
let FormatUsage { id, assigns } = syn::parse(tokens).unwrap();
let mut sets = None;
for (l, r) in assigns.iter().rev() {
if let Some(set) = sets {
sets = Some(quote!(.#l(#r).and_then(|x| x #set)));
} else {
sets = Some(quote!(.#l(#r)));
}
}
quote!(#id #sets).into()
}

/// Write a set of values into a `Formatter` and then builds it into an `OwnedKeyExpr`, stopping as soon as a value doesn't fit the specification for its field.
///
/// `keformat!($formatter, $($ident [= $expr]),*)` will attempt to write `$expr` into their respective `$ident` fields for `$formatter`.
/// `$formatter` must be an expression that dereferences to `&mut Formatter`.
/// `$expr` must resolve to a value that implements `core::fmt::Display`.
/// `$expr` defaults to `$ident` if omitted.
///
/// This macro always results in an expression that resolves to `ZResult<OwnedKeyExpr>`, and leaves `$formatter` in its written state.
#[proc_macro]
pub fn keformat(tokens: TokenStream) -> TokenStream {
let formatted: proc_macro2::TokenStream = kewrite(tokens).into();
quote!(match #formatted {
Ok(ok) => ok.build(),
Err(e) => Err(e.into()),
})
.into()
}

/// Equivalent to [`keyexpr::new`](zenoh_keyexpr::keyexpr::new), but the check is run at compile-time and will throw a compile error in case of failure.
#[proc_macro]
pub fn ke(tokens: TokenStream) -> TokenStream {
let value: LitStr = syn::parse(tokens).unwrap();
let ke = value.value();
match zenoh_keyexpr::keyexpr::new(&ke) {
Ok(_) => quote!(unsafe {::zenoh::key_expr::keyexpr::from_str_unchecked(#ke)}).into(),
Err(e) => panic!("{}", e),
}
}

mod zenoh_runtime_derive;
use syn::DeriveInput;
use zenoh_runtime_derive::{derive_generic_runtime_param, derive_register_param};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use async_std::sync::{Arc, Mutex, RwLock};
use async_trait::async_trait;
use flume::{Receiver, Sender};
use futures::select;
use zenoh::internal::buffers::{SplitBuffer, ZBuf};
use zenoh::{
core::Result as ZResult,
internal::{bail, zenoh_home, Timed, TimedEvent, Timer},
Expand All @@ -37,7 +38,6 @@ use zenoh::{
time::{new_reception_timestamp, Timestamp, NTP64},
value::Value,
};
use zenoh::internal::buffers::{SplitBuffer, ZBuf};
use zenoh_backend_traits::{
config::{GarbageCollectionConfig, StorageConfig},
Capability, History, Persistence, StorageInsertionResult, StoredData,
Expand Down
2 changes: 1 addition & 1 deletion zenoh/src/api/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use zenoh_buffers::{
buffer::{Buffer, SplitBuffer},
reader::HasReader,
writer::HasWriter,
ZBufReader, ZBufWriter, ZSlice, ZBuf,
ZBuf, ZBufReader, ZBufWriter, ZSlice,
};
use zenoh_codec::{RCodec, WCodec, Zenoh080};
use zenoh_protocol::{core::Properties, zenoh::ext::AttachmentType};
Expand Down
4 changes: 3 additions & 1 deletion zenoh/src/api/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ use super::{
info::SessionInfo,
key_expr::{KeyExpr, KeyExprInner},
publisher::{Priority, PublisherState},
query::{ConsolidationMode, SessionGetBuilder, QueryConsolidation, QueryState, QueryTarget, Reply},
query::{
ConsolidationMode, QueryConsolidation, QueryState, QueryTarget, Reply, SessionGetBuilder,
},
queryable::{Query, QueryInner, QueryableBuilder, QueryableState},
sample::{DataInfo, DataInfoIntoSample, Locality, QoS, Sample, SampleKind},
selector::{Selector, TIME_RANGE_KEY},
Expand Down

0 comments on commit eea9d74

Please sign in to comment.