@@ -12,7 +12,7 @@ use cargo_metadata::Package;
1212use semver:: { Version , VersionReq } ;
1313use serde:: {
1414 de:: { self , value:: MapAccessDeserializer } ,
15- Deserialize ,
15+ Deserialize , Serialize
1616} ;
1717use serde_json:: from_value;
1818use url:: Url ;
@@ -169,17 +169,17 @@ pub enum Target {
169169 /// [select-world]: https://docs.rs/wit-parser/latest/wit_parser/struct.Resolve.html#method.select_world
170170 world : Option < String > ,
171171 /// The dependencies of the wit document being targeted.
172- dependencies : HashMap < PackageRef , Dependency > ,
172+ dependencies : HashMap < PackageRef , WasmDependency > ,
173173 } ,
174174}
175175
176176impl Target {
177177 /// Gets the dependencies of the target.
178- pub fn dependencies ( & self ) -> Cow < HashMap < PackageRef , Dependency > > {
178+ pub fn dependencies ( & self ) -> Cow < HashMap < PackageRef , WasmDependency > > {
179179 match self {
180180 Self :: Package { name, package, .. } => Cow :: Owned ( HashMap :: from_iter ( [ (
181181 name. clone ( ) ,
182- Dependency :: Package ( package. clone ( ) ) ,
182+ WasmDependency ( Dependency :: Package ( package. clone ( ) ) ) ,
183183 ) ] ) ) ,
184184 Self :: Local { dependencies, .. } => Cow :: Borrowed ( dependencies) ,
185185 }
@@ -271,7 +271,7 @@ impl<'de> Deserialize<'de> for Target {
271271 world : Option < String > ,
272272 registry : Option < String > ,
273273 path : Option < PathBuf > ,
274- dependencies : HashMap < PackageRef , Dependency > ,
274+ dependencies : HashMap < PackageRef , WasmDependency > ,
275275 }
276276
277277 let entry = Entry :: deserialize ( MapAccessDeserializer :: new ( map) ) ?;
@@ -326,6 +326,112 @@ impl<'de> Deserialize<'de> for Target {
326326 }
327327}
328328
329+ #[ derive( Debug , Clone ) ]
330+ pub struct WasmDependency ( pub Dependency ) ;
331+
332+ impl Serialize for WasmDependency {
333+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
334+ where
335+ S : serde:: Serializer ,
336+ {
337+ match & self . 0 {
338+ Dependency :: Package ( package) => {
339+ if package. name . is_none ( ) && package. registry . is_none ( ) {
340+ let version = package. version . to_string ( ) ;
341+ version. trim_start_matches ( '^' ) . serialize ( serializer)
342+ } else {
343+ #[ derive( Serialize ) ]
344+ struct Entry < ' a > {
345+ package : Option < & ' a PackageRef > ,
346+ version : & ' a str ,
347+ registry : Option < & ' a str > ,
348+ }
349+
350+ Entry {
351+ package : package. name . as_ref ( ) ,
352+ version : package. version . to_string ( ) . trim_start_matches ( '^' ) ,
353+ registry : package. registry . as_deref ( ) ,
354+ }
355+ . serialize ( serializer)
356+ }
357+ }
358+ Dependency :: Local ( path) => {
359+ #[ derive( Serialize ) ]
360+ struct Entry < ' a > {
361+ path : & ' a PathBuf ,
362+ }
363+
364+ Entry { path } . serialize ( serializer)
365+ }
366+ }
367+ }
368+ }
369+
370+ impl < ' de > Deserialize < ' de > for WasmDependency {
371+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
372+ where
373+ D : serde:: Deserializer < ' de > ,
374+ {
375+ struct Visitor ;
376+
377+ impl < ' de > de:: Visitor < ' de > for Visitor {
378+ type Value = WasmDependency ;
379+
380+ fn expecting ( & self , formatter : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
381+ write ! ( formatter, "a string or a table" )
382+ }
383+
384+ fn visit_str < E > ( self , s : & str ) -> Result < Self :: Value , E >
385+ where
386+ E : de:: Error ,
387+ {
388+ Ok ( WasmDependency ( Dependency :: Package (
389+ s. parse ( ) . map_err ( de:: Error :: custom) ?,
390+ ) ) )
391+ }
392+
393+ fn visit_map < A > ( self , map : A ) -> Result < Self :: Value , A :: Error >
394+ where
395+ A : de:: MapAccess < ' de > ,
396+ {
397+ #[ derive( Default , Deserialize ) ]
398+ #[ serde( default , deny_unknown_fields) ]
399+ struct Entry {
400+ path : Option < PathBuf > ,
401+ package : Option < PackageRef > ,
402+ version : Option < VersionReq > ,
403+ registry : Option < String > ,
404+ }
405+
406+ let entry = Entry :: deserialize ( MapAccessDeserializer :: new ( map) ) ?;
407+
408+ match ( entry. path , entry. package , entry. version , entry. registry ) {
409+ ( Some ( path) , None , None , None ) => Ok ( WasmDependency ( Dependency :: Local ( path) ) ) ,
410+ ( None , name, Some ( version) , registry) => {
411+ Ok ( WasmDependency ( Dependency :: Package ( RegistryPackage {
412+ name,
413+ version,
414+ registry,
415+ } ) ) )
416+ }
417+ ( Some ( _) , None , Some ( _) , _) => Err ( de:: Error :: custom (
418+ "cannot specify both `path` and `version` fields in a dependency entry" ,
419+ ) ) ,
420+ ( Some ( _) , None , None , Some ( _) ) => Err ( de:: Error :: custom (
421+ "cannot specify both `path` and `registry` fields in a dependency entry" ,
422+ ) ) ,
423+ ( Some ( _) , Some ( _) , _, _) => Err ( de:: Error :: custom (
424+ "cannot specify both `path` and `package` fields in a dependency entry" ,
425+ ) ) ,
426+ ( None , None , _, _) => Err ( de:: Error :: missing_field ( "package" ) ) ,
427+ ( None , Some ( _) , None , _) => Err ( de:: Error :: missing_field ( "version" ) ) ,
428+ }
429+ }
430+ }
431+
432+ deserializer. deserialize_any ( Visitor )
433+ }
434+ }
329435/// Represents the `package.metadata.component` section in `Cargo.toml`.
330436#[ derive( Default , Debug , Clone , Deserialize ) ]
331437#[ serde( default , deny_unknown_fields) ]
@@ -337,7 +443,7 @@ pub struct ComponentSection {
337443 /// The path to the WASI adapter to use.
338444 pub adapter : Option < PathBuf > ,
339445 /// The dependencies of the component.
340- pub dependencies : HashMap < PackageRef , Dependency > ,
446+ pub dependencies : HashMap < PackageRef , WasmDependency > ,
341447 /// The registries to use for the component.
342448 pub registries : HashMap < String , Url > ,
343449 /// The configuration for bindings generation.
@@ -415,14 +521,14 @@ impl ComponentMetadata {
415521 }
416522
417523 for dependency in dependencies. values_mut ( ) {
418- if let Dependency :: Local ( path) = dependency {
524+ if let Dependency :: Local ( path) = & mut dependency. 0 {
419525 * path = manifest_dir. join ( path. as_path ( ) ) ;
420526 }
421527 }
422528 }
423529
424530 for dependency in section. dependencies . values_mut ( ) {
425- if let Dependency :: Local ( path) = dependency {
531+ if let Dependency :: Local ( path) = & mut dependency. 0 {
426532 * path = manifest_dir. join ( path. as_path ( ) ) ;
427533 }
428534 }
0 commit comments