diff --git a/copper_log/Cargo.toml b/copper_log/Cargo.toml index 504a99475..0d6bf563e 100644 --- a/copper_log/Cargo.toml +++ b/copper_log/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [lib] name = "copper_log" -path = "src/macros.rs" +path = "src/lib.rs" proc-macro = true [[bin]] diff --git a/copper_log/src/macros.rs b/copper_log/src/lib.rs similarity index 78% rename from copper_log/src/macros.rs rename to copper_log/src/lib.rs index 4b9a738aa..49b616a30 100644 --- a/copper_log/src/macros.rs +++ b/copper_log/src/lib.rs @@ -30,11 +30,10 @@ pub fn debug(input: TokenStream) -> TokenStream { let prefix = quote! { use copper_log_runtime::value::Value; use copper_log_runtime::value::to_value; + use copper_log_runtime::CuLogEntry; use copper_log_runtime::ANONYMOUS; let msg = #msg; - let index = #index; - let mut params = Vec::::new(); - let mut params_istring = Vec::::new(); + let mut log_entry = CuLogEntry::new(#index); }; let mut unnamed_params = vec![]; @@ -50,10 +49,8 @@ pub fn debug(input: TokenStream) -> TokenStream { let unnamed_prints = unnamed_params.iter().map(|value| { quote! { - let istring = ANONYMOUS; let param = to_value(#value).expect("Failed to convert a parameter to a Value"); - params_istring.push(istring); - params.push(param); + log_entry.add_param(ANONYMOUS, param); } }); @@ -61,18 +58,14 @@ pub fn debug(input: TokenStream) -> TokenStream { let index = intern_string(quote!(#name).to_string().as_str()) .expect("Failed to insert log string."); quote! { - let istring = to_value(#index).unwrap(); let param = to_value(#value).expect("Failed to convert a parameter to a Value"); - params_istring.push(istring); - params.push(param); + log_entry.add_param(#index, param); } }); let postfix = quote! { - let vparams = Value::Seq(params); // to do add conditional - println!("{} {}", msg, &vparams); - let packed_value = Value::Seq(vec![to_value(index).unwrap(), Value::Seq(params_istring), vparams]); - copper_log_runtime::log(packed_value); + println!("{} {}", msg, &log_entry); + copper_log_runtime::log(log_entry); }; let expanded = quote! { diff --git a/copper_log_runtime/Cargo.toml b/copper_log_runtime/Cargo.toml index 727e1e4a7..a016f2673 100644 --- a/copper_log_runtime/Cargo.toml +++ b/copper_log_runtime/Cargo.toml @@ -8,6 +8,7 @@ copper-value = { path = "../copper_value" } lazy_static = "1.4.0" serde = { version = "1.0.202", features = ["derive"] } bincode = { version = "2.0.0-rc.3", features = ["serde"] } +bincode_derive = "2.0.0-rc.3" pretty-hex = "0.4.1" ctor = "0.2.8" ctrlc = { version = "3.4.4", features = ["termination"] } diff --git a/copper_log_runtime/src/lib.rs b/copper_log_runtime/src/lib.rs index 186764fc3..d7f48fb6d 100644 --- a/copper_log_runtime/src/lib.rs +++ b/copper_log_runtime/src/lib.rs @@ -1,6 +1,7 @@ -use bincode; use bincode::enc::write::Writer; -pub use copper_value as value; +use bincode_derive::{Decode, Encode}; +pub use copper_value as value; // Part of the API, do not remove. +use copper_value::Value; use kanal::{bounded, Sender}; use lazy_static::lazy_static; use pretty_hex::pretty_hex; @@ -8,13 +9,44 @@ use std::fmt::Display; use std::io::{stdout, Write}; use std::sync::{Arc, Mutex}; use std::thread; -use value::Value; #[allow(dead_code)] -pub const ANONYMOUS: Value = Value::U32(0); +pub const ANONYMOUS: u32 = 0; + +#[derive(Debug, Encode, Decode)] +pub struct CuLogEntry { + pub msg_index: u32, + pub paramname_indexes: Vec, + pub params: Vec, +} + +impl Display for CuLogEntry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "CuLogEntry {{ msg_index: {}, paramname_indexes: {:?}, params: {:?} }}", + self.msg_index, self.paramname_indexes, self.params + ) + } +} + +impl CuLogEntry { + pub fn new(msg_index: u32) -> Self { + CuLogEntry { + msg_index, + paramname_indexes: Vec::new(), + params: Vec::new(), + } + } + + pub fn add_param(&mut self, paramname_index: u32, param: Value) { + self.paramname_indexes.push(paramname_index); + self.params.push(param); + } +} lazy_static! { - static ref QUEUE: Sender = initialize_queue(); + static ref QUEUE: Sender = initialize_queue(); } /// The lifetime of this struct is the lifetime of the logger. @@ -37,8 +69,8 @@ impl Drop for LoggerRuntime { } } -fn initialize_queue() -> Sender { - let (sender, receiver) = bounded::(100); +fn initialize_queue() -> Sender { + let (sender, receiver) = bounded::(100); let config = bincode::config::standard(); let handle = thread::spawn(move || loop { @@ -65,9 +97,9 @@ fn initialize_queue() -> Sender { /// Function called from generated code to log data. #[inline] -pub fn log(data: Value) { +pub fn log(entry: CuLogEntry) { // If the queue is closed, we just drop the data. - if QUEUE.send(data).is_err() { + if QUEUE.send(entry).is_err() { if !QUEUE.is_closed() { eprintln!("Copper: Failed to send data to the logger, some data got dropped."); if QUEUE.is_full() { diff --git a/copper_value/src/bdec.rs b/copper_value/src/bdec.rs new file mode 100644 index 000000000..58722d9ba --- /dev/null +++ b/copper_value/src/bdec.rs @@ -0,0 +1,64 @@ +use crate::Value; +use bincode::BorrowDecode; +use std::collections::BTreeMap; + +use bincode::de::Decoder; +use bincode::de::{BorrowDecoder, Decode}; +use bincode::error::DecodeError; + +// TODO: Unharcode all those enum types values +impl Decode for Value { + fn decode(decoder: &mut D) -> Result { + match u8::decode(decoder)? { + 0 => Ok(Value::U8(u8::decode(decoder)?)), + 1 => Ok(Value::U16(u16::decode(decoder)?)), + 2 => Ok(Value::U32(u32::decode(decoder)?)), + 3 => Ok(Value::U64(u64::decode(decoder)?)), + 4 => Ok(Value::I8(i8::decode(decoder)?)), + 5 => Ok(Value::I16(i16::decode(decoder)?)), + 6 => Ok(Value::I32(i32::decode(decoder)?)), + 7 => Ok(Value::I64(i64::decode(decoder)?)), + 8 => Ok(Value::F32(f32::decode(decoder)?)), + 9 => Ok(Value::F64(f64::decode(decoder)?)), + 10 => Ok(Value::Bool(bool::decode(decoder)?)), + 11 => Ok(Value::Char(char::decode(decoder)?)), + 12 => Ok(Value::String(String::decode(decoder)?)), + 13 => Ok(Value::Bytes(Vec::::decode(decoder)?)), + 14 => Ok(Value::Unit), + 15 => Ok(Value::Seq(Vec::::decode(decoder)?)), + 16 => Ok(Value::Map(BTreeMap::::decode(decoder)?)), + 17 => Ok(Value::Option(Option::>::decode(decoder)?)), + 18 => Ok(Value::Newtype(Box::::decode(decoder)?)), + _ => Err(DecodeError::Other("Unknown Value variant")), + } + } +} + +impl<'de> BorrowDecode<'de> for Value { + fn borrow_decode>(decoder: &mut D) -> Result { + match u8::borrow_decode(decoder)? { + 0 => Ok(Value::U8(u8::borrow_decode(decoder)?)), + 1 => Ok(Value::U16(u16::borrow_decode(decoder)?)), + 2 => Ok(Value::U32(u32::borrow_decode(decoder)?)), + 3 => Ok(Value::U64(u64::borrow_decode(decoder)?)), + 4 => Ok(Value::I8(i8::borrow_decode(decoder)?)), + 5 => Ok(Value::I16(i16::borrow_decode(decoder)?)), + 6 => Ok(Value::I32(i32::borrow_decode(decoder)?)), + 7 => Ok(Value::I64(i64::borrow_decode(decoder)?)), + 8 => Ok(Value::F32(f32::borrow_decode(decoder)?)), + 9 => Ok(Value::F64(f64::borrow_decode(decoder)?)), + 10 => Ok(Value::Bool(bool::borrow_decode(decoder)?)), + 11 => Ok(Value::Char(char::borrow_decode(decoder)?)), + 12 => Ok(Value::String(String::borrow_decode(decoder)?)), + 13 => Ok(Value::Bytes(Vec::::borrow_decode(decoder)?)), + 14 => Ok(Value::Unit), + 15 => Ok(Value::Seq(Vec::::borrow_decode(decoder)?)), + 16 => Ok(Value::Map(BTreeMap::::borrow_decode( + decoder, + )?)), + 17 => Ok(Value::Option(Option::>::borrow_decode(decoder)?)), + 18 => Ok(Value::Newtype(Box::::borrow_decode(decoder)?)), + _ => Err(DecodeError::Other("Unknown Value variant")), + } + } +} diff --git a/copper_value/src/de.rs b/copper_value/src/de.rs index 97dc1155e..ef51fd81c 100644 --- a/copper_value/src/de.rs +++ b/copper_value/src/de.rs @@ -1,4 +1,4 @@ -use serde::{forward_to_deserialize_any, de}; +use serde::{de, forward_to_deserialize_any}; use std::collections::BTreeMap; use std::error::Error; use std::fmt; @@ -76,7 +76,6 @@ impl Unexpected { Unexpected::Other(ref v) => de::Unexpected::Other(v), } } - } #[derive(Debug)] @@ -159,19 +158,39 @@ impl fmt::Display for DeserializerError { match *self { DeserializerError::Custom(ref msg) => write!(f, "{}", msg), DeserializerError::InvalidType(ref unexp, ref exp) => { - write!(f, "Invalid type {}. Expected {}", unexp.to_unexpected(), exp) + write!( + f, + "Invalid type {}. Expected {}", + unexp.to_unexpected(), + exp + ) } DeserializerError::InvalidValue(ref unexp, ref exp) => { - write!(f, "Invalid value {}. Expected {}", unexp.to_unexpected(), exp) + write!( + f, + "Invalid value {}. Expected {}", + unexp.to_unexpected(), + exp + ) } DeserializerError::InvalidLength(len, ref exp) => { write!(f, "Invalid length {}. Expected {}", len, exp) } DeserializerError::UnknownVariant(ref field, exp) => { - write!(f, "Unknown variant {}. Expected one of {}", field, exp.join(", ")) - }, + write!( + f, + "Unknown variant {}. Expected one of {}", + field, + exp.join(", ") + ) + } DeserializerError::UnknownField(ref field, exp) => { - write!(f, "Unknown field {}. Expected one of {}", field, exp.join(", ")) + write!( + f, + "Unknown field {}. Expected one of {}", + field, + exp.join(", ") + ) } DeserializerError::MissingField(field) => write!(f, "Missing field {}", field), DeserializerError::DuplicateField(field) => write!(f, "Duplicate field {}", field), @@ -259,11 +278,13 @@ impl<'de> de::Visitor<'de> for ValueVisitor { } fn visit_some>(self, d: D) -> Result { - d.deserialize_any(ValueVisitor).map(|v| Value::Option(Some(Box::new(v)))) + d.deserialize_any(ValueVisitor) + .map(|v| Value::Option(Some(Box::new(v)))) } fn visit_newtype_struct>(self, d: D) -> Result { - d.deserialize_any(ValueVisitor).map(|v| Value::Newtype(Box::new(v))) + d.deserialize_any(ValueVisitor) + .map(|v| Value::Newtype(Box::new(v))) } fn visit_seq>(self, mut visitor: V) -> Result { @@ -323,7 +344,10 @@ impl ValueDeserializer { } } -impl<'de, E> de::Deserializer<'de> for ValueDeserializer where E: de::Error { +impl<'de, E> de::Deserializer<'de> for ValueDeserializer +where + E: de::Error, +{ type Error = E; fn deserialize_any>(self, visitor: V) -> Result { @@ -345,15 +369,13 @@ impl<'de, E> de::Deserializer<'de> for ValueDeserializer where E: de::Error { Value::Option(None) => visitor.visit_none(), Value::Option(Some(v)) => visitor.visit_some(ValueDeserializer::new(*v)), Value::Newtype(v) => visitor.visit_newtype_struct(ValueDeserializer::new(*v)), - Value::Seq(v) => { - visitor.visit_seq(de::value::SeqDeserializer::new(v.into_iter().map(ValueDeserializer::new))) - }, - Value::Map(v) => { - visitor.visit_map(de::value::MapDeserializer::new(v.into_iter().map(|(k, v)| ( - ValueDeserializer::new(k), - ValueDeserializer::new(v), - )))) - }, + Value::Seq(v) => visitor.visit_seq(de::value::SeqDeserializer::new( + v.into_iter().map(ValueDeserializer::new), + )), + Value::Map(v) => visitor + .visit_map(de::value::MapDeserializer::new(v.into_iter().map( + |(k, v)| (ValueDeserializer::new(k), ValueDeserializer::new(v)), + ))), Value::Bytes(v) => visitor.visit_byte_buf(v), } } @@ -362,35 +384,43 @@ impl<'de, E> de::Deserializer<'de> for ValueDeserializer where E: de::Error { match self.value { Value::Option(..) => self.deserialize_any(visitor), Value::Unit => visitor.visit_unit(), - _ => visitor.visit_some(self) + _ => visitor.visit_some(self), } } - fn deserialize_enum>(self, - _name: &'static str, - _variants: &'static [&'static str], - visitor: V) - -> Result { + fn deserialize_enum>( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result { let (variant, value) = match self.value { Value::Map(value) => { let mut iter = value.into_iter(); let (variant, value) = match iter.next() { Some(v) => v, None => { - return Err(de::Error::invalid_value(de::Unexpected::Map, - &"map with a single key")); + return Err(de::Error::invalid_value( + de::Unexpected::Map, + &"map with a single key", + )); } }; // enums are encoded as maps with a single key:value pair if iter.next().is_some() { - return Err(de::Error::invalid_value(de::Unexpected::Map, - &"map with a single key")); + return Err(de::Error::invalid_value( + de::Unexpected::Map, + &"map with a single key", + )); } (variant, Some(value)) } Value::String(variant) => (Value::String(variant), None), other => { - return Err(de::Error::invalid_type(other.unexpected(), &"string or map")); + return Err(de::Error::invalid_type( + other.unexpected(), + &"string or map", + )); } }; @@ -402,10 +432,11 @@ impl<'de, E> de::Deserializer<'de> for ValueDeserializer where E: de::Error { visitor.visit_enum(d) } - fn deserialize_newtype_struct>(self, - _name: &'static str, - visitor: V) - -> Result { + fn deserialize_newtype_struct>( + self, + _name: &'static str, + visitor: V, + ) -> Result { match self.value { Value::Newtype(v) => visitor.visit_newtype_struct(ValueDeserializer::new(*v)), _ => visitor.visit_newtype_struct(self), @@ -419,7 +450,10 @@ impl<'de, E> de::Deserializer<'de> for ValueDeserializer where E: de::Error { } } -impl<'de, E> de::IntoDeserializer<'de, E> for ValueDeserializer where E: de::Error { +impl<'de, E> de::IntoDeserializer<'de, E> for ValueDeserializer +where + E: de::Error, +{ type Deserializer = Self; fn into_deserializer(self) -> Self::Deserializer { @@ -438,18 +472,20 @@ impl<'de> de::Deserializer<'de> for Value { ValueDeserializer::new(self).deserialize_option(visitor) } - fn deserialize_enum>(self, - name: &'static str, - variants: &'static [&'static str], - visitor: V) - -> Result { + fn deserialize_enum>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result { ValueDeserializer::new(self).deserialize_enum(name, variants, visitor) } - fn deserialize_newtype_struct>(self, - name: &'static str, - visitor: V) - -> Result { + fn deserialize_newtype_struct>( + self, + name: &'static str, + visitor: V, + ) -> Result { ValueDeserializer::new(self).deserialize_newtype_struct(name, visitor) } @@ -466,18 +502,26 @@ struct EnumDeserializer { error: PhantomData E>, } -impl<'de, E> de::EnumAccess<'de> for EnumDeserializer where E: de::Error { +impl<'de, E> de::EnumAccess<'de> for EnumDeserializer +where + E: de::Error, +{ type Error = E; type Variant = VariantDeserializer; - fn variant_seed(self, seed: V) -> Result<(V::Value, VariantDeserializer), Self::Error> - where V: de::DeserializeSeed<'de> + fn variant_seed( + self, + seed: V, + ) -> Result<(V::Value, VariantDeserializer), Self::Error> + where + V: de::DeserializeSeed<'de>, { let visitor = VariantDeserializer { value: self.value, error: Default::default(), }; - seed.deserialize(ValueDeserializer::new(self.variant)).map(|v| (v, visitor)) + seed.deserialize(ValueDeserializer::new(self.variant)) + .map(|v| (v, visitor)) } } @@ -486,7 +530,10 @@ struct VariantDeserializer { error: PhantomData E>, } -impl<'de, E> de::VariantAccess<'de> for VariantDeserializer where E: de::Error { +impl<'de, E> de::VariantAccess<'de> for VariantDeserializer +where + E: de::Error, +{ type Error = E; fn unit_variant(self) -> Result<(), Self::Error> { @@ -497,45 +544,62 @@ impl<'de, E> de::VariantAccess<'de> for VariantDeserializer where E: de::Erro } fn newtype_variant_seed(self, seed: T) -> Result - where T: de::DeserializeSeed<'de> + where + T: de::DeserializeSeed<'de>, { match self.value { Some(value) => seed.deserialize(ValueDeserializer::new(value)), - None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant")), + None => Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"newtype variant", + )), } } fn tuple_variant(self, _len: usize, visitor: V) -> Result - where V: de::Visitor<'de> + where + V: de::Visitor<'de>, { match self.value { - Some(Value::Seq(v)) => { - de::Deserializer::deserialize_any( - de::value::SeqDeserializer::new(v.into_iter().map(ValueDeserializer::new)), - visitor) - } - Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant")), - None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant")), + Some(Value::Seq(v)) => de::Deserializer::deserialize_any( + de::value::SeqDeserializer::new(v.into_iter().map(ValueDeserializer::new)), + visitor, + ), + Some(other) => Err(de::Error::invalid_type( + other.unexpected(), + &"tuple variant", + )), + None => Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"tuple variant", + )), } } - fn struct_variant(self, - _fields: &'static [&'static str], - visitor: V) - -> Result - where V: de::Visitor<'de> + fn struct_variant( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, { match self.value { - Some(Value::Map(v)) => { - de::Deserializer::deserialize_any( - de::value::MapDeserializer::new(v.into_iter().map(|(k, v)| ( - ValueDeserializer::new(k), - ValueDeserializer::new(v), - ))), - visitor) - } - Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant")), - None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant")), + Some(Value::Map(v)) => de::Deserializer::deserialize_any( + de::value::MapDeserializer::new( + v.into_iter() + .map(|(k, v)| (ValueDeserializer::new(k), ValueDeserializer::new(v))), + ), + visitor, + ), + Some(other) => Err(de::Error::invalid_type( + other.unexpected(), + &"struct variant", + )), + None => Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"struct variant", + )), } } } diff --git a/copper_value/src/lib.rs b/copper_value/src/lib.rs index 5fc995d9e..27b61a062 100644 --- a/copper_value/src/lib.rs +++ b/copper_value/src/lib.rs @@ -7,13 +7,16 @@ use std::collections::BTreeMap; use std::fmt::{Display, Formatter}; use std::hash::{Hash, Hasher}; -pub use de::*; -pub use ser::*; - +mod bdec; mod benc; mod de; mod ser; +pub use bdec::*; +pub use benc::*; +pub use de::*; +pub use ser::*; + #[derive(Clone, Debug)] pub enum Value { Bool(bool),