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}1use 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 "string & number | object & null"72 );73 assert_eq!(format!("{}", ty!((str | [any]))), "string | array");74 assert_eq!(format!("{}", ty!(((str & num) | [any]))), "string & number | array");75}7677#[derive(Debug, Clone, Copy, PartialEq, Eq)]78pub enum ValType {79 Bool,80 Null,81 Str,82 Num,83 Arr,84 Obj,85 Func,86}8788impl ValType {89 pub const fn name(&self) -> &'static str {90 use ValType::*;91 match self {92 Bool => "boolean",93 Null => "null",94 Str => "string",95 Num => "number",96 Arr => "array",97 Obj => "object",98 Func => "function",99 }100 }101}102103impl Display for ValType {104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {105 write!(f, "{}", self.name())106 }107}108109#[derive(Debug, Clone, PartialEq)]110pub enum ComplexValType {111 Any,112 Char,113 Simple(ValType),114 BoundedNumber(Option<f64>, Option<f64>),115 ArrayRef(&'static ComplexValType),116 ObjectRef(&'static [(&'static str, ComplexValType)]),117 UnionRef(&'static [ComplexValType]),118 SumRef(&'static [ComplexValType]),119}120impl From<ValType> for ComplexValType {121 fn from(s: ValType) -> Self {122 Self::Simple(s)123 }124}125126fn write_union(127 f: &mut std::fmt::Formatter<'_>,128 is_union: bool,129 union: &[ComplexValType],130) -> std::fmt::Result {131 for (i, v) in union.iter().enumerate() {132 let should_add_braces = match v {133 ComplexValType::UnionRef(_) if !is_union => true,134 _ => false,135 };136 if i != 0 {137 write!(f, " {} ", if is_union { '|' } else { '&' })?;138 }139 if should_add_braces {140 write!(f, "(")?;141 }142 write!(f, "{}", v)?;143 if should_add_braces {144 write!(f, ")")?;145 }146 }147 Ok(())148}149150impl Display for ComplexValType {151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {152 match self {153 ComplexValType::Any => write!(f, "any")?,154 ComplexValType::Simple(s) => write!(f, "{}", s)?,155 ComplexValType::Char => write!(f, "char")?,156 ComplexValType::BoundedNumber(a, b) => write!(157 f,158 "BoundedNumber<{}, {}>",159 a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),160 b.map(|e| e.to_string()).unwrap_or_else(|| "".into())161 )?,162 ComplexValType::ArrayRef(a) => {163 if **a == ComplexValType::Any {164 write!(f, "array")?165 } else {166 write!(f, "Array<{}>", a)?167 }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, true, v)?,180 ComplexValType::SumRef(v) => write_union(f, false, v)?,181 };182 Ok(())183 }184}