1use std::str::FromStr;
2
3use bones_utils::LabeledId;
4use semver::VersionReq;
5use serde::Deserialize;
6
7use crate::prelude::*;
8
9impl FromStr for AssetPackReq {
10 type Err = String;
11 fn from_str(s: &str) -> Result<Self, Self::Err> {
12 if let Some((id, version)) = s.split_once('@') {
13 let id = id.parse::<LabeledId>().map_err(|e| e.to_string())?;
14 let version = version.parse::<VersionReq>().map_err(|e| e.to_string())?;
15 Ok(Self { id, version })
16 } else {
17 let id = s.parse::<LabeledId>().map_err(|e| e.to_string())?;
18 Ok(Self {
19 id,
20 version: VersionReq::STAR,
21 })
22 }
23 }
24}
25
26impl FromStr for SchemaPath {
27 type Err = String;
28 fn from_str(s: &str) -> Result<Self, Self::Err> {
29 if let Some((pack_id, schema)) = s.split_once('/') {
30 let pack = AssetPackReq::from_str(pack_id)?;
31
32 Ok(SchemaPath {
33 pack: Some(pack),
34 name: schema.into(),
35 })
36 } else {
37 Ok(SchemaPath {
38 pack: None,
39 name: s.into(),
40 })
41 }
42 }
43}
44
45impl<'de> Deserialize<'de> for SchemaPath {
46 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
47 where
48 D: serde::Deserializer<'de>,
49 {
50 use serde::de::Error;
51 let s = String::deserialize(deserializer)?;
52 s.parse::<SchemaPath>().map_err(D::Error::custom)
53 }
54}