@@ -10,7 +10,7 @@ pub mod syscall_handler;
1010use std:: { any:: Any , collections:: HashMap } ;
1111
1212use :: syscall_handler:: SyscallHandlerWrapper ;
13- use cairo_lang_casm:: hints:: { Hint , StarknetHint } ;
13+ use cairo_lang_casm:: hints:: { CoreHint , CoreHintBase , Hint , StarknetHint } ;
1414use cairo_vm:: {
1515 hint_processor:: {
1616 builtin_hint_processor:: builtin_hint_processor_definition:: { BuiltinHintProcessor , HintProcessorData } ,
@@ -44,16 +44,18 @@ pub struct CustomHintProcessor {
4444 cairo1_builtin_hint_proc : Cairo1HintProcessor ,
4545 hints : HashMap < String , HintImpl > ,
4646 extensive_hints : HashMap < String , ExtensiveHintImpl > ,
47+ pretty_output : bool ,
4748}
4849
4950impl CustomHintProcessor {
50- pub fn new ( inputs : HDPDryRunInput ) -> Self {
51+ pub fn new ( inputs : HDPDryRunInput , pretty_output : bool ) -> Self {
5152 Self {
5253 inputs,
5354 builtin_hint_proc : BuiltinHintProcessor :: new_empty ( ) ,
5455 cairo1_builtin_hint_proc : Cairo1HintProcessor :: new ( Default :: default ( ) , Default :: default ( ) , true ) ,
5556 hints : Self :: hints ( ) ,
5657 extensive_hints : Self :: extensive_hints ( ) ,
58+ pretty_output,
5759 }
5860 }
5961
@@ -139,6 +141,29 @@ impl HintProcessorLogic for CustomHintProcessor {
139141 . map ( |_| HintExtension :: default ( ) )
140142 } )
141143 } ) ;
144+ } else if self . pretty_output {
145+ if let Hint :: Core ( CoreHintBase :: Core ( CoreHint :: DebugPrint { start, end } ) ) = hint {
146+ let start_ptr = get_ptr_from_res_operand ( vm, start) ?;
147+ let end_ptr = get_ptr_from_res_operand ( vm, end) ?;
148+ let len = ( end_ptr - start_ptr)
149+ . map_err ( |_| HintError :: CustomHint ( "DebugPrint: invalid range" . into ( ) ) ) ?;
150+ if len > 0 {
151+ let felts: Vec < Felt252 > = vm
152+ . get_integer_range ( start_ptr, len) ?
153+ . into_iter ( )
154+ . map ( |f| ( * f. as_ref ( ) ) )
155+ . collect ( ) ;
156+ let text = pretty_debug_text ( & felts) ;
157+ if !text. is_empty ( ) {
158+ println ! ( "{}" , text) ;
159+ }
160+ }
161+ return Ok ( HintExtension :: default ( ) ) ;
162+ }
163+ return self
164+ . cairo1_builtin_hint_proc
165+ . execute ( vm, exec_scopes, hint)
166+ . map ( |_| HintExtension :: default ( ) ) ;
142167 } else {
143168 return self
144169 . cairo1_builtin_hint_proc
@@ -152,3 +177,33 @@ impl HintProcessorLogic for CustomHintProcessor {
152177}
153178
154179impl ResourceTracker for CustomHintProcessor { }
180+
181+ /// Reconstruct a clean debug message from a DebugPrint felt range.
182+ /// Each felt is tried as a Cairo short string (up to 31 ASCII bytes);
183+ /// printable fragments are concatenated into a single line.
184+ fn pretty_debug_text ( felts : & [ Felt252 ] ) -> String {
185+ let mut text = String :: new ( ) ;
186+ for value in felts {
187+ if let Some ( s) = felt_as_short_string ( value) {
188+ text. push_str ( & s) ;
189+ }
190+ }
191+ text
192+ }
193+
194+ /// Decode a Felt252 as a Cairo short string (same logic as cairo-vm's
195+ /// `as_cairo_short_string`). Returns None if any byte is non-ASCII.
196+ fn felt_as_short_string ( value : & Felt252 ) -> Option < String > {
197+ let mut result = String :: new ( ) ;
198+ let mut ended = false ;
199+ for byte in value. to_bytes_be ( ) . into_iter ( ) . skip_while ( |b| * b == 0 ) {
200+ if byte == 0 {
201+ ended = true ;
202+ } else if ended || !byte. is_ascii ( ) {
203+ return None ;
204+ } else {
205+ result. push ( byte as char ) ;
206+ }
207+ }
208+ Some ( result)
209+ }
0 commit comments