diff --git a/Cargo.lock b/Cargo.lock index fa432e0..65c37e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + [[package]] name = "axum" version = "0.8.9" @@ -74,6 +80,7 @@ name = "bogos-binted" version = "0.1.0" dependencies = [ "axum", + "rmp", "tokio", "tower", "tracing", @@ -326,6 +333,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -439,9 +455,18 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rmp" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" +dependencies = [ + "num-traits", +] [[package]] name = "rustversion" diff --git a/Cargo.toml b/Cargo.toml index c8516f5..d2855a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,10 @@ [workspace] resolver = "3" -members = ["crates/demo","crates/lib"] +members = [ + "crates/demo", + "crates/lib", +] + [workspace.dependencies] axum = "0.8.9" @@ -9,3 +13,5 @@ tower = "0.5.3" tracing = "0.1.44" tracing-futures = "0.2.5" tracing-subscriber = "0.3.23" +rmp = "0.8.15" +rmpv = "1.3.1" diff --git a/crates/lib/Cargo.toml b/crates/lib/Cargo.toml index 7241170..55a1fe8 100644 --- a/crates/lib/Cargo.toml +++ b/crates/lib/Cargo.toml @@ -8,4 +8,5 @@ axum = { workspace = true } tokio = { workspace = true } tower = { workspace = true } tracing = { workspace = true } +rmp = { workspace = true } ulid = "1.2.1" diff --git a/crates/lib/src/messagepack.rs b/crates/lib/src/messagepack.rs index 2bd9f0a..b82e1db 100644 --- a/crates/lib/src/messagepack.rs +++ b/crates/lib/src/messagepack.rs @@ -1,20 +1,103 @@ -use tracing::{Event, span}; +use rmp::encode::ByteBuf; +use tracing::{Event, field::Visit, span}; pub struct MessagePackBytes(Vec); impl From<&span::Attributes<'_>> for MessagePackBytes { fn from(value: &span::Attributes<'_>) -> Self { - todo!() + let mut visitor = Visitor::new(value.fields().len()); + value.record(&mut visitor); + + Self(visitor.0.into_vec()) } } impl From<&span::Record<'_>> for MessagePackBytes { fn from(value: &span::Record<'_>) -> Self { - todo!() + let mut visitor = Visitor::new(value.len()); + value.record(&mut visitor); + + Self(visitor.0.into_vec()) } } impl From<&Event<'_>> for MessagePackBytes { fn from(value: &Event<'_>) -> Self { - todo!() + let mut visitor = Visitor::new(value.fields().count()); + value.record(&mut visitor); + + Self(visitor.0.into_vec()) + } +} + +const SIGNED_128: i8 = 27; +const UNSIGNED_128: i8 = 34; + +#[derive(Debug, Default)] +struct Visitor(ByteBuf); + +impl Visitor { + fn new(len: usize) -> Self { + let mut this = Self(ByteBuf::new()); + rmp::encode::write_map_len(&mut this.0, len.try_into().unwrap()).unwrap(); + this + } +} + +impl Visitor { + fn record_field_name(&mut self, field: &tracing::field::Field) { + rmp::encode::write_str_len(&mut self.0, field.name().len().try_into().unwrap()).unwrap(); + rmp::encode::write_str(&mut self.0, field.name()).unwrap(); + } +} + +impl Visit for Visitor { + fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn core::fmt::Debug) { + self.record_field_name(field); + let s = format!("{:?}", value); + rmp::encode::write_str_len(&mut self.0, s.len().try_into().unwrap()).unwrap(); + rmp::encode::write_str(&mut self.0, &s).unwrap(); + } + + fn record_f64(&mut self, field: &tracing::field::Field, value: f64) { + self.record_field_name(field); + rmp::encode::write_f64(&mut self.0, value).unwrap(); + } + + fn record_i64(&mut self, field: &tracing::field::Field, value: i64) { + self.record_field_name(field); + rmp::encode::write_i64(&mut self.0, value).unwrap(); + } + + fn record_u64(&mut self, field: &tracing::field::Field, value: u64) { + self.record_field_name(field); + rmp::encode::write_u64(&mut self.0, value).unwrap(); + } + + fn record_i128(&mut self, field: &tracing::field::Field, value: i128) { + self.record_field_name(field); + rmp::encode::write_ext_meta(&mut self.0, 16, SIGNED_128).unwrap(); + rmp::encode::write_bin(&mut self.0, &value.to_be_bytes()).unwrap(); + } + + fn record_u128(&mut self, field: &tracing::field::Field, value: u128) { + self.record_field_name(field); + rmp::encode::write_ext_meta(&mut self.0, 16, UNSIGNED_128).unwrap(); + rmp::encode::write_bin(&mut self.0, &value.to_be_bytes()).unwrap(); + } + + fn record_bool(&mut self, field: &tracing::field::Field, value: bool) { + self.record_field_name(field); + rmp::encode::write_bool(&mut self.0, value).unwrap(); + } + + fn record_str(&mut self, field: &tracing::field::Field, value: &str) { + self.record_field_name(field); + rmp::encode::write_str(&mut self.0, value).unwrap(); + } + + fn record_bytes(&mut self, field: &tracing::field::Field, value: &[u8]) { + self.record_field_name(field); + rmp::encode::write_bin_len(&mut self.0, value.len().try_into().unwrap()).unwrap(); + rmp::encode::write_bin(&mut self.0, value).unwrap(); } }