From 5c813a6f2a53f8d069aa91a9c08866c93d2ae525 Mon Sep 17 00:00:00 2001 From: John Starks Date: Tue, 26 Nov 2024 09:26:07 -0800 Subject: [PATCH] mesh_protobuf: support building with no_std (#391) Support encoding/decoding protobuf messages from `no_std` environments. We don't have an immediate use case for this, but there is some talk of using this within the boot loader (which would need a global allocator). --- support/mesh/mesh_channel/Cargo.toml | 2 +- support/mesh/mesh_protobuf/Cargo.toml | 1 + support/mesh/mesh_protobuf/src/buffer.rs | 7 ++- support/mesh/mesh_protobuf/src/encode_with.rs | 6 +- support/mesh/mesh_protobuf/src/encoding.rs | 53 +++++++++--------- support/mesh/mesh_protobuf/src/inplace.rs | 22 +++++--- support/mesh/mesh_protobuf/src/lib.rs | 56 ++++++++++++------- support/mesh/mesh_protobuf/src/message.rs | 6 ++ support/mesh/mesh_protobuf/src/prost.rs | 2 + support/mesh/mesh_protobuf/src/protobuf.rs | 17 ++++-- .../mesh/mesh_protobuf/src/protofile/mod.rs | 5 +- .../mesh_protobuf/src/protofile/writer.rs | 13 ++++- .../mesh/mesh_protobuf/src/table/decode.rs | 11 ++-- .../mesh/mesh_protobuf/src/table/encode.rs | 12 ++-- support/mesh/mesh_protobuf/src/time.rs | 36 ++++++------ 15 files changed, 150 insertions(+), 99 deletions(-) diff --git a/support/mesh/mesh_channel/Cargo.toml b/support/mesh/mesh_channel/Cargo.toml index e3ad0c893..65ec9c219 100644 --- a/support/mesh/mesh_channel/Cargo.toml +++ b/support/mesh/mesh_channel/Cargo.toml @@ -8,7 +8,7 @@ rust-version.workspace = true [dependencies] mesh_node.workspace = true -mesh_protobuf.workspace = true +mesh_protobuf = { workspace = true, features = ["std"] } futures-core.workspace = true futures-io.workspace = true diff --git a/support/mesh/mesh_protobuf/Cargo.toml b/support/mesh/mesh_protobuf/Cargo.toml index 29854398e..4b1f585cf 100644 --- a/support/mesh/mesh_protobuf/Cargo.toml +++ b/support/mesh/mesh_protobuf/Cargo.toml @@ -10,6 +10,7 @@ rust-version.workspace = true default = [] prost = ["dep:prost", "dep:prost-types", "dep:prost-build"] socket2 = ["dep:socket2"] +std = [] [dependencies] mesh_derive.workspace = true diff --git a/support/mesh/mesh_protobuf/src/buffer.rs b/support/mesh/mesh_protobuf/src/buffer.rs index 5c0ed6dee..fb34de138 100644 --- a/support/mesh/mesh_protobuf/src/buffer.rs +++ b/support/mesh/mesh_protobuf/src/buffer.rs @@ -6,7 +6,8 @@ //! This is different from `bytes::BufMut` in that the buffer is required to be //! contiguous, which allows for more efficient use with type erasure. -use std::mem::MaybeUninit; +use alloc::vec::Vec; +use core::mem::MaybeUninit; /// Models a partially written, contiguous byte buffer. pub trait Buffer { @@ -66,11 +67,12 @@ impl Buffer for Buf<'_> { } } +#[cfg(feature = "std")] impl Buffer for std::io::Cursor<&mut [u8]> { unsafe fn unwritten(&mut self) -> &mut [MaybeUninit] { let slice = self.get_mut(); // SAFETY: the caller promises not to uninitialize any initialized data. - unsafe { std::slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) } + unsafe { core::slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) } } unsafe fn extend_written(&mut self, len: usize) { @@ -187,6 +189,7 @@ where #[cfg(test)] mod tests { use super::write_with; + use alloc::vec; #[test] #[should_panic] diff --git a/support/mesh/mesh_protobuf/src/encode_with.rs b/support/mesh/mesh_protobuf/src/encode_with.rs index 745b7c489..8cea272b0 100644 --- a/support/mesh/mesh_protobuf/src/encode_with.rs +++ b/support/mesh/mesh_protobuf/src/encode_with.rs @@ -16,8 +16,8 @@ use super::MessageEncode; use super::Result; use crate::inplace; use crate::Downcast; -use std::ops::Deref; -use std::ops::DerefMut; +use core::ops::Deref; +use core::ops::DerefMut; /// Wrapper type to easily support custom mesh encoding. /// @@ -72,7 +72,7 @@ impl> EncodeAs { } fn encode(&mut self) -> &mut U { - match std::mem::replace(&mut self.0, Inner::Invalid) { + match core::mem::replace(&mut self.0, Inner::Invalid) { Inner::Unencoded(t) => { self.0 = Inner::Encoded(t.into()); } diff --git a/support/mesh/mesh_protobuf/src/encoding.rs b/support/mesh/mesh_protobuf/src/encoding.rs index c038d734a..d3ef3e961 100644 --- a/support/mesh/mesh_protobuf/src/encoding.rs +++ b/support/mesh/mesh_protobuf/src/encoding.rs @@ -39,23 +39,25 @@ use crate::protofile::DescribeMessage; use crate::protofile::FieldType; use crate::protofile::MessageDescription; use crate::Error; -use std::borrow::Cow; -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::convert::Infallible; -use std::marker::PhantomData; -use std::num::NonZeroI16; -use std::num::NonZeroI32; -use std::num::NonZeroI64; -use std::num::NonZeroI8; -use std::num::NonZeroIsize; -use std::num::NonZeroU16; -use std::num::NonZeroU32; -use std::num::NonZeroU64; -use std::num::NonZeroU8; -use std::num::NonZeroUsize; -use std::sync::Arc; -use std::time::Duration; +use alloc::borrow::Cow; +use alloc::boxed::Box; +use alloc::collections::BTreeMap; +use alloc::string::String; +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::convert::Infallible; +use core::marker::PhantomData; +use core::num::NonZeroI16; +use core::num::NonZeroI32; +use core::num::NonZeroI64; +use core::num::NonZeroI8; +use core::num::NonZeroIsize; +use core::num::NonZeroU16; +use core::num::NonZeroU32; +use core::num::NonZeroU64; +use core::num::NonZeroU8; +use core::num::NonZeroUsize; +use core::time::Duration; use thiserror::Error; /// An encoding derived by `mesh_derive` for `T`. @@ -254,7 +256,7 @@ impl FromNumber for char { fn from_u64(v: u64) -> Result { v.try_into() .ok() - .and_then(std::char::from_u32) + .and_then(core::char::from_u32) .ok_or_else(|| DecodeError::InvalidUtf32.into()) } @@ -825,7 +827,7 @@ impl, R> FieldEncode for StringField { impl<'a, T: From<&'a str> + Default, R> FieldDecode<'a, T, R> for StringField { fn read_field(item: &mut InplaceOption<'_, T>, reader: FieldReader<'a, '_, R>) -> Result<()> { item.set( - std::str::from_utf8(reader.bytes()?) + core::str::from_utf8(reader.bytes()?) .map_err(DecodeError::InvalidUtf8)? .into(), ); @@ -862,7 +864,7 @@ impl<'a, R> FieldDecode<'a, Cow<'a, str>, R> for BorrowedCowField { reader: FieldReader<'a, '_, R>, ) -> Result<()> { item.set(Cow::Borrowed( - std::str::from_utf8(reader.bytes()?).map_err(DecodeError::InvalidUtf8)?, + core::str::from_utf8(reader.bytes()?).map_err(DecodeError::InvalidUtf8)?, )); Ok(()) } @@ -930,7 +932,7 @@ impl<'a, 'b, R> FieldDecode<'a, Cow<'b, str>, R> for OwningCowField { reader: FieldReader<'a, '_, R>, ) -> Result<()> { item.set(Cow::Owned( - std::str::from_utf8(reader.bytes()?) + core::str::from_utf8(reader.bytes()?) .map_err(DecodeError::InvalidUtf8)? .into(), )); @@ -1674,7 +1676,8 @@ impl DefaultEncoding for Vec { impl Downcast> for Vec where T: Downcast {} -impl DefaultEncoding for HashMap { +#[cfg(feature = "std")] +impl DefaultEncoding for std::collections::HashMap { type Encoding = MapField; } @@ -1796,7 +1799,7 @@ impl FieldDecode<'_, T, R> for ResourceField where T: From, U: TryFrom, - U::Error: 'static + std::error::Error + Send + Sync, + U::Error: 'static + core::error::Error + Send + Sync, { fn read_field(item: &mut InplaceOption<'_, T>, reader: FieldReader<'_, '_, R>) -> Result<()> { let resource = T::from(reader.resource()?.try_into().map_err(Error::new)?); @@ -1822,7 +1825,7 @@ macro_rules! os_resource { }; } -#[cfg(windows)] +#[cfg(all(feature = "std", windows))] mod windows { use crate::os_resource; use std::os::windows::prelude::*; @@ -1839,7 +1842,7 @@ mod windows { os_resource!(socket2::Socket, OwnedSocket); } -#[cfg(unix)] +#[cfg(all(feature = "std", unix))] mod unix { use crate::os_resource; use std::os::unix::prelude::*; diff --git a/support/mesh/mesh_protobuf/src/inplace.rs b/support/mesh/mesh_protobuf/src/inplace.rs index 982b4aec1..44480f9c1 100644 --- a/support/mesh/mesh_protobuf/src/inplace.rs +++ b/support/mesh/mesh_protobuf/src/inplace.rs @@ -3,8 +3,9 @@ //! Provides an `Option`-like type for constructing values in place. -use std::mem::MaybeUninit; -use std::sync::Arc; +use alloc::boxed::Box; +use alloc::sync::Arc; +use core::mem::MaybeUninit; /// A type with methods like `Option` but that operates on a mutable reference /// to possibly-initialized data. @@ -51,7 +52,7 @@ impl<'a, T> InplaceOption<'a, T> { self.init = false; // SAFETY: val is initialized unsafe { - let val = std::ptr::read(&*self.val); + let val = core::ptr::read(&*self.val); Some(val.assume_init()) } } else { @@ -227,12 +228,12 @@ macro_rules! inplace { let mut $v; let mut $v = match opt { Some(v) => { - $v = std::mem::MaybeUninit::new(v); + $v = core::mem::MaybeUninit::new(v); // SAFETY: We just initialized the value. unsafe { $crate::inplace::InplaceOption::new_init_unchecked(&mut $v) } } None => { - $v = std::mem::MaybeUninit::uninit(); + $v = core::mem::MaybeUninit::uninit(); $crate::inplace::InplaceOption::uninit(&mut $v) } }; @@ -243,7 +244,7 @@ macro_rules! inplace { #[macro_export] macro_rules! inplace_some { ($v:ident) => { - let mut $v = std::mem::MaybeUninit::new($v); + let mut $v = core::mem::MaybeUninit::new($v); #[allow(unused_mut)] // SAFETY: We just initialized the value. let mut $v = unsafe { $crate::inplace::InplaceOption::new_init_unchecked(&mut $v) }; @@ -254,12 +255,12 @@ macro_rules! inplace_some { #[macro_export] macro_rules! inplace_none { ($v:ident) => { - let mut $v = std::mem::MaybeUninit::uninit(); + let mut $v = core::mem::MaybeUninit::uninit(); #[allow(unused_mut)] let mut $v = $crate::inplace::InplaceOption::uninit(&mut $v); }; ($v:ident : $t:ty) => { - let mut $v = std::mem::MaybeUninit::<$t>::uninit(); + let mut $v = core::mem::MaybeUninit::<$t>::uninit(); #[allow(unused_mut)] let mut $v = $crate::inplace::InplaceOption::uninit(&mut $v); }; @@ -267,7 +268,10 @@ macro_rules! inplace_none { #[cfg(test)] mod tests { - use std::sync::Arc; + use alloc::boxed::Box; + use alloc::string::String; + use alloc::string::ToString; + use alloc::sync::Arc; #[test] fn test_inplace_some() { diff --git a/support/mesh/mesh_protobuf/src/lib.rs b/support/mesh/mesh_protobuf/src/lib.rs index f9119f788..22c33c3a9 100644 --- a/support/mesh/mesh_protobuf/src/lib.rs +++ b/support/mesh/mesh_protobuf/src/lib.rs @@ -20,8 +20,15 @@ #![warn(missing_docs)] // UNSAFETY: Serialization and deserialization of structs directly. #![allow(unsafe_code)] +#![warn(clippy::std_instead_of_alloc)] +#![warn(clippy::std_instead_of_core)] +#![warn(clippy::alloc_instead_of_core)] +#![no_std] +extern crate alloc; extern crate self as mesh_protobuf; +#[cfg(feature = "std")] +extern crate std; pub mod buffer; mod encode_with; @@ -43,14 +50,16 @@ pub use time::Timestamp; use self::table::decode::DecoderEntry; use self::table::encode::EncoderEntry; +use alloc::boxed::Box; +use alloc::fmt; +use alloc::vec::Vec; +use core::cell::RefCell; +use core::mem::MaybeUninit; +use core::num::Wrapping; use inplace::InplaceOption; use protofile::DescribeMessage; use protofile::MessageDescription; use protofile::TypeUrl; -use std::cell::RefCell; -use std::fmt; -use std::mem::MaybeUninit; -use std::num::Wrapping; /// Associates the default encoder/decoder type for converting an object to/from /// protobuf format. @@ -437,7 +446,7 @@ pub struct Error(Box); #[derive(Debug)] struct ErrorInner { types: Vec<&'static str>, - err: Box, + err: Box, } /// The cause of a decoding error. @@ -483,7 +492,7 @@ enum DecodeError { #[error("wrong buffer size for u128")] BadU128, #[error("invalid UTF-8 string")] - InvalidUtf8(#[source] std::str::Utf8Error), + InvalidUtf8(#[source] core::str::Utf8Error), #[error("missing required field")] MissingRequiredField, #[error("wrong packed array length")] @@ -497,7 +506,7 @@ enum DecodeError { impl Error { /// Creates a new error. - pub fn new(error: impl Into>) -> Self { + pub fn new(error: impl Into>) -> Self { Self(Box::new(ErrorInner { types: Vec::new(), err: error.into(), @@ -506,7 +515,7 @@ impl Error { /// Returns a new error with an additional type context added. pub fn typed(mut self) -> Self { - self.0.types.push(std::any::type_name::()); + self.0.types.push(core::any::type_name::()); self } } @@ -534,8 +543,8 @@ impl fmt::Display for Error { } } -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { +impl core::error::Error for Error { + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { Some(self.0.err.as_ref()) } } @@ -553,10 +562,12 @@ impl ResultExt for Result { } /// A decoding result. -pub type Result = std::result::Result; +pub type Result = core::result::Result; #[cfg(test)] mod tests { + extern crate std; + use super::encode; use super::SerializedMessage; use crate::decode; @@ -567,19 +578,21 @@ mod tests { use crate::FieldDecode; use crate::FieldEncode; use crate::NoResources; + use alloc::borrow::Cow; + use alloc::collections::BTreeMap; + use alloc::vec; + use core::convert::Infallible; + use core::error::Error; + use core::num::NonZeroU32; + use core::time::Duration; use mesh_derive::Protobuf; - use std::borrow::Cow; - use std::collections::BTreeMap; - use std::collections::HashMap; - use std::convert::Infallible; - use std::error::Error; - use std::num::NonZeroU32; - use std::time::Duration; + use std::prelude::rust_2021::*; + use std::println; #[track_caller] fn assert_roundtrips(t: T) where - T: crate::DefaultEncoding + Clone + Eq + std::fmt::Debug, + T: crate::DefaultEncoding + Clone + Eq + core::fmt::Debug, T::Encoding: crate::MessageEncode + for<'a> crate::MessageDecode<'a, T, NoResources>, { @@ -593,7 +606,7 @@ mod tests { #[track_caller] fn assert_field_roundtrips(t: T) where - T: crate::DefaultEncoding + Clone + Eq + std::fmt::Debug, + T: crate::DefaultEncoding + Clone + Eq + core::fmt::Debug, T::Encoding: FieldEncode + for<'a> FieldDecode<'a, T, NoResources>, { assert_roundtrips((t,)); @@ -617,7 +630,8 @@ mod tests { assert_field_roundtrips(Some(Some(true))); assert_field_roundtrips(Some(Option::::None)); assert_field_roundtrips(vec![None, Some(true), None]); - assert_field_roundtrips(HashMap::from_iter([(5u32, 6u32), (4, 2)])); + #[cfg(feature = "std")] + assert_field_roundtrips(std::collections::HashMap::from_iter([(5u32, 6u32), (4, 2)])); assert_field_roundtrips(BTreeMap::from_iter([ ("hi".to_owned(), 6u32), ("hmm".to_owned(), 2), diff --git a/support/mesh/mesh_protobuf/src/message.rs b/support/mesh/mesh_protobuf/src/message.rs index 9259839be..ac511b920 100644 --- a/support/mesh/mesh_protobuf/src/message.rs +++ b/support/mesh/mesh_protobuf/src/message.rs @@ -20,6 +20,9 @@ use crate::Error; use crate::MessageDecode; use crate::MessageEncode; use crate::Protobuf; +use alloc::string::String; +use alloc::string::ToString; +use alloc::vec::Vec; use thiserror::Error; /// An opaque protobuf message. @@ -130,10 +133,13 @@ impl ProtobufAny { #[cfg(test)] mod tests { + extern crate std; + use crate::encode; use crate::message::ProtobufAny; use crate::message::ProtobufMessage; use crate::Protobuf; + use std::println; #[test] fn test_message() { diff --git a/support/mesh/mesh_protobuf/src/prost.rs b/support/mesh/mesh_protobuf/src/prost.rs index c3dfcdbe6..f29fd07cb 100644 --- a/support/mesh/mesh_protobuf/src/prost.rs +++ b/support/mesh/mesh_protobuf/src/prost.rs @@ -9,6 +9,7 @@ use super::MessageDecode; use super::MessageEncode; use super::Result; use crate::Error; +use alloc::vec::Vec; /// Encoding for using Prost messages as Mesh messages. pub struct ProstMessage; @@ -44,6 +45,7 @@ impl MessageDecode<'_, T, R> for ProstMessage { #[cfg(test)] mod tests { use crate::SerializedMessage; + use alloc::string::ToString; mod items { // Crates used by generated code. Reference them explicitly to ensure that diff --git a/support/mesh/mesh_protobuf/src/protobuf.rs b/support/mesh/mesh_protobuf/src/protobuf.rs index 3c1d849d5..6b7f013d7 100644 --- a/support/mesh/mesh_protobuf/src/protobuf.rs +++ b/support/mesh/mesh_protobuf/src/protobuf.rs @@ -13,8 +13,10 @@ use super::MessageEncode; use super::RefCell; use super::Result; use crate::DefaultEncoding; -use std::marker::PhantomData; -use std::ops::Range; +use alloc::vec; +use alloc::vec::Vec; +use core::marker::PhantomData; +use core::ops::Range; /// Writes a variable-length integer, as defined in the protobuf specification. fn write_varint(v: &mut Buf<'_>, mut n: u64) { @@ -116,7 +118,7 @@ impl<'a, R> DecodeState<'a, R> { struct EncodeState<'a, R> { data: Buf<'a>, - message_sizes: std::slice::Iter<'a, MessageSize>, + message_sizes: core::slice::Iter<'a, MessageSize>, resources: &'a mut Vec, field_number: u32, in_sequence: bool, @@ -366,7 +368,7 @@ impl<'a> FieldSizer<'a> { let index = self.state.message_sizes.len(); self.state.message_sizes.push(MessageSize::default()); PreviousSizeParams { - index: std::mem::replace(&mut self.state.index, index) as u32, + index: core::mem::replace(&mut self.state.index, index) as u32, tag_size: self.state.tag_size, in_sequence: self.state.in_sequence, } @@ -374,7 +376,7 @@ impl<'a> FieldSizer<'a> { fn set_cached_message_size(&mut self, prev: PreviousSizeParams) { let size = self.state.message_sizes[self.state.index]; - let index = std::mem::replace(&mut self.state.index, prev.index as usize); + let index = core::mem::replace(&mut self.state.index, prev.index as usize); let parent_size = &mut self.state.message_sizes[self.state.index]; let mut len = varint_size(size.len as u64) + size.len; if size.num_resources > 0 { @@ -831,7 +833,7 @@ pub struct PackedReader<'a> { impl<'a> PackedReader<'a> { /// Reads the remaining bytes. pub fn bytes(&mut self) -> &'a [u8] { - std::mem::take(&mut self.data) + core::mem::take(&mut self.data) } /// Reads a varint. @@ -970,8 +972,11 @@ pub fn decode_with<'a, E: MessageDecode<'a, T, R>, T, R>( #[cfg(test)] mod tests { + extern crate std; + use super::*; use crate::buffer; + use std::eprintln; #[test] fn test_zigzag() { diff --git a/support/mesh/mesh_protobuf/src/protofile/mod.rs b/support/mesh/mesh_protobuf/src/protofile/mod.rs index 5fcbd1a8e..0e89e6540 100644 --- a/support/mesh/mesh_protobuf/src/protofile/mod.rs +++ b/support/mesh/mesh_protobuf/src/protofile/mod.rs @@ -7,10 +7,11 @@ mod writer; +#[cfg(feature = "std")] pub use writer::DescriptorWriter; use crate::DefaultEncoding; -use std::fmt::Display; +use core::fmt::Display; /// A trait for a self-describing protobuf message field. pub trait DescribeField { @@ -66,7 +67,7 @@ impl TypeUrl<'_> { } impl Display for TypeUrl<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "type.googleapis.com/{}.{}", self.package, self.name) } } diff --git a/support/mesh/mesh_protobuf/src/protofile/writer.rs b/support/mesh/mesh_protobuf/src/protofile/writer.rs index ba777c36a..5ca9ef16d 100644 --- a/support/mesh/mesh_protobuf/src/protofile/writer.rs +++ b/support/mesh/mesh_protobuf/src/protofile/writer.rs @@ -3,6 +3,8 @@ //! Code to write .proto files from descriptors. +#![cfg(feature = "std")] + use super::FieldDescriptor; use super::FieldType; use super::MessageDescriptor; @@ -11,8 +13,12 @@ use super::TopLevelDescriptor; use crate::protofile::FieldKind; use crate::protofile::MessageDescription; use crate::protofile::SequenceType; +use alloc::borrow::Cow; +use alloc::boxed::Box; +use alloc::format; +use alloc::string::String; +use alloc::vec::Vec; use heck::ToUpperCamelCase; -use std::borrow::Cow; use std::collections::HashSet; use std::io; use std::io::Write; @@ -470,9 +476,12 @@ mod tests { use super::DescriptorWriter; use crate::protofile::message_description; use crate::Protobuf; - use std::cell::RefCell; + use alloc::string::String; + use alloc::vec::Vec; + use core::cell::RefCell; use std::collections::HashMap; use std::io::Write; + use std::println; /// Comment on this guy. #[derive(Protobuf)] diff --git a/support/mesh/mesh_protobuf/src/table/decode.rs b/support/mesh/mesh_protobuf/src/table/decode.rs index 39b4ee149..763589d51 100644 --- a/support/mesh/mesh_protobuf/src/table/decode.rs +++ b/support/mesh/mesh_protobuf/src/table/decode.rs @@ -11,9 +11,10 @@ use crate::protobuf::MessageReader; use crate::Error; use crate::FieldDecode; use crate::MessageDecode; +use alloc::slice; +use alloc::vec; use core::marker::PhantomData; -use std::mem::MaybeUninit; -use std::slice; +use core::mem::MaybeUninit; /// Calls `f` on `item`, splitting the pointer and initialized flag out. /// @@ -404,12 +405,12 @@ impl<'a, T, R> DecoderEntry<'a, T, R> { pub(crate) const fn custom>() -> Self { Self( ErasedDecoderEntry( - std::ptr::from_ref( + core::ptr::from_ref( const { &StaticDecoderVtable { read_fn: read_field_dyn::, default_fn: default_field_dyn::, - drop_fn: if std::mem::needs_drop::() { + drop_fn: if core::mem::needs_drop::() { Some(drop_field_dyn::) } else { None @@ -429,7 +430,7 @@ impl<'a, T, R> DecoderEntry<'a, T, R> { { Self( ErasedDecoderEntry( - std::ptr::from_ref( + core::ptr::from_ref( const { &DecoderTable { count: T::NUMBERS.len(), diff --git a/support/mesh/mesh_protobuf/src/table/encode.rs b/support/mesh/mesh_protobuf/src/table/encode.rs index 1e71cccb3..8dc04199f 100644 --- a/support/mesh/mesh_protobuf/src/table/encode.rs +++ b/support/mesh/mesh_protobuf/src/table/encode.rs @@ -11,9 +11,9 @@ use crate::protobuf::MessageSizer; use crate::protobuf::MessageWriter; use crate::FieldEncode; use crate::MessageEncode; +use alloc::slice; use core::marker::PhantomData; -use std::mem::MaybeUninit; -use std::slice; +use core::mem::MaybeUninit; impl MessageEncode for TableEncoder where @@ -42,7 +42,7 @@ where T::NUMBERS, T::ENCODERS, T::OFFSETS, - std::ptr::from_mut(item).cast::(), + core::ptr::from_mut(item).cast::(), sizer, ); } @@ -80,7 +80,7 @@ where T::NUMBERS, T::ENCODERS, T::OFFSETS, - std::ptr::from_mut(item).cast::(), + core::ptr::from_mut(item).cast::(), sizer, ); } @@ -367,7 +367,7 @@ impl EncoderEntry { pub(crate) const fn custom>() -> Self { Self( ErasedEncoderEntry( - std::ptr::from_ref( + core::ptr::from_ref( const { &StaticEncoderVtable { write_fn: write_field_dyn::, @@ -388,7 +388,7 @@ impl EncoderEntry { { Self( ErasedEncoderEntry( - std::ptr::from_ref( + core::ptr::from_ref( const { &EncoderTable { count: T::NUMBERS.len(), diff --git a/support/mesh/mesh_protobuf/src/time.rs b/support/mesh/mesh_protobuf/src/time.rs index c95ceb954..f0bc1a403 100644 --- a/support/mesh/mesh_protobuf/src/time.rs +++ b/support/mesh/mesh_protobuf/src/time.rs @@ -16,10 +16,8 @@ use crate::table::TableEncoder; use crate::DecodeError; use crate::MessageDecode; use crate::MessageEncode; +use core::time::Duration; use mesh_protobuf::Protobuf; -use std::time::Duration; -use std::time::SystemTime; -use std::time::UNIX_EPOCH; use thiserror::Error; const NANOS_PER_SEC: u32 = 1_000_000_000; @@ -42,9 +40,10 @@ pub struct Timestamp { pub nanos: i32, } -impl From for Timestamp { - fn from(value: SystemTime) -> Self { - match value.duration_since(UNIX_EPOCH) { +#[cfg(feature = "std")] +impl From for Timestamp { + fn from(value: std::time::SystemTime) -> Self { + match value.duration_since(std::time::UNIX_EPOCH) { Ok(since_epoch) => Self { seconds: since_epoch.as_secs() as i64, nanos: since_epoch.subsec_nanos() as i32, @@ -71,7 +70,8 @@ impl From for Timestamp { #[error("timestamp out of range for system time")] pub struct TimestampOutOfRange; -impl TryFrom for SystemTime { +#[cfg(feature = "std")] +impl TryFrom for std::time::SystemTime { type Error = TimestampOutOfRange; fn try_from(value: Timestamp) -> Result { @@ -79,14 +79,14 @@ impl TryFrom for SystemTime { return Err(TimestampOutOfRange); } if value.seconds >= 0 { - SystemTime::UNIX_EPOCH + std::time::SystemTime::UNIX_EPOCH .checked_add(Duration::new(value.seconds as u64, value.nanos as u32)) } else { let secs = value.seconds.checked_neg().ok_or(TimestampOutOfRange)? as u64; if value.nanos == 0 { - SystemTime::UNIX_EPOCH.checked_sub(Duration::new(secs, 0)) + std::time::SystemTime::UNIX_EPOCH.checked_sub(Duration::new(secs, 0)) } else { - SystemTime::UNIX_EPOCH + std::time::SystemTime::UNIX_EPOCH .checked_sub(Duration::new(secs - 1, NANOS_PER_SEC - value.nanos as u32)) } } @@ -134,25 +134,27 @@ impl MessageDecode<'_, Duration, R> for DurationEncoding { #[cfg(test)] mod tests { - use super::Timestamp; - use std::time::SystemTime; + #[cfg(feature = "std")] #[test] fn test_timestamp_system_time() { + use super::Timestamp; + use std::time::SystemTime; + let check = |st: SystemTime| { let st2 = SystemTime::try_from(Timestamp::from(st)).unwrap(); assert_eq!(st, st2); }; check(SystemTime::now()); - check(SystemTime::now() + std::time::Duration::from_secs(1)); - check(SystemTime::now() - std::time::Duration::from_secs(1)); - check(SystemTime::UNIX_EPOCH - std::time::Duration::from_nanos(1_500_000_000)); - check(SystemTime::UNIX_EPOCH + std::time::Duration::from_nanos(1_500_000_000)); + check(SystemTime::now() + core::time::Duration::from_secs(1)); + check(SystemTime::now() - core::time::Duration::from_secs(1)); + check(SystemTime::UNIX_EPOCH - core::time::Duration::from_nanos(1_500_000_000)); + check(SystemTime::UNIX_EPOCH + core::time::Duration::from_nanos(1_500_000_000)); assert_eq!( Timestamp::from( - SystemTime::UNIX_EPOCH - std::time::Duration::from_nanos(1_500_000_000) + SystemTime::UNIX_EPOCH - core::time::Duration::from_nanos(1_500_000_000) ), Timestamp { seconds: -2,