dockerfile_parser/instructions/
arg.rs1use std::convert::TryFrom;
4
5use crate::dockerfile_parser::Instruction;
6use crate::SpannedString;
7use crate::error::*;
8use crate::parse_string;
9use crate::parser::{Pair, Rule};
10use crate::splicer::Span;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct ArgInstruction {
17 pub span: Span,
18
19 pub name: SpannedString,
21
22 pub value: Option<SpannedString>,
29}
30
31impl ArgInstruction {
32 pub(crate) fn from_record(record: Pair) -> Result<ArgInstruction> {
33 let span = Span::from_pair(&record);
34 let mut name = None;
35 let mut value = None;
36
37 for field in record.into_inner() {
38 match field.as_rule() {
39 Rule::arg_name => name = Some(parse_string(&field)?),
40 Rule::arg_quoted_value => value = Some(parse_string(&field)?),
41 Rule::arg_value => value = Some(parse_string(&field)?),
42 Rule::comment => continue,
43 _ => return Err(unexpected_token(field))
44 }
45 }
46
47 let name = match name {
48 Some(name) => name,
49 _ => return Err(Error::GenericParseError {
50 message: "arg name is required".into()
51 })
52 };
53
54 Ok(ArgInstruction {
55 span,
56 name,
57 value,
58 })
59 }
60}
61
62impl<'a> TryFrom<&'a Instruction> for &'a ArgInstruction {
63 type Error = Error;
64
65 fn try_from(instruction: &'a Instruction) -> std::result::Result<Self, Self::Error> {
66 if let Instruction::Arg(a) = instruction {
67 Ok(a)
68 } else {
69 Err(Error::ConversionError {
70 from: format!("{:?}", instruction),
71 to: "ArgInstruction".into()
72 })
73 }
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use pretty_assertions::assert_eq;
80
81 use super::*;
82 use crate::Dockerfile;
83 use crate::test_util::*;
84
85 #[test]
86 fn arg_strings() -> Result<()> {
87 assert_eq!(
88 parse_single(r#"arg foo=bar"#, Rule::arg)?,
89 ArgInstruction {
90 span: Span::new(0, 11),
91 name: SpannedString {
92 span: Span::new(4, 7),
93 content: "foo".into(),
94 },
95 value: Some(SpannedString {
96 span: Span::new(8, 11),
97 content: "bar".into(),
98 }),
99 }.into()
100 );
101
102 assert_eq!(
103 parse_single(r#"arg foo="bar""#, Rule::arg)?,
104 ArgInstruction {
105 span: Span::new(0, 13),
106 name: SpannedString {
107 span: Span::new(4, 7),
108 content: "foo".into(),
109 },
110 value: Some(SpannedString {
111 span: Span::new(8, 13),
112 content: "bar".into(),
113 }),
114 }.into()
115 );
116
117 assert_eq!(
118 parse_single(r#"arg foo='bar'"#, Rule::arg)?,
119 ArgInstruction {
120 span: Span::new(0, 13),
121 name: SpannedString {
122 span: Span::new(4, 7),
123 content: "foo".into(),
124 },
125 value: Some(SpannedString {
126 span: Span::new(8, 13),
127 content: "bar".into(),
128 }),
129 }.into()
130 );
131
132 assert!(Dockerfile::parse(r#"arg foo="bar"bar"#).is_err());
133 assert!(Dockerfile::parse(r#"arg foo='bar'bar"#).is_err());
134
135 Ok(())
136 }
137}