From 0d63ac48b0a0bd85feb0351cbb87f9631bd19f47 Mon Sep 17 00:00:00 2001 From: David Edey Date: Wed, 25 Sep 2024 22:57:10 +0100 Subject: [PATCH] tweak: Move some code around --- radix-common/src/data/scrypto/definitions.rs | 1 + sbor/src/lib.rs | 1 + sbor/src/traversal/mod.rs | 2 + .../{untyped => }/traversal_traits.rs | 80 +++++++++++++++++++ sbor/src/traversal/typed/typed_traverser.rs | 66 +++++++++++++-- sbor/src/traversal/untyped/mod.rs | 2 - 6 files changed, 145 insertions(+), 7 deletions(-) rename sbor/src/traversal/{untyped => }/traversal_traits.rs (59%) diff --git a/radix-common/src/data/scrypto/definitions.rs b/radix-common/src/data/scrypto/definitions.rs index 25c5ffb23b0..5367c577149 100644 --- a/radix-common/src/data/scrypto/definitions.rs +++ b/radix-common/src/data/scrypto/definitions.rs @@ -9,6 +9,7 @@ pub type ScryptoEncoder<'a> = VecEncoder<'a, ScryptoCustomValueKind>; pub type ScryptoDecoder<'a> = VecDecoder<'a, ScryptoCustomValueKind>; #[allow(deprecated)] pub type ScryptoTraverser<'a> = VecTraverser<'a, ScryptoCustomTraversal>; +pub type ScryptoUntypedTraverser<'a> = UntypedTraverser<'a, ScryptoCustomTraversal>; pub type ScryptoValueKind = ValueKind; pub type ScryptoValue = Value; // ScryptoRawValue and friends are defined in custom_payload_wrappers.rs diff --git a/sbor/src/lib.rs b/sbor/src/lib.rs index 5f16fae30a8..0dcd3a2908c 100644 --- a/sbor/src/lib.rs +++ b/sbor/src/lib.rs @@ -123,6 +123,7 @@ pub(crate) mod internal_prelude { // These are mostly used for more advanced use cases, // so aren't included in the general prelude pub use crate::basic::*; + pub use crate::basic_well_known_types::*; pub use crate::decoder::*; pub use crate::encoder::*; pub use crate::payload_validation::*; diff --git a/sbor/src/traversal/mod.rs b/sbor/src/traversal/mod.rs index e8600c6b97d..13193becfea 100644 --- a/sbor/src/traversal/mod.rs +++ b/sbor/src/traversal/mod.rs @@ -1,7 +1,9 @@ mod path_formatting; +mod traversal_traits; mod typed; mod untyped; pub use path_formatting::*; +pub use traversal_traits::*; pub use typed::*; pub use untyped::*; diff --git a/sbor/src/traversal/untyped/traversal_traits.rs b/sbor/src/traversal/traversal_traits.rs similarity index 59% rename from sbor/src/traversal/untyped/traversal_traits.rs rename to sbor/src/traversal/traversal_traits.rs index b51a2c51d12..337ca2c1721 100644 --- a/sbor/src/traversal/untyped/traversal_traits.rs +++ b/sbor/src/traversal/traversal_traits.rs @@ -109,3 +109,83 @@ pub struct OnError<'t, T: CustomTraversal> { pub error: DecodeError, pub location: Location<'t, T>, } + +// We add this allow so that the placeholder names don't have to start with underscores +#[allow(unused_variables)] +pub trait TypedPayloadVisitor<'de, E: CustomExtension> { + type Output<'t, 's> + where + 's: 't; + + #[inline] + #[must_use] + fn on_container_start<'t, 's>( + &mut self, + details: OnContainerStartTyped<'t, 's, E::CustomTraversal>, + ) -> ControlFlow> { + ControlFlow::Continue(()) + } + + #[inline] + #[must_use] + fn on_terminal_value<'t, 's>( + &mut self, + details: OnTerminalValueTyped<'t, 's, 'de, E::CustomTraversal>, + ) -> ControlFlow> { + ControlFlow::Continue(()) + } + + #[inline] + #[must_use] + fn on_terminal_value_batch<'t, 's>( + &mut self, + details: OnTerminalValueBatchTyped<'t, 's, 'de, E::CustomTraversal>, + ) -> ControlFlow> { + ControlFlow::Continue(()) + } + + #[inline] + #[must_use] + fn on_container_end<'t, 's>( + &mut self, + details: OnContainerEndTyped<'t, 's, E::CustomTraversal>, + ) -> ControlFlow> { + ControlFlow::Continue(()) + } + + #[must_use] + fn on_error<'t, 's>(&mut self, details: OnErrorTyped<'t, 's, E>) -> Self::Output<'t, 's>; + + #[must_use] + fn on_traversal_end<'t, 's>(&mut self, details: OnTraversalEndTyped) -> Self::Output<'t, 's>; +} + +pub struct OnContainerStartTyped<'t, 's, T: CustomTraversal> { + pub local_type_id: LocalTypeId, + pub header: ContainerHeader, + pub location: TypedLocation<'t, 's, T>, +} + +pub struct OnTerminalValueTyped<'t, 's, 'de, T: CustomTraversal> { + pub local_type_id: LocalTypeId, + pub value: TerminalValueRef<'de, T>, + pub location: TypedLocation<'t, 's, T>, +} + +pub struct OnTerminalValueBatchTyped<'t, 's, 'de, T: CustomTraversal> { + pub local_type_id: LocalTypeId, + pub value_batch: TerminalValueBatchRef<'de>, + pub location: TypedLocation<'t, 's, T>, +} + +pub struct OnContainerEndTyped<'t, 's, T: CustomTraversal> { + pub local_type_id: LocalTypeId, + pub location: TypedLocation<'t, 's, T>, +} + +pub struct OnTraversalEndTyped {} + +pub struct OnErrorTyped<'t, 's, E: CustomExtension> { + pub error: TypedTraversalError, + pub location: TypedLocation<'t, 's, E::CustomTraversal>, +} diff --git a/sbor/src/traversal/typed/typed_traverser.rs b/sbor/src/traversal/typed/typed_traverser.rs index 43082cbe2b6..1e4fa8af0ee 100644 --- a/sbor/src/traversal/typed/typed_traverser.rs +++ b/sbor/src/traversal/typed/typed_traverser.rs @@ -1,8 +1,4 @@ -use super::*; -use crate::basic_well_known_types::ANY_TYPE; -use crate::rust::prelude::*; -use crate::traversal::*; -use crate::*; +use crate::internal_prelude::*; pub fn traverse_payload_with_types<'de, 's, E: CustomExtension>( payload: &'de [u8], @@ -142,6 +138,66 @@ impl<'de, 's, E: CustomExtension> TypedTraverser<'de, 's, E> { } } + /// Allows migrating off `next_event` before it's removed + pub fn traverse<'t, V: TypedPayloadVisitor<'de, E>>( + &'t mut self, + visitor: &mut V, + ) -> V::Output<'t, 's> { + match self.traverse_internal(visitor) { + ControlFlow::Continue(_) => unreachable!("Never returns a continue"), + ControlFlow::Break(output) => output, + } + } + + fn traverse_internal<'t, V: TypedPayloadVisitor<'de, E>>( + &'t mut self, + visitor: &mut V, + ) -> ControlFlow> { + loop { + // SAFETY: Work around the current borrow checker, which is sound as per this thread: + // https://users.rust-lang.org/t/mutable-borrow-in-loop-borrow-checker-query/118081/3 + // Unsafe syntax borrowed from here: https://docs.rs/polonius-the-crab/latest/polonius_the_crab/ + // Can remove this once the polonius borrow checker hits stable + let fixed_self: &mut TypedTraverser<'de, 's, E> = unsafe { &mut *(self as *mut _) }; + let TypedLocatedTraversalEvent { location, event } = fixed_self.next_event(); + match event { + TypedTraversalEvent::ContainerStart(local_type_id, header) => { + visitor.on_container_start(OnContainerStartTyped { + local_type_id, + header, + location, + })?; + } + TypedTraversalEvent::ContainerEnd(local_type_id, _header) => { + visitor.on_container_end(OnContainerEndTyped { + local_type_id, + location, + })?; + } + TypedTraversalEvent::TerminalValue(local_type_id, value) => { + visitor.on_terminal_value(OnTerminalValueTyped { + local_type_id, + value, + location, + })?; + } + TypedTraversalEvent::TerminalValueBatch(local_type_id, value_batch) => { + visitor.on_terminal_value_batch(OnTerminalValueBatchTyped { + local_type_id, + value_batch, + location, + })?; + } + TypedTraversalEvent::Error(error) => { + ControlFlow::Break(visitor.on_error(OnErrorTyped { error, location }))?; + } + TypedTraversalEvent::End => { + ControlFlow::Break(visitor.on_traversal_end(OnTraversalEndTyped {}))?; + } + } + } + } + pub fn next_event(&mut self) -> TypedLocatedTraversalEvent<'_, 's, 'de, E> { let (typed_event, location) = Self::next_event_internal(&mut self.traverser, &mut self.state); diff --git a/sbor/src/traversal/untyped/mod.rs b/sbor/src/traversal/untyped/mod.rs index 28610ec0a95..4e5ce4fea8d 100644 --- a/sbor/src/traversal/untyped/mod.rs +++ b/sbor/src/traversal/untyped/mod.rs @@ -2,13 +2,11 @@ use crate::internal_prelude::*; mod event_stream_traverser; mod events; -mod traversal_traits; mod untyped_traverser; mod utility_visitors; pub use event_stream_traverser::*; pub use events::*; -pub use traversal_traits::*; pub use untyped_traverser::*; pub use utility_visitors::*;