Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-core / src / requirement.rs
3.8 kB 138 lines
1use std::fmt; 2use std::str::FromStr; 3 4use crate::error::Result; 5use crate::io::make_relative; 6use camino::{Utf8Path, Utf8PathBuf}; 7use ecow::EcoString; 8use hexpm::version::Range; 9use serde::de::{self, Deserializer, MapAccess, Visitor}; 10use serde::ser::{Serialize, SerializeMap, Serializer}; 11use serde::Deserialize; 12 13#[derive(Deserialize, Debug, PartialEq, Eq, Clone)] 14#[serde(untagged, remote = "Self")] 15pub enum Requirement { 16 Hex { version: Range }, 17 Path { path: Utf8PathBuf }, 18 Git { git: EcoString }, 19} 20 21impl Requirement { 22 pub fn hex(range: &str) -> Requirement { 23 Requirement::Hex { 24 version: Range::new(range.to_string()), 25 } 26 } 27 28 pub fn path(path: &str) -> Requirement { 29 Requirement::Path { path: path.into() } 30 } 31 32 pub fn git(url: &str) -> Requirement { 33 Requirement::Git { git: url.into() } 34 } 35 36 pub fn to_toml(&self, root_path: &Utf8Path) -> String { 37 match self { 38 Requirement::Hex { version: range } => { 39 format!(r#"{{ version = "{}" }}"#, range) 40 } 41 Requirement::Path { path } => { 42 format!( 43 r#"{{ path = "{}" }}"#, 44 make_relative(root_path, path).as_str().replace('\\', "/") 45 ) 46 } 47 Requirement::Git { git: url } => format!(r#"{{ git = "{}" }}"#, url), 48 } 49 } 50} 51 52// Serialization 53 54impl Serialize for Requirement { 55 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 56 where 57 S: Serializer, 58 { 59 let mut map = serializer.serialize_map(Some(1))?; 60 match self { 61 Requirement::Hex { version: range } => map.serialize_entry("version", range)?, 62 Requirement::Path { path } => map.serialize_entry("path", path)?, 63 Requirement::Git { git: url } => map.serialize_entry("git", url)?, 64 } 65 map.end() 66 } 67} 68 69// Deserialization 70 71#[derive(Debug, Copy, Clone)] 72pub struct Void; 73 74impl FromStr for Requirement { 75 type Err = Void; 76 77 fn from_str(s: &str) -> Result<Self, Self::Err> { 78 Ok(Requirement::hex(s)) 79 } 80} 81 82struct RequirementVisitor; 83 84impl<'de> Visitor<'de> for RequirementVisitor { 85 type Value = Requirement; 86 87 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 88 formatter.write_str("string or map") 89 } 90 91 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> 92 where 93 E: de::Error, 94 { 95 Ok(FromStr::from_str(value).expect("expected string")) 96 } 97 98 fn visit_map<M>(self, visitor: M) -> Result<Self::Value, M::Error> 99 where 100 M: MapAccess<'de>, 101 { 102 Requirement::deserialize(de::value::MapAccessDeserializer::new(visitor)) 103 } 104} 105 106impl<'de> Deserialize<'de> for Requirement { 107 fn deserialize<D>(deserializer: D) -> Result<Requirement, D::Error> 108 where 109 D: Deserializer<'de>, 110 { 111 deserializer.deserialize_any(RequirementVisitor) 112 } 113} 114 115#[cfg(test)] 116mod tests { 117 118 use super::*; 119 use std::collections::HashMap; 120 121 #[test] 122 fn read_requirement() { 123 let toml = r#" 124 short = "~> 0.5" 125 hex = { version = "~> 1.0.0" } 126 local = { path = "/path/to/package" } 127 github = { git = "https://github.com/gleam-lang/otp.git" } 128 "#; 129 let deps: HashMap<String, Requirement> = toml::from_str(toml).unwrap(); 130 assert_eq!(deps["short"], Requirement::hex("~> 0.5")); 131 assert_eq!(deps["hex"], Requirement::hex("~> 1.0.0")); 132 assert_eq!(deps["local"], Requirement::path("/path/to/package")); 133 assert_eq!( 134 deps["github"], 135 Requirement::git("https://github.com/gleam-lang/otp.git") 136 ); 137 } 138}