@@ -3,10 +3,61 @@ use std::collections::{BTreeMap, HashMap};
33
44use rattler_conda_types:: NoArchType ;
55use serde:: { Deserialize , Serialize } ;
6+ use serde_json:: ser:: Formatter ;
67use sha1:: { Digest , Sha1 } ;
78
89use crate :: { normalized_key:: NormalizedKey , recipe:: variable:: Variable } ;
910
11+ /// A formatter that matches Python's json.dumps() format exactly
12+ struct PythonJsonFormatter ;
13+
14+ impl Formatter for PythonJsonFormatter {
15+ fn begin_object < W > ( & mut self , writer : & mut W ) -> std:: io:: Result < ( ) >
16+ where
17+ W : ?Sized + std:: io:: Write ,
18+ {
19+ writer. write_all ( b"{" )
20+ }
21+
22+ fn end_object < W > ( & mut self , writer : & mut W ) -> std:: io:: Result < ( ) >
23+ where
24+ W : ?Sized + std:: io:: Write ,
25+ {
26+ writer. write_all ( b"}" )
27+ }
28+
29+ fn begin_object_key < W > ( & mut self , writer : & mut W , first : bool ) -> std:: io:: Result < ( ) >
30+ where
31+ W : ?Sized + std:: io:: Write ,
32+ {
33+ if !first {
34+ writer. write_all ( b", " ) ?;
35+ }
36+ Ok ( ( ) )
37+ }
38+
39+ fn begin_object_value < W > ( & mut self , writer : & mut W ) -> std:: io:: Result < ( ) >
40+ where
41+ W : ?Sized + std:: io:: Write ,
42+ {
43+ writer. write_all ( b": " )
44+ }
45+
46+ fn begin_string < W > ( & mut self , writer : & mut W ) -> std:: io:: Result < ( ) >
47+ where
48+ W : ?Sized + std:: io:: Write ,
49+ {
50+ writer. write_all ( b"\" " )
51+ }
52+
53+ fn end_string < W > ( & mut self , writer : & mut W ) -> std:: io:: Result < ( ) >
54+ where
55+ W : ?Sized + std:: io:: Write ,
56+ {
57+ writer. write_all ( b"\" " )
58+ }
59+ }
60+
1061/// A hash will be added if all of these are true for any dependency:
1162///
1263/// 1. package is an explicit dependency in build, host, or run deps
@@ -63,8 +114,13 @@ impl HashInput {
63114 map. insert ( key. normalize ( ) , value. to_string ( ) ) ;
64115 }
65116
66- // Use serde_json with default formatting to match Python's json.dumps()
67- let json = serde_json:: to_string ( & map) . expect ( "Failed to serialize input" ) ;
117+ // Configure serde_json to match Python's json.dumps() format
118+ let mut writer = Vec :: new ( ) ;
119+ let mut ser = serde_json:: Serializer :: with_formatter ( & mut writer, PythonJsonFormatter ) ;
120+ map. serialize ( & mut ser) . expect ( "Failed to serialize input" ) ;
121+
122+ // Convert to string, ensuring we match Python's format
123+ let json = String :: from_utf8 ( writer) . expect ( "Invalid UTF-8" ) ;
68124 Self ( json)
69125 }
70126
0 commit comments