1use super::cst::*;
18use super::node::ASTNode;
19use std::fmt;
20
21struct View<'a, T>(&'a ASTNode<Option<T>>);
23impl<'a, T: fmt::Display> fmt::Display for View<'a, T> {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 if let Some(n) = &self.0.as_inner() {
26 if f.alternate() {
27 write!(f, "{:#}", n)
28 } else {
29 write!(f, "{}", n)
30 }
31 } else {
32 write!(f, "[error]")
33 }
34 }
35}
36
37impl fmt::Display for Policies {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 if f.alternate() {
40 let mut ps = self.0.iter();
41 if let Some(p) = ps.next() {
42 write!(f, "{:#}", View(p))?;
43 }
44 for p in ps {
45 write!(f, "\n\n{:#}", View(p))?;
46 }
47 } else {
48 let mut ps = self.0.iter();
49 if let Some(p) = ps.next() {
50 write!(f, "{}", View(p))?;
51 }
52 for p in ps {
53 write!(f, " {}", View(p))?;
54 }
55 }
56 Ok(())
57 }
58}
59impl fmt::Display for Policy {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 for anno in self.annotations.iter() {
63 if f.alternate() {
64 writeln!(f, "{:#}", View(anno))?;
66 } else {
67 write!(f, "{} ", View(anno))?;
68 }
69 }
70 if f.alternate() {
72 write!(f, "{:#}(", View(&self.effect))?;
73 let mut vars = self.variables.iter();
74 if let Some(v) = vars.next() {
76 write!(f, "\n {:#}", View(v))?;
78 for v in vars {
80 write!(f, ",\n {:#}", View(v))?;
81 }
82 write!(f, "\n)")?;
84 } else {
85 write!(f, ")")?;
87 }
88 for c in self.conds.iter() {
90 write!(f, "\n{:#}", View(c))?;
91 }
92 write!(f, ";")?;
93 } else {
94 write!(f, "{}(", View(&self.effect))?;
95 let mut vars = self.variables.iter();
96 if let Some(v) = vars.next() {
98 write!(f, "{}", View(v))?;
100 for v in vars {
102 write!(f, ", {}", View(v))?;
103 }
104 }
105 write!(f, ")")?;
106
107 for c in self.conds.iter() {
108 write!(f, " {}", View(c))?;
109 }
110 write!(f, ";")?;
111 }
112 Ok(())
113 }
114}
115
116impl fmt::Display for Annotation {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(f, "@{}({})", View(&self.key), View(&self.value))
119 }
120}
121
122impl fmt::Display for VariableDef {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 write!(f, "{}", View(&self.variable))?;
125 if let Some(name) = &self.name {
126 write!(f, ": {}", View(name))?;
127 }
128 if let Some((op, expr)) = &self.ineq {
129 write!(f, " {} {}", op, View(expr))?;
130 }
131 Ok(())
132 }
133}
134impl fmt::Display for Cond {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 if self.expr.is_none() {
137 write!(f, "{} {{ }}", View(&self.cond))
138 } else if f.alternate() {
139 write!(
140 f,
141 "{} {{\n {:#}\n}}",
142 View(&self.cond),
143 View(self.expr.as_ref().unwrap())
144 )
145 } else {
146 write!(
147 f,
148 "{} {{{}}}",
149 View(&self.cond),
150 View(self.expr.as_ref().unwrap())
151 )
152 }
153 }
154}
155impl fmt::Display for Expr {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 let expr = &*self.expr;
158 match expr {
159 ExprData::Or(or) => write!(f, "{}", View(or)),
160 ExprData::If(ex1, ex2, ex3) => {
161 write!(f, "if {} then {} else {}", View(ex1), View(ex2), View(ex3))
162 }
163 }
164 }
165}
166impl fmt::Display for Or {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 write!(f, "{}", View(&self.initial))?;
169 for or in self.extended.iter() {
170 write!(f, " || {}", View(or))?;
171 }
172 Ok(())
173 }
174}
175impl fmt::Display for And {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 write!(f, "{}", View(&self.initial))?;
178 for and in self.extended.iter() {
179 write!(f, " && {}", View(and))?;
180 }
181 Ok(())
182 }
183}
184impl fmt::Display for Relation {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 match self {
187 Relation::Common { initial, extended } => {
188 write!(f, "{}", View(initial))?;
189 for (op, add) in extended.iter() {
190 write!(f, " {} {}", op, View(add))?;
191 }
192 }
193 Relation::Has { target, field } => {
194 write!(f, "{} has {}", View(target), View(field))?;
195 }
196 Relation::Like { target, pattern } => {
197 write!(f, "{} like {}", View(target), View(pattern))?;
198 }
199 }
200 Ok(())
201 }
202}
203impl fmt::Display for RelOp {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 match self {
206 RelOp::Less => write!(f, "<"),
207 RelOp::LessEq => write!(f, "<="),
208 RelOp::GreaterEq => write!(f, ">="),
209 RelOp::Greater => write!(f, ">"),
210 RelOp::NotEq => write!(f, "!="),
211 RelOp::Eq => write!(f, "=="),
212 RelOp::In => write!(f, "in"),
213 }
214 }
215}
216impl fmt::Display for AddOp {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 match self {
219 AddOp::Plus => write!(f, "+"),
220 AddOp::Minus => write!(f, "-"),
221 }
222 }
223}
224impl fmt::Display for MultOp {
225 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226 match self {
227 MultOp::Times => write!(f, "*"),
228 MultOp::Divide => write!(f, "/"),
229 MultOp::Mod => write!(f, "%"),
230 }
231 }
232}
233impl fmt::Display for NegOp {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 match self {
236 NegOp::Bang(cnt) => {
237 for _ in 0..*cnt {
238 write!(f, "!")?;
239 }
240 }
241 NegOp::OverBang => write!(f, "!!!!!!!!!!")?,
243 NegOp::Dash(cnt) => {
244 for _ in 0..*cnt {
245 write!(f, "-")?;
246 }
247 }
248 NegOp::OverDash => write!(f, "----------")?,
250 }
251 Ok(())
252 }
253}
254impl fmt::Display for Add {
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 write!(f, "{}", View(&self.initial))?;
257 for (op, mult) in self.extended.iter() {
258 write!(f, " {} {}", op, View(mult))?;
259 }
260 Ok(())
261 }
262}
263impl fmt::Display for Mult {
264 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 write!(f, "{}", View(&self.initial))?;
266 for (op, un) in self.extended.iter() {
267 write!(f, " {} {}", op, View(un))?;
268 }
269 Ok(())
270 }
271}
272impl fmt::Display for Unary {
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 if let Some(op) = &self.op {
275 write!(f, "{}{}", op, View(&self.item))
276 } else {
277 write!(f, "{}", View(&self.item))
278 }
279 }
280}
281impl fmt::Display for Member {
282 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
283 write!(f, "{}", View(&self.item))?;
284 for m in self.access.iter() {
285 write!(f, "{}", View(m))?;
286 }
287 Ok(())
288 }
289}
290impl fmt::Display for MemAccess {
291 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292 match self {
293 MemAccess::Field(id) => write!(f, ".{}", View(id))?,
294 MemAccess::Call(exprs) => {
295 write!(f, "(")?;
296 let mut es = exprs.iter();
297 if let Some(ex) = es.next() {
298 write!(f, "{}", View(ex))?;
299 }
300 for e in es {
301 write!(f, ", {}", View(e))?;
302 }
303 write!(f, ")")?;
304 }
305 MemAccess::Index(e) => write!(f, "[{}]", View(e))?,
306 }
307 Ok(())
308 }
309}
310impl fmt::Display for Primary {
311 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
312 match self {
313 Primary::Literal(lit) => write!(f, "{}", View(lit)),
314 Primary::Ref(rf) => write!(f, "{}", View(rf)),
315 Primary::Name(nm) => write!(f, "{}", View(nm)),
316 Primary::Expr(expr) => write!(f, "({})", View(expr)),
317 Primary::EList(exs) => {
318 write!(f, "[")?;
319 let mut es = exs.iter();
320 if let Some(ex) = es.next() {
321 write!(f, "{}", View(ex))?;
322 }
323 for e in es {
324 write!(f, ", {}", View(e))?;
325 }
326 write!(f, "]")
327 }
328 Primary::RInits(mis) => {
329 write!(f, "{{")?;
330 let mut ms = mis.iter();
331 if let Some(i) = ms.next() {
332 write!(f, "{}", View(i))?;
333 }
334 for i in ms {
335 write!(f, ", {}", View(i))?;
336 }
337 write!(f, "}}")
338 }
339 Primary::Slot(s) => write!(f, "{}", View(s)),
340 }
341 }
342}
343impl fmt::Display for Name {
344 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345 for n in self.path.iter() {
346 write!(f, "{}::", View(n))?;
347 }
348 write!(f, "{}", View(&self.name))?;
349 Ok(())
350 }
351}
352impl fmt::Display for Ref {
353 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
354 match self {
355 Ref::Uid { path, eid } => {
356 write!(f, "{}::{}", View(path), View(eid))?;
357 }
358 Ref::Ref { path, rinits } => {
359 write!(f, "{}::{{", View(path))?;
360 let mut ris = rinits.iter();
361 if let Some(r) = ris.next() {
362 write!(f, "{}", View(r))?;
363 }
364 for r in ris {
365 write!(f, ", {}", View(r))?;
366 }
367 write!(f, "}}")?;
368 }
369 }
370 Ok(())
371 }
372}
373impl fmt::Display for RefInit {
374 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
375 write!(f, "{}: {}", View(&self.0), View(&self.1))
376 }
377}
378impl fmt::Display for RecInit {
379 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380 write!(f, "{}: {}", View(&self.0), View(&self.1))
381 }
382}
383impl fmt::Display for Ident {
384 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385 match self {
386 Ident::Principal => write!(f, "principal"),
387 Ident::Action => write!(f, "action"),
388 Ident::Resource => write!(f, "resource"),
389 Ident::Context => write!(f, "context"),
390 Ident::True => write!(f, "true"),
391 Ident::False => write!(f, "false"),
392 Ident::Permit => write!(f, "permit"),
393 Ident::Forbid => write!(f, "forbid"),
394 Ident::When => write!(f, "when"),
395 Ident::Unless => write!(f, "unless"),
396 Ident::In => write!(f, "in"),
397 Ident::Has => write!(f, "has"),
398 Ident::Like => write!(f, "like"),
399 Ident::If => write!(f, "if"),
400 Ident::Then => write!(f, "then"),
401 Ident::Else => write!(f, "else"),
402 Ident::Ident(s) => write!(f, "{}", s),
403 Ident::Invalid(s) => write!(f, "{}", s),
404 }
405 }
406}
407impl fmt::Display for Literal {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 match self {
410 Literal::True => write!(f, "true"),
411 Literal::False => write!(f, "false"),
412 Literal::Num(n) => write!(f, "{}", n),
413 Literal::Str(s) => write!(f, "{}", View(s)),
414 }
415 }
416}
417impl fmt::Display for Str {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419 match self {
420 Str::String(s) | Str::Invalid(s) => {
421 write!(f, "\"{}\"", s)
422 }
423 }
424 }
425}
426
427impl std::fmt::Display for Slot {
428 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
429 let src = match self {
430 Slot::Principal => "principal",
431 Slot::Resource => "resource",
432 };
433 write!(f, "?{src}")
434 }
435}
436
437#[cfg(test)]
438mod test {
439 use crate::parser::*;
440
441 #[test]
445 fn idempotent1() {
446 let cstnode1 = text_to_cst::parse_policies(
450 r#"
451
452 permit(principal,action,resource,context)
453 when {
454 -3 != !!2
455 };
456
457 "#,
458 )
459 .expect("parse fail");
460 let cst1 = cstnode1.as_inner().expect("no data");
461 let revert = format!("{}", cst1);
462 let cstnode2 = text_to_cst::parse_policies(&revert).expect("parse fail");
463 let cst2 = cstnode2.as_inner().expect("no data");
464 println!("{:#}", cst2);
465 assert!(cst1 == cst2);
466 }
467 #[test]
468 fn idempotent2() {
469 let cstnode1 = text_to_cst::parse_policies(
470 r#"
471
472 permit(principal,action,resource,context)
473 when {
474 context.contains(3,"four",five(6,7))
475 };
476
477 "#,
478 )
479 .expect("parse fail");
480 let cst1 = cstnode1.as_inner().expect("no data");
481 let revert = format!("{}", cst1);
482 let cstnode2 = text_to_cst::parse_policies(&revert).expect("parse fail");
483 let cst2 = cstnode2.as_inner().expect("no data");
484 assert!(cst1 == cst2);
485 }
486 #[test]
487 fn idempotent3() {
488 let cstnode1 = text_to_cst::parse_policies(
489 r#"
490
491 permit(principal,action,resource,context)
492 when {
493 context == {3: 14, "true": false || true }
494 };
495
496 "#,
497 )
498 .expect("parse fail");
499 let cst1 = cstnode1.as_inner().expect("no data");
500 let revert = format!("{}", cst1);
501 let cstnode2 = text_to_cst::parse_policies(&revert).expect("parse fail");
502 let cst2 = cstnode2.as_inner().expect("no data");
503 assert!(cst1 == cst2);
504 }
505 #[test]
506 fn idempotent4() {
507 let cstnode1 = text_to_cst::parse_policies(
508 r#"
509
510 permit(principal,action,resource,context)
511 when {
512 contains() ||
513 containsAll() ||
514 containsAny() ||
515 "sometext" like "some*" ||
516 Random::naming::of::foo()
517 };
518
519 "#,
520 )
521 .expect("parse fail");
522 let cst1 = cstnode1.as_inner().expect("no data");
523 let revert = format!("{}", cst1);
524 println!("{:#}", cst1);
525 let cstnode2 = text_to_cst::parse_policies(&revert).expect("parse fail");
526 let cst2 = cstnode2.as_inner().expect("no data");
527 assert!(cst1 == cst2);
528 }
529
530 #[test]
531 fn idempotent5() {
532 let cstnode1 = text_to_cst::parse_policies(
533 r#"
534
535 permit(principal,action,resource,context)
536 when {
537 principle == Group::{uid:"ajn34-3qg3-g5"}
538 };
539
540 "#,
541 )
542 .expect("parse fail");
543 let cst1 = cstnode1.as_inner().expect("no data");
544 let revert = format!("{}", cst1);
545 let cstnode2 = text_to_cst::parse_policies(&revert).expect("parse fail");
546 let cst2 = cstnode2.as_inner().expect("no data");
547 assert!(cst1 == cst2);
548 }
549}