difftreelog
style fix clippy warnings
in: master
9 files changed
crates/jrsonnet-evaluator/src/builtin/manifest.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/manifest.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/manifest.rs
@@ -42,7 +42,7 @@
}
}
Val::Null => buf.push_str("null"),
- Val::Str(s) => buf.push_str(&escape_string_json(&s)),
+ Val::Str(s) => buf.push_str(&escape_string_json(s)),
Val::Num(n) => write!(buf, "{}", n).unwrap(),
Val::Arr(items) => {
buf.push('[');
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -445,7 +445,7 @@
},
Val::Arr(a) => {
base64::encode(a.iter().map(|v| {
- Ok(v?.clone().unwrap_num()? as u8)
+ Ok(v?.unwrap_num()? as u8)
}).collect::<Result<Vec<_>>>()?).into()
},
_ => unreachable!()
@@ -589,7 +589,7 @@
name: &str,
args: &ArgsDesc,
) -> Result<Val> {
- if let Some(f) = BUILTINS.with(|builtins| builtins.get(name).map(|f| *f)) {
+ if let Some(f) = BUILTINS.with(|builtins| builtins.get(name).copied()) {
return Ok(f(context, loc, args)?);
}
throw!(IntrinsicNotFound(name.into()))
crates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate.rs
@@ -473,7 +473,6 @@
}
v.get(n as usize)?
.ok_or_else(|| ArrayBoundsError(n as usize, v.len()))?
- .clone()
}
(Val::Arr(_), Val::Str(n)) => throw!(AttemptedIndexAnArrayWithString(n)),
(Val::Arr(_), n) => throw!(ValueIndexMustBeTypeGot(
crates/jrsonnet-evaluator/src/native.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/native.rs
+++ b/crates/jrsonnet-evaluator/src/native.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::type_complexity)]
+
use crate::{error::Result, Val};
use jrsonnet_parser::ParamsDesc;
use std::fmt::Debug;
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -34,7 +34,7 @@
}
let mut debug = f.debug_struct("ObjValue");
for (name, member) in self.0.this_entries.iter() {
- debug.field(&name, member);
+ debug.field(name, member);
}
#[cfg(feature = "unstable")]
{
@@ -140,7 +140,7 @@
.evaluate()?)
}
- pub fn ptr_eq(a: &ObjValue, b: &ObjValue) -> bool {
+ pub fn ptr_eq(a: &Self, b: &Self) -> bool {
Rc::ptr_eq(&a.0, &b.0)
}
}
crates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed.rs
+++ b/crates/jrsonnet-evaluator/src/typed.rs
@@ -29,7 +29,7 @@
pub struct TypeLocError(Box<TypeError>, ValuePathStack);
impl From<TypeError> for TypeLocError {
fn from(e: TypeError) -> Self {
- TypeLocError(Box::new(e), ValuePathStack(Vec::new()))
+ Self(Box::new(e), ValuePathStack(Vec::new()))
}
}
impl From<TypeLocError> for LocError {
@@ -61,7 +61,7 @@
write!(out, "{}", err)?;
for (i, line) in out.lines().enumerate() {
- if line.trim().len() == 0 {
+ if line.trim().is_empty() {
continue;
}
if i != 0 {
@@ -118,8 +118,8 @@
impl Display for ValuePathItem {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
- ValuePathItem::Field(name) => write!(f, ".{}", name)?,
- ValuePathItem::Index(idx) => write!(f, "[{}]", idx)?,
+ Self::Field(name) => write!(f, ".{}", name)?,
+ Self::Index(idx) => write!(f, "[{}]", idx)?,
}
Ok(())
}
@@ -140,25 +140,25 @@
impl CheckType for ComplexValType {
fn check(&self, value: &Val) -> Result<()> {
match self {
- ComplexValType::Any => Ok(()),
- ComplexValType::Simple(s) => s.check(value),
- ComplexValType::Char => match value {
+ Self::Any => Ok(()),
+ Self::Simple(s) => s.check(value),
+ Self::Char => match value {
Val::Str(s) if s.len() == 1 || s.chars().count() == 1 => Ok(()),
v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
},
- ComplexValType::BoundedNumber(from, to) => {
+ Self::BoundedNumber(from, to) => {
if let Val::Num(n) = value {
if from.map(|from| from > *n).unwrap_or(false)
|| to.map(|to| to <= *n).unwrap_or(false)
{
- return Err(TypeError::BoundsFailed(*n, from.clone(), to.clone()).into());
+ return Err(TypeError::BoundsFailed(*n, *from, *to).into());
}
Ok(())
} else {
Err(TypeError::ExpectedGot(self.clone(), value.value_type()).into())
}
}
- ComplexValType::Array(elem_type) => match value {
+ Self::Array(elem_type) => match value {
Val::Arr(a) => {
for (i, item) in a.iter().enumerate() {
push_type(
@@ -170,9 +170,9 @@
}
Ok(())
}
- v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
+ v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
},
- ComplexValType::ArrayRef(elem_type) => match value {
+ Self::ArrayRef(elem_type) => match value {
Val::Arr(a) => {
for (i, item) in a.iter().enumerate() {
push_type(
@@ -184,9 +184,9 @@
}
Ok(())
}
- v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
+ v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
},
- ComplexValType::ObjectRef(elems) => match value {
+ Self::ObjectRef(elems) => match value {
Val::Obj(obj) => {
for (k, v) in elems.iter() {
if let Some(got_v) = obj.get((*k).into())? {
@@ -202,11 +202,11 @@
);
}
}
- return Ok(());
+ Ok(())
}
- v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
+ v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
},
- ComplexValType::Union(types) => {
+ Self::Union(types) => {
let mut errors = Vec::new();
for ty in types.iter() {
match ty.check(value) {
@@ -219,9 +219,9 @@
},
}
}
- return Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into());
+ Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into())
}
- ComplexValType::UnionRef(types) => {
+ Self::UnionRef(types) => {
let mut errors = Vec::new();
for ty in types.iter() {
match ty.check(value) {
@@ -234,15 +234,15 @@
},
}
}
- return Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into());
+ Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into())
}
- ComplexValType::Sum(types) => {
+ Self::Sum(types) => {
for ty in types.iter() {
ty.check(value)?
}
Ok(())
}
- ComplexValType::SumRef(types) => {
+ Self::SumRef(types) => {
for ty in types.iter() {
ty.check(value)?
}
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -176,14 +176,14 @@
pub enum ArrValue {
Lazy(Rc<Vec<LazyVal>>),
Eager(Rc<Vec<Val>>),
- Extended(Box<(ArrValue, ArrValue)>),
+ Extended(Box<(Self, Self)>),
}
impl ArrValue {
pub fn len(&self) -> usize {
match self {
- ArrValue::Lazy(l) => l.len(),
- ArrValue::Eager(e) => e.len(),
- ArrValue::Extended(v) => v.0.len() + v.1.len(),
+ Self::Lazy(l) => l.len(),
+ Self::Eager(e) => e.len(),
+ Self::Extended(v) => v.0.len() + v.1.len(),
}
}
@@ -193,15 +193,15 @@
pub fn get(&self, index: usize) -> Result<Option<Val>> {
match self {
- ArrValue::Lazy(vec) => {
+ Self::Lazy(vec) => {
if let Some(v) = vec.get(index) {
Ok(Some(v.evaluate()?))
} else {
Ok(None)
}
}
- ArrValue::Eager(vec) => Ok(vec.get(index).cloned()),
- ArrValue::Extended(v) => {
+ Self::Eager(vec) => Ok(vec.get(index).cloned()),
+ Self::Extended(v) => {
let a_len = v.0.len();
if a_len > index {
v.0.get(index)
@@ -214,12 +214,9 @@
pub fn get_lazy(&self, index: usize) -> Option<LazyVal> {
match self {
- ArrValue::Lazy(vec) => vec.get(index).cloned(),
- ArrValue::Eager(vec) => vec
- .get(index)
- .cloned()
- .map(|val| LazyVal::new_resolved(val)),
- ArrValue::Extended(v) => {
+ Self::Lazy(vec) => vec.get(index).cloned(),
+ Self::Eager(vec) => vec.get(index).cloned().map(LazyVal::new_resolved),
+ Self::Extended(v) => {
let a_len = v.0.len();
if a_len > index {
v.0.get_lazy(index)
@@ -232,15 +229,15 @@
pub fn evaluated(&self) -> Result<Rc<Vec<Val>>> {
Ok(match self {
- ArrValue::Lazy(vec) => {
+ Self::Lazy(vec) => {
let mut out = Vec::with_capacity(vec.len());
for item in vec.iter() {
out.push(item.evaluate()?);
}
Rc::new(out)
}
- ArrValue::Eager(vec) => vec.clone(),
- ArrValue::Extended(v) => {
+ Self::Eager(vec) => vec.clone(),
+ Self::Extended(_v) => {
let mut out = Vec::with_capacity(self.len());
for item in self.iter() {
out.push(item?);
@@ -252,40 +249,40 @@
pub fn iter(&self) -> impl DoubleEndedIterator<Item = Result<Val>> + '_ {
(0..self.len()).map(move |idx| match self {
- ArrValue::Lazy(l) => l[idx].evaluate(),
- ArrValue::Eager(e) => Ok(e[idx].clone()),
- ArrValue::Extended(_) => self.get(idx).map(|e| e.unwrap()),
+ Self::Lazy(l) => l[idx].evaluate(),
+ Self::Eager(e) => Ok(e[idx].clone()),
+ Self::Extended(_) => self.get(idx).map(|e| e.unwrap()),
})
}
pub fn iter_lazy(&self) -> impl DoubleEndedIterator<Item = LazyVal> + '_ {
(0..self.len()).map(move |idx| match self {
- ArrValue::Lazy(l) => l[idx].clone(),
- ArrValue::Eager(e) => LazyVal::new_resolved(e[idx].clone()),
- ArrValue::Extended(_) => self.get_lazy(idx).unwrap(),
+ Self::Lazy(l) => l[idx].clone(),
+ Self::Eager(e) => LazyVal::new_resolved(e[idx].clone()),
+ Self::Extended(_) => self.get_lazy(idx).unwrap(),
})
}
pub fn reversed(self) -> Self {
match self {
- ArrValue::Lazy(vec) => {
+ Self::Lazy(vec) => {
let mut out = (&vec as &Vec<_>).clone();
out.reverse();
Self::Lazy(Rc::new(out))
}
- ArrValue::Eager(vec) => {
+ Self::Eager(vec) => {
let mut out = (&vec as &Vec<_>).clone();
out.reverse();
Self::Eager(Rc::new(out))
}
- ArrValue::Extended(b) => ArrValue::Extended(Box::new((b.1.reversed(), b.0.reversed()))),
+ Self::Extended(b) => Self::Extended(Box::new((b.1.reversed(), b.0.reversed()))),
}
}
- pub fn ptr_eq(a: &ArrValue, b: &ArrValue) -> bool {
+ pub fn ptr_eq(a: &Self, b: &Self) -> bool {
match (a, b) {
- (ArrValue::Lazy(a), ArrValue::Lazy(b)) => Rc::ptr_eq(a, b),
- (ArrValue::Eager(a), ArrValue::Eager(b)) => Rc::ptr_eq(a, b),
+ (Self::Lazy(a), Self::Lazy(b)) => Rc::ptr_eq(a, b),
+ (Self::Eager(a), Self::Eager(b)) => Rc::ptr_eq(a, b),
_ => false,
}
}
@@ -359,7 +356,7 @@
self.assert_type(context, ValType::Num)?;
self.unwrap_num()
}
- pub fn value_type(&self) -> ValType {
+ pub const fn value_type(&self) -> ValType {
match self {
Self::Str(..) => ValType::Str,
Self::Num(..) => ValType::Num,
@@ -378,7 +375,7 @@
Self::Null => "null".into(),
Self::Str(s) => s.clone(),
v => manifest_json_ex(
- &v,
+ v,
&ManifestJsonOptions {
padding: "",
mtype: ManifestType::ToString,
@@ -556,7 +553,7 @@
(Val::Obj(_), Val::Obj(_)) => throw!(RuntimeError(
"primitiveEquals operates on primitive types, got object".into(),
)),
- (a, b) if is_function_like(&a) && is_function_like(&b) => {
+ (a, b) if is_function_like(a) && is_function_like(b) => {
throw!(RuntimeError("cannot test equality of functions".into()))
}
(_, _) => false,
@@ -598,6 +595,6 @@
}
Ok(true)
}
- (a, b) => Ok(primitive_equals(&a, &b)?),
+ (a, b) => Ok(primitive_equals(a, b)?),
}
}
crates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-interner/src/lib.rs
+++ b/crates/jrsonnet-interner/src/lib.rs
@@ -68,7 +68,7 @@
IStr(STR_POOL.with(|pool| {
let mut pool = pool.borrow_mut();
if let Some((k, _)) = pool.get_key_value(str) {
- return k.clone();
+ k.clone()
} else {
let rc: Rc<str> = str.into();
pool.insert(rc.clone(), ());
crates/jrsonnet-types/src/lib.rsdiffbeforeafterboth1use std::fmt::Display;23#[macro_export]4macro_rules! ty {5 ((Array<number>)) => {{6 $crate::ComplexValType::ArrayRef(&$crate::ComplexValType::Simple($crate::ValType::Num))7 }};8 (array) => {9 $crate::ComplexValType::Simple($crate::ValType::Arr)10 };11 (boolean) => {12 $crate::ComplexValType::Simple($crate::ValType::Bool)13 };14 (null) => {15 $crate::ComplexValType::Simple($crate::ValType::Null)16 };17 (string) => {18 $crate::ComplexValType::Simple($crate::ValType::Str)19 };20 (char) => {21 $crate::ComplexValType::Char22 };23 (number) => {24 $crate::ComplexValType::Simple($crate::ValType::Num)25 };26 (BoundedNumber<($min:expr), ($max:expr)>) => {{27 $crate::ComplexValType::BoundedNumber($min, $max)28 }};29 (object) => {30 $crate::ComplexValType::Simple($crate::ValType::Obj)31 };32 (any) => {33 $crate::ComplexValType::Any34 };35 (function) => {36 $crate::ComplexValType::Simple($crate::ValType::Func)37 };38 (($($a:tt) |+)) => {{39 static CONTENTS: &'static [$crate::ComplexValType] = &[40 $(ty!($a)),+41 ];42 $crate::ComplexValType::UnionRef(CONTENTS)43 }};44 (($($a:tt) &+)) => {{45 static CONTENTS: &'static [$crate::ComplexValType] = &[46 $(ty!($a)),+47 ];48 $crate::ComplexValType::SumRef(CONTENTS)49 }};50}5152#[test]53fn test() {54 assert_eq!(55 ty!((Array<number>)),56 ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))57 );58 assert_eq!(ty!(array), ComplexValType::Simple(ValType::Arr));59 assert_eq!(ty!(any), ComplexValType::Any);60 assert_eq!(61 ty!((string | number)),62 ComplexValType::UnionRef(&[63 ComplexValType::Simple(ValType::Str),64 ComplexValType::Simple(ValType::Num)65 ])66 );67 assert_eq!(68 format!("{}", ty!(((string & number) | (object & null)))),69 "string & number | object & null"70 );71 assert_eq!(format!("{}", ty!((string | array))), "string | array");72 assert_eq!(73 format!("{}", ty!(((string & number) | array))),74 "string & number | array"75 );76}7778#[derive(Debug, Clone, Copy, PartialEq, Eq)]79pub enum ValType {80 Bool,81 Null,82 Str,83 Num,84 Arr,85 Obj,86 Func,87}8889impl ValType {90 pub const fn name(&self) -> &'static str {91 use ValType::*;92 match self {93 Bool => "boolean",94 Null => "null",95 Str => "string",96 Num => "number",97 Arr => "array",98 Obj => "object",99 Func => "function",100 }101 }102}103104impl Display for ValType {105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {106 write!(f, "{}", self.name())107 }108}109110#[derive(Debug, Clone, PartialEq)]111pub enum ComplexValType {112 Any,113 Char,114 Simple(ValType),115 BoundedNumber(Option<f64>, Option<f64>),116 Array(Box<ComplexValType>),117 ArrayRef(&'static ComplexValType),118 ObjectRef(&'static [(&'static str, ComplexValType)]),119 Union(Vec<ComplexValType>),120 UnionRef(&'static [ComplexValType]),121 Sum(Vec<ComplexValType>),122 SumRef(&'static [ComplexValType]),123}124impl From<ValType> for ComplexValType {125 fn from(s: ValType) -> Self {126 Self::Simple(s)127 }128}129130fn write_union(131 f: &mut std::fmt::Formatter<'_>,132 is_union: bool,133 union: &[ComplexValType],134) -> std::fmt::Result {135 for (i, v) in union.iter().enumerate() {136 let should_add_braces = match v {137 ComplexValType::UnionRef(_) | ComplexValType::Union(_) if !is_union => true,138 _ => false,139 };140 if i != 0 {141 write!(f, " {} ", if is_union { '|' } else { '&' })?;142 }143 if should_add_braces {144 write!(f, "(")?;145 }146 write!(f, "{}", v)?;147 if should_add_braces {148 write!(f, ")")?;149 }150 }151 Ok(())152}153154fn print_array(a: &ComplexValType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {155 if *a == ComplexValType::Any {156 write!(f, "array")?157 } else {158 write!(f, "Array<{}>", a)?159 }160 Ok(())161}162163impl Display for ComplexValType {164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {165 match self {166 ComplexValType::Any => write!(f, "any")?,167 ComplexValType::Simple(s) => write!(f, "{}", s)?,168 ComplexValType::Char => write!(f, "char")?,169 ComplexValType::BoundedNumber(a, b) => write!(170 f,171 "BoundedNumber<{}, {}>",172 a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),173 b.map(|e| e.to_string()).unwrap_or_else(|| "".into())174 )?,175 ComplexValType::ArrayRef(a) => print_array(a, f)?,176 ComplexValType::Array(a) => print_array(a, f)?,177 ComplexValType::ObjectRef(fields) => {178 write!(f, "{{")?;179 for (i, (k, v)) in fields.iter().enumerate() {180 if i != 0 {181 write!(f, ", ")?;182 }183 write!(f, "{}: {}", k, v)?;184 }185 write!(f, "}}")?;186 }187 ComplexValType::Union(v) => write_union(f, true, v)?,188 ComplexValType::UnionRef(v) => write_union(f, true, v)?,189 ComplexValType::Sum(v) => write_union(f, false, v)?,190 ComplexValType::SumRef(v) => write_union(f, false, v)?,191 };192 Ok(())193 }194}195196peg::parser! {197pub grammar parser() for str {198 rule number() -> f64199 = n:$(['0'..='9']+) { n.parse().unwrap() }200201 rule any_ty() -> ComplexValType = "any" { ComplexValType::Any }202 rule char_ty() -> ComplexValType = "character" { ComplexValType::Char }203 rule bool_ty() -> ComplexValType = "boolean" { ComplexValType::Simple(ValType::Bool) }204 rule null_ty() -> ComplexValType = "null" { ComplexValType::Simple(ValType::Null) }205 rule str_ty() -> ComplexValType = "string" { ComplexValType::Simple(ValType::Str) }206 rule num_ty() -> ComplexValType = "number" { ComplexValType::Simple(ValType::Num) }207 rule simple_array_ty() -> ComplexValType = "array" { ComplexValType::Simple(ValType::Arr) }208 rule simple_object_ty() -> ComplexValType = "object" { ComplexValType::Simple(ValType::Obj) }209 rule simple_function_ty() -> ComplexValType = "function" { ComplexValType::Simple(ValType::Func) }210211 rule array_ty() -> ComplexValType212 = "Array<" t:ty() ">" { ComplexValType::Array(Box::new(t)) }213214 rule bounded_number_ty() -> ComplexValType215 = "BoundedNumber<" a:number() ", " b:number() ">" { ComplexValType::BoundedNumber(Some(a), Some(b)) }216217 rule ty_basic() -> ComplexValType218 = any_ty()219 / char_ty()220 / bool_ty()221 / null_ty()222 / str_ty()223 / num_ty()224 / simple_array_ty()225 / simple_object_ty()226 / simple_function_ty()227 / array_ty()228 / bounded_number_ty()229230 pub rule ty() -> ComplexValType231 = precedence! {232 a:(@) " | " b:@ {233 match a {234 ComplexValType::Union(mut a) => {235 a.push(b);236 ComplexValType::Union(a)237 }238 _ => ComplexValType::Union(vec![a, b]),239 }240 }241 --242 a:(@) " & " b:@ {243 match a {244 ComplexValType::Sum(mut a) => {245 a.push(b);246 ComplexValType::Sum(a)247 }248 _ => ComplexValType::Sum(vec![a, b]),249 }250 }251 --252 "(" t:ty() ")" { t }253 t:ty_basic() { t }254 }255}256}257258#[cfg(test)]259pub mod tests {260 use super::parser;261262 #[test]263 fn precedence() {264 assert_eq!(265 parser::ty("(any & any) | (any | any) & any")266 .unwrap()267 .to_string(),268 "any & any | (any | any) & any"269 );270 }271272 #[test]273 fn array() {274 assert_eq!(parser::ty("Array<any>").unwrap().to_string(), "array");275 assert_eq!(276 parser::ty("Array<number>").unwrap().to_string(),277 "Array<number>"278 );279 }280 #[test]281 fn bounded_number() {282 assert_eq!(283 parser::ty("BoundedNumber<1, 2>").unwrap().to_string(),284 "BoundedNumber<1, 2>"285 );286 }287}1use std::fmt::Display;23#[macro_export]4macro_rules! ty {5 ((Array<number>)) => {{6 $crate::ComplexValType::ArrayRef(&$crate::ComplexValType::Simple($crate::ValType::Num))7 }};8 (array) => {9 $crate::ComplexValType::Simple($crate::ValType::Arr)10 };11 (boolean) => {12 $crate::ComplexValType::Simple($crate::ValType::Bool)13 };14 (null) => {15 $crate::ComplexValType::Simple($crate::ValType::Null)16 };17 (string) => {18 $crate::ComplexValType::Simple($crate::ValType::Str)19 };20 (char) => {21 $crate::ComplexValType::Char22 };23 (number) => {24 $crate::ComplexValType::Simple($crate::ValType::Num)25 };26 (BoundedNumber<($min:expr), ($max:expr)>) => {{27 $crate::ComplexValType::BoundedNumber($min, $max)28 }};29 (object) => {30 $crate::ComplexValType::Simple($crate::ValType::Obj)31 };32 (any) => {33 $crate::ComplexValType::Any34 };35 (function) => {36 $crate::ComplexValType::Simple($crate::ValType::Func)37 };38 (($($a:tt) |+)) => {{39 static CONTENTS: &'static [$crate::ComplexValType] = &[40 $(ty!($a)),+41 ];42 $crate::ComplexValType::UnionRef(CONTENTS)43 }};44 (($($a:tt) &+)) => {{45 static CONTENTS: &'static [$crate::ComplexValType] = &[46 $(ty!($a)),+47 ];48 $crate::ComplexValType::SumRef(CONTENTS)49 }};50}5152#[test]53fn test() {54 assert_eq!(55 ty!((Array<number>)),56 ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))57 );58 assert_eq!(ty!(array), ComplexValType::Simple(ValType::Arr));59 assert_eq!(ty!(any), ComplexValType::Any);60 assert_eq!(61 ty!((string | number)),62 ComplexValType::UnionRef(&[63 ComplexValType::Simple(ValType::Str),64 ComplexValType::Simple(ValType::Num)65 ])66 );67 assert_eq!(68 format!("{}", ty!(((string & number) | (object & null)))),69 "string & number | object & null"70 );71 assert_eq!(format!("{}", ty!((string | array))), "string | array");72 assert_eq!(73 format!("{}", ty!(((string & number) | array))),74 "string & number | array"75 );76}7778#[derive(Debug, Clone, Copy, PartialEq, Eq)]79pub enum ValType {80 Bool,81 Null,82 Str,83 Num,84 Arr,85 Obj,86 Func,87}8889impl ValType {90 pub const fn name(&self) -> &'static str {91 use ValType::*;92 match self {93 Bool => "boolean",94 Null => "null",95 Str => "string",96 Num => "number",97 Arr => "array",98 Obj => "object",99 Func => "function",100 }101 }102}103104impl Display for ValType {105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {106 write!(f, "{}", self.name())107 }108}109110#[derive(Debug, Clone, PartialEq)]111pub enum ComplexValType {112 Any,113 Char,114 Simple(ValType),115 BoundedNumber(Option<f64>, Option<f64>),116 Array(Box<ComplexValType>),117 ArrayRef(&'static ComplexValType),118 ObjectRef(&'static [(&'static str, ComplexValType)]),119 Union(Vec<ComplexValType>),120 UnionRef(&'static [ComplexValType]),121 Sum(Vec<ComplexValType>),122 SumRef(&'static [ComplexValType]),123}124impl From<ValType> for ComplexValType {125 fn from(s: ValType) -> Self {126 Self::Simple(s)127 }128}129130fn write_union(131 f: &mut std::fmt::Formatter<'_>,132 is_union: bool,133 union: &[ComplexValType],134) -> std::fmt::Result {135 for (i, v) in union.iter().enumerate() {136 let should_add_braces =137 matches!(v, ComplexValType::UnionRef(_) | ComplexValType::Union(_) if !is_union);138 if i != 0 {139 write!(f, " {} ", if is_union { '|' } else { '&' })?;140 }141 if should_add_braces {142 write!(f, "(")?;143 }144 write!(f, "{}", v)?;145 if should_add_braces {146 write!(f, ")")?;147 }148 }149 Ok(())150}151152fn print_array(a: &ComplexValType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {153 if *a == ComplexValType::Any {154 write!(f, "array")?155 } else {156 write!(f, "Array<{}>", a)?157 }158 Ok(())159}160161impl Display for ComplexValType {162 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {163 match self {164 ComplexValType::Any => write!(f, "any")?,165 ComplexValType::Simple(s) => write!(f, "{}", s)?,166 ComplexValType::Char => write!(f, "char")?,167 ComplexValType::BoundedNumber(a, b) => write!(168 f,169 "BoundedNumber<{}, {}>",170 a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),171 b.map(|e| e.to_string()).unwrap_or_else(|| "".into())172 )?,173 ComplexValType::ArrayRef(a) => print_array(a, f)?,174 ComplexValType::Array(a) => print_array(a, f)?,175 ComplexValType::ObjectRef(fields) => {176 write!(f, "{{")?;177 for (i, (k, v)) in fields.iter().enumerate() {178 if i != 0 {179 write!(f, ", ")?;180 }181 write!(f, "{}: {}", k, v)?;182 }183 write!(f, "}}")?;184 }185 ComplexValType::Union(v) => write_union(f, true, v)?,186 ComplexValType::UnionRef(v) => write_union(f, true, v)?,187 ComplexValType::Sum(v) => write_union(f, false, v)?,188 ComplexValType::SumRef(v) => write_union(f, false, v)?,189 };190 Ok(())191 }192}193194peg::parser! {195pub grammar parser() for str {196 rule number() -> f64197 = n:$(['0'..='9']+) { n.parse().unwrap() }198199 rule any_ty() -> ComplexValType = "any" { ComplexValType::Any }200 rule char_ty() -> ComplexValType = "character" { ComplexValType::Char }201 rule bool_ty() -> ComplexValType = "boolean" { ComplexValType::Simple(ValType::Bool) }202 rule null_ty() -> ComplexValType = "null" { ComplexValType::Simple(ValType::Null) }203 rule str_ty() -> ComplexValType = "string" { ComplexValType::Simple(ValType::Str) }204 rule num_ty() -> ComplexValType = "number" { ComplexValType::Simple(ValType::Num) }205 rule simple_array_ty() -> ComplexValType = "array" { ComplexValType::Simple(ValType::Arr) }206 rule simple_object_ty() -> ComplexValType = "object" { ComplexValType::Simple(ValType::Obj) }207 rule simple_function_ty() -> ComplexValType = "function" { ComplexValType::Simple(ValType::Func) }208209 rule array_ty() -> ComplexValType210 = "Array<" t:ty() ">" { ComplexValType::Array(Box::new(t)) }211212 rule bounded_number_ty() -> ComplexValType213 = "BoundedNumber<" a:number() ", " b:number() ">" { ComplexValType::BoundedNumber(Some(a), Some(b)) }214215 rule ty_basic() -> ComplexValType216 = any_ty()217 / char_ty()218 / bool_ty()219 / null_ty()220 / str_ty()221 / num_ty()222 / simple_array_ty()223 / simple_object_ty()224 / simple_function_ty()225 / array_ty()226 / bounded_number_ty()227228 pub rule ty() -> ComplexValType229 = precedence! {230 a:(@) " | " b:@ {231 match a {232 ComplexValType::Union(mut a) => {233 a.push(b);234 ComplexValType::Union(a)235 }236 _ => ComplexValType::Union(vec![a, b]),237 }238 }239 --240 a:(@) " & " b:@ {241 match a {242 ComplexValType::Sum(mut a) => {243 a.push(b);244 ComplexValType::Sum(a)245 }246 _ => ComplexValType::Sum(vec![a, b]),247 }248 }249 --250 "(" t:ty() ")" { t }251 t:ty_basic() { t }252 }253}254}255256#[cfg(test)]257pub mod tests {258 use super::parser;259260 #[test]261 fn precedence() {262 assert_eq!(263 parser::ty("(any & any) | (any | any) & any")264 .unwrap()265 .to_string(),266 "any & any | (any | any) & any"267 );268 }269270 #[test]271 fn array() {272 assert_eq!(parser::ty("Array<any>").unwrap().to_string(), "array");273 assert_eq!(274 parser::ty("Array<number>").unwrap().to_string(),275 "Array<number>"276 );277 }278 #[test]279 fn bounded_number() {280 assert_eq!(281 parser::ty("BoundedNumber<1, 2>").unwrap().to_string(),282 "BoundedNumber<1, 2>"283 );284 }285}