use std::fmt;
use sval_derive::Value;
use super::stream_field;
const ANY_VALUE_STRING_LABEL: sval::Label =
sval::Label::new("stringValue").with_tag(&sval::tags::VALUE_IDENT);
const ANY_VALUE_BOOL_LABEL: sval::Label =
sval::Label::new("boolValue").with_tag(&sval::tags::VALUE_IDENT);
const ANY_VALUE_INT_LABEL: sval::Label =
sval::Label::new("intValue").with_tag(&sval::tags::VALUE_IDENT);
const ANY_VALUE_DOUBLE_LABEL: sval::Label =
sval::Label::new("doubleValue").with_tag(&sval::tags::VALUE_IDENT);
const ANY_VALUE_ARRAY_LABEL: sval::Label =
sval::Label::new("arrayValue").with_tag(&sval::tags::VALUE_IDENT);
const ANY_VALUE_KVLIST_LABEL: sval::Label =
sval::Label::new("kvlistValue").with_tag(&sval::tags::VALUE_IDENT);
const ANY_VALUE_BYTES_LABEL: sval::Label =
sval::Label::new("bytesValue").with_tag(&sval::tags::VALUE_IDENT);
const ANY_VALUE_STRING_INDEX: sval::Index = sval::Index::new(1);
const ANY_VALUE_BOOL_INDEX: sval::Index = sval::Index::new(2);
const ANY_VALUE_INT_INDEX: sval::Index = sval::Index::new(3);
const ANY_VALUE_DOUBLE_INDEX: sval::Index = sval::Index::new(4);
const ANY_VALUE_ARRAY_INDEX: sval::Index = sval::Index::new(5);
const ANY_VALUE_KVLIST_INDEX: sval::Index = sval::Index::new(6);
const ANY_VALUE_BYTES_INDEX: sval::Index = sval::Index::new(7);
#[derive(Value)]
pub enum AnyValue<'a, SV: ?Sized = str> {
#[sval(label = ANY_VALUE_STRING_LABEL, index = ANY_VALUE_STRING_INDEX)]
String(&'a SV),
}
const ARRAY_VALUES_LABEL: sval::Label =
sval::Label::new("values").with_tag(&sval::tags::VALUE_IDENT);
const ARRAY_VALUES_INDEX: sval::Index = sval::Index::new(1);
const KVLIST_VALUES_LABEL: sval::Label =
sval::Label::new("values").with_tag(&sval::tags::VALUE_IDENT);
const KVLIST_VALUES_INDEX: sval::Index = sval::Index::new(1);
const KEY_VALUE_KEY_LABEL: sval::Label = sval::Label::new("key").with_tag(&sval::tags::VALUE_IDENT);
const KEY_VALUE_VALUE_LABEL: sval::Label =
sval::Label::new("value").with_tag(&sval::tags::VALUE_IDENT);
const KEY_VALUE_KEY_INDEX: sval::Index = sval::Index::new(1);
const KEY_VALUE_VALUE_INDEX: sval::Index = sval::Index::new(2);
#[derive(Value)]
pub struct KeyValue<K, V> {
#[sval(label = KEY_VALUE_KEY_LABEL, index = KEY_VALUE_KEY_INDEX)]
pub key: K,
#[sval(label = KEY_VALUE_VALUE_LABEL, index = KEY_VALUE_VALUE_INDEX)]
pub value: V,
}
impl<'a, K: sval_ref::ValueRef<'a>, V: sval_ref::ValueRef<'a>> sval_ref::ValueRef<'a>
for KeyValue<K, V>
{
fn stream_ref<S: sval::Stream<'a> + ?Sized>(&self, stream: &mut S) -> sval::Result {
stream.record_tuple_begin(None, None, None, Some(2))?;
stream_field(
&mut *stream,
&KEY_VALUE_KEY_LABEL,
&KEY_VALUE_KEY_INDEX,
|stream| sval_ref::stream_ref(&mut *stream, &self.key),
)?;
stream_field(
&mut *stream,
&KEY_VALUE_VALUE_LABEL,
&KEY_VALUE_VALUE_INDEX,
|stream| sval_ref::stream_ref(&mut *stream, &self.value),
)?;
stream.record_tuple_end(None, None, None)
}
}
#[repr(transparent)]
pub struct Stacktrace(dyn std::error::Error + 'static);
impl Stacktrace {
pub fn new_borrowed<'a>(err: &'a (dyn std::error::Error + 'static)) -> &'a Self {
unsafe { &*(err as *const (dyn std::error::Error + 'static) as *const Stacktrace) }
}
}
impl fmt::Display for Stacktrace {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut first = true;
for cause in std::iter::successors(Some(&self.0), |err| (*err).source()) {
if !first {
f.write_str("\n")?;
}
first = false;
f.write_str("caused by: ")?;
fmt::Display::fmt(cause, f)?;
}
Ok(())
}
}
pub struct TextValue<T>(pub T);
impl<T: fmt::Display> sval::Value for TextValue<T> {
fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result {
stream.enum_begin(None, None, None)?;
stream.tagged_begin(
None,
Some(&ANY_VALUE_STRING_LABEL),
Some(&ANY_VALUE_STRING_INDEX),
)?;
sval::stream_display(&mut *stream, &self.0)?;
stream.tagged_end(
None,
Some(&ANY_VALUE_STRING_LABEL),
Some(&ANY_VALUE_STRING_INDEX),
)?;
stream.enum_end(None, None, None)
}
}
pub struct EmitValue<'a>(pub emit::value::Value<'a>);
impl<'a> sval::Value for EmitValue<'a> {
fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result {
use sval_ref::ValueRef as _;
self.stream_ref(stream)
}
}
impl<'a> sval_ref::ValueRef<'a> for EmitValue<'a> {
fn stream_ref<S: sval::Stream<'a> + ?Sized>(&self, stream: &mut S) -> sval::Result {
struct AnyStream<S> {
stream: S,
in_map_key: bool,
}
impl<'sval, S: sval::Stream<'sval>> AnyStream<S> {
fn any_value_begin(
&mut self,
label: &sval::Label,
index: &sval::Index,
) -> sval::Result {
self.stream.enum_begin(None, None, None)?;
self.stream.tagged_begin(None, Some(label), Some(index))
}
fn any_value_end(&mut self, label: &sval::Label, index: &sval::Index) -> sval::Result {
self.stream.tagged_end(None, Some(label), Some(index))?;
self.stream.enum_end(None, None, None)
}
}
impl<'sval, S: sval::Stream<'sval>> sval::Stream<'sval> for AnyStream<S> {
fn null(&mut self) -> sval::Result {
self.stream.null()
}
fn bool(&mut self, value: bool) -> sval::Result {
if self.in_map_key {
todo!()
}
self.any_value_begin(&ANY_VALUE_BOOL_LABEL, &ANY_VALUE_BOOL_INDEX)?;
self.stream.bool(value)?;
self.any_value_end(&ANY_VALUE_BOOL_LABEL, &ANY_VALUE_BOOL_INDEX)
}
fn text_begin(&mut self, num_bytes: Option<usize>) -> sval::Result {
if !self.in_map_key {
self.any_value_begin(&ANY_VALUE_STRING_LABEL, &ANY_VALUE_STRING_INDEX)?;
}
self.stream.text_begin(num_bytes)
}
fn text_fragment(&mut self, fragment: &'sval str) -> sval::Result {
self.stream.text_fragment(fragment)
}
fn text_fragment_computed(&mut self, fragment: &str) -> sval::Result {
self.stream.text_fragment_computed(fragment)
}
fn text_end(&mut self) -> sval::Result {
self.stream.text_end()?;
if !self.in_map_key {
self.any_value_end(&ANY_VALUE_STRING_LABEL, &ANY_VALUE_STRING_INDEX)?;
}
Ok(())
}
fn i64(&mut self, value: i64) -> sval::Result {
if self.in_map_key {
todo!()
}
self.any_value_begin(&ANY_VALUE_INT_LABEL, &ANY_VALUE_INT_INDEX)?;
self.stream.i64(value)?;
self.any_value_end(&ANY_VALUE_INT_LABEL, &ANY_VALUE_INT_INDEX)
}
fn f64(&mut self, value: f64) -> sval::Result {
if self.in_map_key {
todo!()
}
self.any_value_begin(&ANY_VALUE_DOUBLE_LABEL, &ANY_VALUE_DOUBLE_INDEX)?;
self.stream.f64(value)?;
self.any_value_end(&ANY_VALUE_DOUBLE_LABEL, &ANY_VALUE_DOUBLE_INDEX)
}
fn binary_begin(&mut self, num_bytes: Option<usize>) -> sval::Result {
if self.in_map_key {
todo!()
}
self.any_value_begin(&ANY_VALUE_BYTES_LABEL, &ANY_VALUE_BYTES_INDEX)?;
self.stream.binary_begin(num_bytes)
}
fn binary_fragment(&mut self, fragment: &'sval [u8]) -> sval::Result {
self.stream.binary_fragment(fragment)
}
fn binary_fragment_computed(&mut self, fragment: &[u8]) -> sval::Result {
self.stream.binary_fragment_computed(fragment)
}
fn binary_end(&mut self) -> sval::Result {
self.stream.binary_end()?;
self.any_value_end(&ANY_VALUE_BYTES_LABEL, &ANY_VALUE_BYTES_INDEX)
}
fn seq_begin(&mut self, num_entries: Option<usize>) -> sval::Result {
if self.in_map_key {
todo!()
}
self.any_value_begin(&ANY_VALUE_ARRAY_LABEL, &ANY_VALUE_ARRAY_INDEX)?;
self.stream.record_tuple_begin(None, None, None, Some(1))?;
self.stream.record_tuple_value_begin(
None,
&ARRAY_VALUES_LABEL,
&ARRAY_VALUES_INDEX,
)?;
self.stream.seq_begin(num_entries)
}
fn seq_value_begin(&mut self) -> sval::Result {
self.stream.seq_value_begin()
}
fn seq_value_end(&mut self) -> sval::Result {
self.stream.seq_value_end()
}
fn seq_end(&mut self) -> sval::Result {
self.stream.seq_end()?;
self.stream.record_tuple_value_end(
None,
&ARRAY_VALUES_LABEL,
&ARRAY_VALUES_INDEX,
)?;
self.stream.record_tuple_end(None, None, None)?;
self.any_value_end(&ANY_VALUE_ARRAY_LABEL, &ANY_VALUE_ARRAY_INDEX)
}
fn map_begin(&mut self, num_entries: Option<usize>) -> sval::Result {
if self.in_map_key {
todo!()
}
self.any_value_begin(&ANY_VALUE_KVLIST_LABEL, &ANY_VALUE_KVLIST_INDEX)?;
self.stream.record_tuple_begin(None, None, None, Some(1))?;
self.stream.record_tuple_value_begin(
None,
&ARRAY_VALUES_LABEL,
&ARRAY_VALUES_INDEX,
)?;
self.stream.seq_begin(num_entries)
}
fn map_key_begin(&mut self) -> sval::Result {
self.in_map_key = true;
self.stream.seq_value_begin()?;
self.stream.record_tuple_begin(None, None, None, Some(2))?;
self.stream.record_tuple_value_begin(
None,
&KEY_VALUE_KEY_LABEL,
&KEY_VALUE_KEY_INDEX,
)
}
fn map_key_end(&mut self) -> sval::Result {
self.in_map_key = false;
self.stream
.record_tuple_value_end(None, &KEY_VALUE_KEY_LABEL, &KEY_VALUE_KEY_INDEX)
}
fn map_value_begin(&mut self) -> sval::Result {
self.stream.record_tuple_value_begin(
None,
&KEY_VALUE_VALUE_LABEL,
&KEY_VALUE_VALUE_INDEX,
)
}
fn map_value_end(&mut self) -> sval::Result {
self.stream.record_tuple_value_end(
None,
&KEY_VALUE_VALUE_LABEL,
&KEY_VALUE_VALUE_INDEX,
)?;
self.stream.record_tuple_end(None, None, None)?;
self.stream.seq_value_end()
}
fn map_end(&mut self) -> sval::Result {
self.stream.seq_end()?;
self.stream.record_tuple_value_end(
None,
&KVLIST_VALUES_LABEL,
&KVLIST_VALUES_INDEX,
)?;
self.stream.record_tuple_end(None, None, None)?;
self.any_value_end(&ANY_VALUE_KVLIST_LABEL, &ANY_VALUE_KVLIST_INDEX)
}
}
sval_ref::stream_ref(
&mut AnyStream {
stream,
in_map_key: false,
},
&self.0,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use prost::Message;
use crate::data::generated::{common::v1 as common, util::*};
fn encode<'a>(v: impl Into<emit::Value<'a>>) -> impl bytes::Buf {
sval_protobuf::stream_to_protobuf(EmitValue(v.into())).into_cursor()
}
#[test]
fn encode_string() {
let de = common::AnyValue::decode(encode("string value")).unwrap();
assert_eq!(string_value("string value"), de);
}
#[test]
fn encode_bytes() {
let de = common::AnyValue::decode(encode(emit::Value::capture_sval(
&sval::BinarySlice::new(b"bytes value"),
)))
.unwrap();
assert_eq!(bytes_value(b"bytes value"), de);
}
#[test]
fn encode_bool() {
let de = common::AnyValue::decode(encode(true)).unwrap();
assert_eq!(bool_value(true), de);
}
#[test]
fn encode_int_i32() {
let de = common::AnyValue::decode(encode(42)).unwrap();
assert_eq!(int_value(42), de);
}
#[test]
fn encode_int_i128_oversize() {
let de = common::AnyValue::decode(encode(i128::MAX)).unwrap();
assert_eq!(string_value(i128::MAX.to_string()), de);
}
#[test]
fn encode_double() {
let de = common::AnyValue::decode(encode(42.1)).unwrap();
assert_eq!(double_value(42.1), de);
}
#[test]
fn encode_array() {
let de = common::AnyValue::decode(encode(emit::Value::capture_sval(&[1, 2, 3]))).unwrap();
assert_eq!(array_value([int_value(1), int_value(2), int_value(3)]), de);
}
#[test]
fn encode_array_nested() {
let de = common::AnyValue::decode(encode(emit::Value::capture_sval(&[
emit::Value::from(1),
emit::Value::from(emit::Value::capture_sval(&[1, 2, 3])),
emit::Value::from(3),
])))
.unwrap();
assert_eq!(
array_value([
int_value(1),
array_value([int_value(1), int_value(2), int_value(3)]),
int_value(3)
]),
de
);
}
#[test]
fn encode_kvlist() {
let de =
common::AnyValue::decode(encode(emit::Value::capture_sval(&sval::MapSlice::new(&[
("a", 1),
("b", 2),
("c", 3),
]))))
.unwrap();
assert_eq!(
kvlist_value([
("a".into(), int_value(1)),
("b".into(), int_value(2)),
("c".into(), int_value(3)),
]),
de
);
}
#[test]
fn encode_kvlist_nested() {
let de = common::AnyValue::decode(encode(emit::Value::from_sval(&sval::MapSlice::new(&[
("a", emit::Value::from(1)),
(
"b",
emit::Value::from_sval(&sval::MapSlice::new(&[("a", 1), ("b", 2), ("c", 3)])),
),
("c", emit::Value::from(3)),
]))))
.unwrap();
assert_eq!(
kvlist_value([
("a".into(), int_value(1)),
(
"b".into(),
kvlist_value([
("a".into(), int_value(1)),
("b".into(), int_value(2)),
("c".into(), int_value(3)),
])
),
("c".into(), int_value(3)),
]),
de
);
}
}