From 9ca409db7f797c1412f327b2eeb7fe9fc85dd0e5 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Wed, 6 Feb 2019 14:00:13 -0800 Subject: [PATCH] Re-introduce `ValueSet` length limit Signed-off-by: Eliza Weisman --- tokio-trace/src/lib.rs | 29 +++++++++++++++ tokio-trace/src/span.rs | 3 +- tokio-trace/tokio-trace-core/src/field.rs | 44 ++++++++++++++++++++--- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/tokio-trace/src/lib.rs b/tokio-trace/src/lib.rs index e6a3d27d982..8f6d79afd2f 100644 --- a/tokio-trace/src/lib.rs +++ b/tokio-trace/src/lib.rs @@ -443,6 +443,21 @@ macro_rules! callsite { /// my_span.record("bar", &7); /// # } /// ``` +/// +/// Note that a span may have up to 32 fields. The following will not compile: +/// ```rust,compile_fail +/// # #[macro_use] +/// # extern crate tokio_trace; +/// # fn main() { +/// span!( +/// "too many fields!", +/// a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7, h = 8, i = 9, +/// j = 10, k = 11, l = 12, m = 13, n = 14, o = 15, p = 16, q = 17, +/// r = 18, s = 19, t = 20, u = 21, v = 22, w = 23, x = 24, y = 25, +/// z = 26, aa = 27, bb = 28, cc = 29, dd = 30, ee = 31, ff = 32, gg = 33 +/// ); +/// # } +/// ``` #[macro_export] macro_rules! span { ($name:expr) => { span!($name,) }; @@ -500,6 +515,20 @@ macro_rules! span { /// event!(Level::Info, foo = 5, bad_field, bar = field::display("hello")) /// #} /// ``` +/// +/// Events may have up to 32 fields. The following will not compile: +/// ```rust,compile_fail +/// # #[macro_use] +/// # extern crate tokio_trace; +/// # fn main() { +/// event!(tokio_trace::Level::INFO, +/// a = 1, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7, h = 8, i = 9, +/// j = 10, k = 11, l = 12, m = 13, n = 14, o = 15, p = 16, q = 17, +/// r = 18, s = 19, t = 20, u = 21, v = 22, w = 23, x = 24, y = 25, +/// z = 26, aa = 27, bb = 28, cc = 29, dd = 30, ee = 31, ff = 32, gg = 33 +/// ); +/// # } +/// ``` #[macro_export] macro_rules! event { (target: $target:expr, $lvl:expr, { $( $k:ident = $val:expr ),* $(,)*} )=> ({ diff --git a/tokio-trace/src/span.rs b/tokio-trace/src/span.rs index ceae403770e..f9db6041267 100644 --- a/tokio-trace/src/span.rs +++ b/tokio-trace/src/span.rs @@ -293,7 +293,8 @@ impl<'a> Span<'a> { if let Some(ref mut inner) = self.inner { let meta = inner.metadata(); if let Some(field) = field.as_field(meta) { - inner.record(&meta.fields().value_set(&[(&field, Some(value))])) + inner.record(&meta.fields() + .value_set(&[(&field, Some(value as &field::Value))])) } } self diff --git a/tokio-trace/tokio-trace-core/src/field.rs b/tokio-trace/tokio-trace-core/src/field.rs index 45ee028eabd..a6f4573219b 100644 --- a/tokio-trace/tokio-trace-core/src/field.rs +++ b/tokio-trace/tokio-trace-core/src/field.rs @@ -221,6 +221,17 @@ pub struct DisplayValue(T); #[derive(Debug, Clone)] pub struct DebugValue(T); +/// Marker trait implemented by arrays which are of valid length to +/// construct a `ValueSet`. +/// +/// `ValueSet`s may only be constructed from arrays containing 32 or fewer +/// elements, to ensure the array is small enough to always be allocated on the +/// stack. This trait is only implemented by arrays of an appropriate length, +/// ensuring that the correct size arrays are used at compile-time. +pub trait ValidLen<'a>: ::sealed::Sealed + + Borrow<[(&'a Field, Option<&'a (Value + 'a)>)]> +{} + /// Wraps a type implementing `fmt::Display` as a `Value` that can be /// recorded using its `Display` implementation. pub fn display(t: T) -> DisplayValue @@ -447,14 +458,20 @@ impl FieldSet { } /// Returns a new `ValueSet` with entries for this `FieldSet`'s values. + /// + /// Note that a `ValueSet` may not be constructed with arrays of over 32 + /// elements. #[doc(hidden)] - pub fn value_set<'v>( + pub fn value_set<'v, V>( &'v self, - values: &'v [(&'v Field, Option<&'v (Value + 'v)>)], - ) -> ValueSet<'v> { + values: &'v V, + ) -> ValueSet<'v> + where + V: ValidLen<'v>, + { ValueSet { fields: self, - values, + values: &values.borrow()[..] } } @@ -565,6 +582,25 @@ impl<'a> fmt::Debug for ValueSet<'a> { } } +// ===== impl ValidLen ===== + +macro_rules! impl_valid_len { + ( $( $len:tt ),+ ) => { + $( + impl<'a> ::sealed::Sealed for + [(&'a Field, Option<&'a (Value + 'a)>); $len] {} + impl<'a> ValidLen<'a> for + [(&'a Field, Option<&'a (Value + 'a)>); $len] {} + )+ + } +} + +impl_valid_len! { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 +} + + #[cfg(test)] mod test { use super::*;