schematic/validate/
extends.rs1use crate::config::{ExtendsFrom, Path, PathSegment, ValidateError, ValidateResult};
2use crate::helpers::*;
3
4pub fn extends_string<D, C>(
6 value: &str,
7 _data: &D,
8 _context: &C,
9 _finalize: bool,
10) -> ValidateResult {
11 let is_file = is_file_like(value);
12 let is_url = is_url_like(value);
13
14 if !is_url && !is_file {
15 return Err(ValidateError::new(
16 "only file paths and URLs can be extended",
17 ));
18 }
19
20 if !value.is_empty() && !is_source_format(value) {
21 return Err(ValidateError::new(
22 "invalid file format, try a supported extension",
23 ));
24 }
25
26 if is_url && !is_secure_url(value) {
27 return Err(ValidateError::new("only secure URLs can be extended"));
28 }
29
30 Ok(())
31}
32
33pub fn extends_list<D, C>(
35 values: &[String],
36 data: &D,
37 context: &C,
38 finalize: bool,
39) -> ValidateResult {
40 for (i, value) in values.iter().enumerate() {
41 if let Err(mut error) = extends_string(value, data, context, finalize) {
42 error.path = Path::new(vec![PathSegment::Index(i)]);
43
44 return Err(error);
45 }
46 }
47
48 Ok(())
49}
50
51pub fn extends_from<D, C>(
53 value: &ExtendsFrom,
54 data: &D,
55 context: &C,
56 finalize: bool,
57) -> ValidateResult {
58 match value {
59 ExtendsFrom::String(string) => extends_string(string, data, context, finalize)?,
60 ExtendsFrom::List(list) => extends_list(list, data, context, finalize)?,
61 };
62
63 Ok(())
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn string_valid() {
72 assert!(extends_string("file.yml", &(), &(), false).is_ok());
73 assert!(extends_string("./file.json", &(), &(), false).is_ok());
74 assert!(extends_string("../file.yaml", &(), &(), false).is_ok());
75 assert!(extends_string("/nested/file.toml", &(), &(), false).is_ok());
76 assert!(extends_string("https://domain.com/file.yml", &(), &(), false).is_ok());
77 assert!(extends_string("https://domain.com/nested/file.toml", &(), &(), false).is_ok());
78 assert!(
79 extends_string(
80 "https://domain.com/nested/file.toml?query=string",
81 &(),
82 &(),
83 false
84 )
85 .is_ok()
86 );
87 }
88
89 #[test]
90 fn string_invalid() {
91 assert!(extends_string("file.exe", &(), &(), false).is_err());
93 assert!(extends_string("https://domain.com/nested/file.exe", &(), &(), false).is_err());
94 assert!(
95 extends_string(
96 "https://domain.com/nested/file.exe?query=string",
97 &(),
98 &(),
99 false
100 )
101 .is_err()
102 );
103
104 assert!(extends_string("http://domain.com/nested/file.json", &(), &(), false).is_err());
106 }
107}