difftreelog
feat prettier union type printing
in: master
1 file changed
crates/jrsonnet-types/src/lib.rsdiffbeforeafterboth1use std::fmt::Display;23#[macro_export]4macro_rules! ty {5 ([$inner:tt]) => {{6 use $crate::{ComplexValType, ValType, ty};7 static VAL: &'static ComplexValType = &ty!($inner);8 match VAL {9 ComplexValType::Any => ComplexValType::Simple(ValType::Arr),10 _ => ComplexValType::ArrayRef(&VAL),11 }12 }};13 (bool) => {14 $crate::ComplexValType::Simple($crate::ValType::Bool)15 };16 (null) => {17 $crate::ComplexValType::Simple($crate::ValType::Null)18 };19 (str) => {20 $crate::ComplexValType::Simple($crate::ValType::Str)21 };22 (char) => {23 $crate::ComplexValType::Char24 };25 (num) => {26 $crate::ComplexValType::Simple($crate::ValType::Num)27 };28 (number(($min:expr)..($max:expr))) => {{29 $crate::ComplexValType::BoundedNumber($min, $max)30 }};31 (obj) => {32 $crate::ComplexValType::Simple($crate::ValType::Obj)33 };34 (any) => {35 $crate::ComplexValType::Any36 };37 (fn.any) => {38 $crate::ComplexValType::Simple($crate::ValType::Func)39 };40 (($($a:tt) |+)) => {{41 static CONTENTS: &'static [$crate::ComplexValType] = &[42 $(ty!($a)),+43 ];44 $crate::ComplexValType::UnionRef(CONTENTS)45 }};46 (($($a:tt) &+)) => {{47 static CONTENTS: &'static [$crate::ComplexValType] = &[48 $(ty!($a)),+49 ];50 $crate::ComplexValType::SumRef(CONTENTS)51 }};52}5354#[test]55fn test() {56 assert_eq!(57 ty!([num]),58 ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))59 );60 assert_eq!(ty!([any]), ComplexValType::Simple(ValType::Arr));61 assert_eq!(ty!(any), ComplexValType::Any);62 assert_eq!(63 ty!((str | num)),64 ComplexValType::UnionRef(&[65 ComplexValType::Simple(ValType::Str),66 ComplexValType::Simple(ValType::Num)67 ])68 );69 assert_eq!(70 format!("{}", ty!(((str & num) | (obj & null)))),71 "((str & num) | (obj & null))"72 );73 assert_eq!(format!("{}", ty!((str | [any]))), "(str | [any])");74}7576#[derive(Debug, Clone, Copy, PartialEq, Eq)]77pub enum ValType {78 Bool,79 Null,80 Str,81 Num,82 Arr,83 Obj,84 Func,85}8687impl ValType {88 pub const fn name(&self) -> &'static str {89 use ValType::*;90 match self {91 Bool => "boolean",92 Null => "null",93 Str => "string",94 Num => "number",95 Arr => "array",96 Obj => "object",97 Func => "function",98 }99 }100}101102impl Display for ValType {103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {104 write!(f, "{}", self.name())105 }106}107108#[derive(Debug, Clone, PartialEq)]109pub enum ComplexValType {110 Any,111 Char,112 Simple(ValType),113 BoundedNumber(Option<f64>, Option<f64>),114 ArrayRef(&'static ComplexValType),115 ObjectRef(&'static [(&'static str, ComplexValType)]),116 UnionRef(&'static [ComplexValType]),117 SumRef(&'static [ComplexValType]),118}119impl From<ValType> for ComplexValType {120 fn from(s: ValType) -> Self {121 Self::Simple(s)122 }123}124125impl ComplexValType {126 fn needs_brackets(&self) -> bool {127 matches!(self, ComplexValType::UnionRef(_) | ComplexValType::SumRef(_))128 }129}130131fn write_union(132 f: &mut std::fmt::Formatter<'_>,133 ch: char,134 union: &[ComplexValType],135) -> std::fmt::Result {136 write!(f, "(")?;137 for (i, v) in union.iter().enumerate() {138 if i != 0 {139 write!(f, " {} ", ch)?;140 }141 write!(f, "{}", v)?;142 }143 write!(f, ")")?;144 Ok(())145}146147impl Display for ComplexValType {148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {149 match self {150 ComplexValType::Any => write!(f, "any")?,151 ComplexValType::Simple(s) => write!(f, "{}", s)?,152 ComplexValType::Char => write!(f, "char")?,153 ComplexValType::BoundedNumber(a, b) => write!(154 f,155 "number({}..{})",156 a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),157 b.map(|e| e.to_string()).unwrap_or_else(|| "".into())158 )?,159 ComplexValType::ArrayRef(a) => {160 if a.needs_brackets() {161 write!(f, "(")?;162 }163 write!(f, "{}", a)?;164 if a.needs_brackets() {165 write!(f, ")")?;166 }167 write!(f, "[]")?;168 }169 ComplexValType::ObjectRef(fields) => {170 write!(f, "{{")?;171 for (i, (k, v)) in fields.iter().enumerate() {172 if i != 0 {173 write!(f, ", ")?;174 }175 write!(f, "{}: {}", k, v)?;176 }177 write!(f, "}}")?;178 }179 ComplexValType::UnionRef(v) => write_union(f, '|', v)?,180 ComplexValType::SumRef(v) => write_union(f, '&', v)?,181 };182 Ok(())183 }184}