Complete ImmutableString.
This commit is contained in:
@@ -269,141 +269,69 @@ macro_rules! reg_op {
|
||||
}
|
||||
|
||||
def_package!(crate:ArithmeticPackage:"Basic arithmetic", lib, {
|
||||
// Checked basic arithmetic
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
{
|
||||
// reg_op!(lib, "+", add, INT);
|
||||
// reg_op!(lib, "-", sub, INT);
|
||||
// reg_op!(lib, "*", mul, INT);
|
||||
// reg_op!(lib, "/", div, INT);
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
{
|
||||
// reg_op!(lib, "+", add, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "-", sub, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "*", mul, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "/", div, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// Checked basic arithmetic
|
||||
reg_op!(lib, "+", add, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "-", sub, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "*", mul, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "/", div, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
}
|
||||
}
|
||||
|
||||
// Unchecked basic arithmetic
|
||||
#[cfg(feature = "unchecked")]
|
||||
{
|
||||
// reg_op!(lib, "+", add_u, INT);
|
||||
// reg_op!(lib, "-", sub_u, INT);
|
||||
// reg_op!(lib, "*", mul_u, INT);
|
||||
// reg_op!(lib, "/", div_u, INT);
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
{
|
||||
// reg_op!(lib, "+", add_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "-", sub_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "*", mul_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "/", div_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
reg_op!(lib, "+", add_u, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "-", sub_u, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "*", mul_u, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "/", div_u, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
}
|
||||
}
|
||||
|
||||
// Basic arithmetic for floating-point - no need to check
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
{
|
||||
// reg_op!(lib, "+", add_u, f32, f64);
|
||||
// reg_op!(lib, "-", sub_u, f32, f64);
|
||||
// reg_op!(lib, "*", mul_u, f32, f64);
|
||||
// reg_op!(lib, "/", div_u, f32, f64);
|
||||
reg_op!(lib, "+", add_u, f32);
|
||||
reg_op!(lib, "-", sub_u, f32);
|
||||
reg_op!(lib, "*", mul_u, f32);
|
||||
reg_op!(lib, "/", div_u, f32);
|
||||
}
|
||||
|
||||
// Bit operations
|
||||
// reg_op!(lib, "|", binary_or, INT);
|
||||
// reg_op!(lib, "&", binary_and, INT);
|
||||
// reg_op!(lib, "^", binary_xor, INT);
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
{
|
||||
// reg_op!(lib, "|", binary_or, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "&", binary_and, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "^", binary_xor, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
reg_op!(lib, "|", binary_or, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "&", binary_and, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "^", binary_xor, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
}
|
||||
|
||||
// Checked bit shifts
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
{
|
||||
// reg_op!(lib, "<<", shl, INT);
|
||||
// reg_op!(lib, ">>", shr, INT);
|
||||
// reg_op!(lib, "%", modulo, INT);
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
{
|
||||
// reg_op!(lib, "<<", shl, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, ">>", shr, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "%", modulo, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// Checked bit shifts
|
||||
reg_op!(lib, "<<", shl, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, ">>", shr, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "%", modulo, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
}
|
||||
}
|
||||
|
||||
// Unchecked bit shifts
|
||||
#[cfg(feature = "unchecked")]
|
||||
{
|
||||
// reg_op!(lib, "<<", shl_u, INT, INT);
|
||||
// reg_op!(lib, ">>", shr_u, INT, INT);
|
||||
// reg_op!(lib, "%", modulo_u, INT);
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
#[cfg(feature = "unchecked")]
|
||||
{
|
||||
// reg_op!(lib, "<<", shl_u, i64, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, ">>", shr_u, i64, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "%", modulo_u, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// Unchecked basic arithmetic
|
||||
reg_op!(lib, "+", add_u, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "-", sub_u, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "*", mul_u, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "/", div_u, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
// Unchecked bit shifts
|
||||
reg_op!(lib, "<<", shl_u, i64, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, ">>", shr_u, i64, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "%", modulo_u, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
}
|
||||
}
|
||||
|
||||
// Checked power
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
{
|
||||
// lib.set_fn_2("~", pow_i_i);
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
lib.set_fn_2("~", pow_f_i);
|
||||
}
|
||||
|
||||
// Unchecked power
|
||||
#[cfg(feature = "unchecked")]
|
||||
{
|
||||
// lib.set_fn_2("~", pow_i_i_u);
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
lib.set_fn_2("~", pow_f_i_u);
|
||||
}
|
||||
|
||||
// Floating-point modulo and power
|
||||
// Basic arithmetic for floating-point - no need to check
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
{
|
||||
// reg_op!(lib, "%", modulo_u, f32, f64);
|
||||
reg_op!(lib, "+", add_u, f32);
|
||||
reg_op!(lib, "-", sub_u, f32);
|
||||
reg_op!(lib, "*", mul_u, f32);
|
||||
reg_op!(lib, "/", div_u, f32);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
{
|
||||
reg_op!(lib, "|", binary_or, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "&", binary_and, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "^", binary_xor, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
{
|
||||
// Checked power
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
lib.set_fn_2("~", pow_f_i);
|
||||
|
||||
// Unchecked power
|
||||
#[cfg(feature = "unchecked")]
|
||||
lib.set_fn_2("~", pow_f_i_u);
|
||||
|
||||
// Floating-point modulo and power
|
||||
reg_op!(lib, "%", modulo_u, f32);
|
||||
// lib.set_fn_2("~", pow_f_f);
|
||||
|
||||
// Floating-point unary
|
||||
reg_unary!(lib, "-", neg_u, f32, f64);
|
||||
reg_unary!(lib, "abs", abs_u, f32, f64);
|
||||
}
|
||||
|
||||
// Checked unary
|
||||
@@ -433,11 +361,4 @@ def_package!(crate:ArithmeticPackage:"Basic arithmetic", lib, {
|
||||
reg_unary!(lib, "abs", abs_u, i8, i16, i32, i64, i128);
|
||||
}
|
||||
}
|
||||
|
||||
// Floating-point unary
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
{
|
||||
reg_unary!(lib, "-", neg_u, f32, f64);
|
||||
reg_unary!(lib, "abs", abs_u, f32, f64);
|
||||
}
|
||||
});
|
||||
|
@@ -1,6 +1,5 @@
|
||||
use crate::def_package;
|
||||
use crate::module::FuncReturn;
|
||||
use crate::parser::{ImmutableString, INT};
|
||||
|
||||
// Comparison operators
|
||||
pub fn lt<T: PartialOrd>(x: T, y: T) -> FuncReturn<bool> {
|
||||
@@ -23,12 +22,6 @@ pub fn ne<T: PartialEq>(x: T, y: T) -> FuncReturn<bool> {
|
||||
}
|
||||
|
||||
// Logic operators
|
||||
fn and(x: bool, y: bool) -> FuncReturn<bool> {
|
||||
Ok(x && y)
|
||||
}
|
||||
fn or(x: bool, y: bool) -> FuncReturn<bool> {
|
||||
Ok(x || y)
|
||||
}
|
||||
fn not(x: bool) -> FuncReturn<bool> {
|
||||
Ok(!x)
|
||||
}
|
||||
@@ -40,30 +33,9 @@ macro_rules! reg_op {
|
||||
}
|
||||
|
||||
def_package!(crate:LogicPackage:"Logical operators.", lib, {
|
||||
// reg_op!(lib, "<", lt, INT, char);
|
||||
// reg_op!(lib, "<=", lte, INT, char);
|
||||
// reg_op!(lib, ">", gt, INT, char);
|
||||
// reg_op!(lib, ">=", gte, INT, char);
|
||||
// reg_op!(lib, "==", eq, INT, char, bool, ());
|
||||
// reg_op!(lib, "!=", ne, INT, char, bool, ());
|
||||
|
||||
// Special versions for strings - at least avoid copying the first string
|
||||
// lib.set_fn_2("<", |x: ImmutableString, y: ImmutableString| Ok(*x < y));
|
||||
// lib.set_fn_2("<=", |x: ImmutableString, y: ImmutableString| Ok(*x <= y));
|
||||
// lib.set_fn_2(">", |x: ImmutableString, y: ImmutableString| Ok(*x > y));
|
||||
// lib.set_fn_2(">=", |x: ImmutableString, y: ImmutableString| Ok(*x >= y));
|
||||
// lib.set_fn_2("==", |x: ImmutableString, y: ImmutableString| Ok(*x == y));
|
||||
// lib.set_fn_2("!=", |x: ImmutableString, y: ImmutableString| Ok(*x != y));
|
||||
|
||||
#[cfg(not(feature = "only_i32"))]
|
||||
#[cfg(not(feature = "only_i64"))]
|
||||
{
|
||||
// reg_op!(lib, "<", lt, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "<=", lte, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, ">", gt, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, ">=", gte, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "==", eq, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
// reg_op!(lib, "!=", ne, i8, u8, i16, u16, i32, i64, u32, u64, i128, u128);
|
||||
reg_op!(lib, "<", lt, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, "<=", lte, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
reg_op!(lib, ">", gt, i8, u8, i16, u16, i32, u32, u64, i128, u128);
|
||||
@@ -74,12 +46,6 @@ def_package!(crate:LogicPackage:"Logical operators.", lib, {
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
{
|
||||
// reg_op!(lib, "<", lt, f32, f64);
|
||||
// reg_op!(lib, "<=", lte, f32, f64);
|
||||
// reg_op!(lib, ">", gt, f32, f64);
|
||||
// reg_op!(lib, ">=", gte, f32, f64);
|
||||
// reg_op!(lib, "==", eq, f32, f64);
|
||||
// reg_op!(lib, "!=", ne, f32, f64);
|
||||
reg_op!(lib, "<", lt, f32);
|
||||
reg_op!(lib, "<=", lte, f32);
|
||||
reg_op!(lib, ">", gt, f32);
|
||||
@@ -88,12 +54,5 @@ def_package!(crate:LogicPackage:"Logical operators.", lib, {
|
||||
reg_op!(lib, "!=", ne, f32);
|
||||
}
|
||||
|
||||
// `&&` and `||` are treated specially as they short-circuit.
|
||||
// They are implemented as special `Expr` instances, not function calls.
|
||||
//reg_op!(lib, "||", or, bool);
|
||||
//reg_op!(lib, "&&", and, bool);
|
||||
|
||||
// lib.set_fn_2("|", or);
|
||||
// lib.set_fn_2("&", and);
|
||||
lib.set_fn_1("!", not);
|
||||
});
|
||||
|
@@ -6,10 +6,7 @@ use crate::engine::Map;
|
||||
use crate::module::FuncReturn;
|
||||
use crate::parser::{ImmutableString, INT};
|
||||
|
||||
use crate::stdlib::{
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use crate::stdlib::{string::ToString, vec::Vec};
|
||||
|
||||
fn map_get_keys(map: &mut Map) -> FuncReturn<Vec<Dynamic>> {
|
||||
Ok(map.iter().map(|(k, _)| k.to_string().into()).collect())
|
||||
|
@@ -4,7 +4,7 @@ use crate::fn_native::{CallableFunction, IteratorFn, Shared};
|
||||
use crate::module::Module;
|
||||
use crate::utils::StaticVec;
|
||||
|
||||
use crate::stdlib::{any::TypeId, boxed::Box, collections::HashMap, rc::Rc, sync::Arc, vec::Vec};
|
||||
use crate::stdlib::any::TypeId;
|
||||
|
||||
pub(crate) mod arithmetic;
|
||||
mod array_basic;
|
||||
|
@@ -1,6 +1,5 @@
|
||||
use crate::def_package;
|
||||
use crate::engine::{FUNC_TO_STRING, KEYWORD_DEBUG, KEYWORD_PRINT};
|
||||
use crate::fn_native::shared_make_mut;
|
||||
use crate::module::FuncReturn;
|
||||
use crate::parser::{ImmutableString, INT};
|
||||
|
||||
@@ -13,7 +12,7 @@ use crate::engine::Map;
|
||||
use crate::stdlib::{
|
||||
fmt::{Debug, Display},
|
||||
format,
|
||||
string::{String, ToString},
|
||||
string::ToString,
|
||||
};
|
||||
|
||||
// Register print and debug
|
||||
@@ -79,58 +78,9 @@ def_package!(crate:BasicStringPackage:"Basic string utilities, including printin
|
||||
lib.set_fn_1_mut(KEYWORD_DEBUG, format_map);
|
||||
}
|
||||
|
||||
lib.set_fn_2(
|
||||
"+",
|
||||
|s: ImmutableString, ch: char| {
|
||||
if s.is_empty() {
|
||||
return Ok(ch.to_string().into());
|
||||
}
|
||||
|
||||
let mut s = (*s).clone();
|
||||
s.push(ch);
|
||||
Ok(s)
|
||||
},
|
||||
);
|
||||
lib.set_fn_2(
|
||||
"+",
|
||||
|s:ImmutableString, s2:ImmutableString| {
|
||||
if s.is_empty() {
|
||||
return Ok(s2);
|
||||
} else if s2.is_empty() {
|
||||
return Ok(s);
|
||||
}
|
||||
|
||||
let mut s = (*s).clone();
|
||||
s.push_str(s2.as_str());
|
||||
Ok(s.into())
|
||||
},
|
||||
);
|
||||
lib.set_fn_2_mut("+=", |s: &mut ImmutableString, ch: char| {
|
||||
shared_make_mut(s).push(ch);
|
||||
Ok(())
|
||||
});
|
||||
lib.set_fn_2_mut("append", |s: &mut ImmutableString, ch: char| {
|
||||
shared_make_mut(s).push(ch);
|
||||
Ok(())
|
||||
});
|
||||
lib.set_fn_2_mut(
|
||||
"+=",
|
||||
|s: &mut ImmutableString, s2: ImmutableString| {
|
||||
if !s2.is_empty() {
|
||||
shared_make_mut(s).push_str(s2.as_str());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
);
|
||||
lib.set_fn_2_mut(
|
||||
"append",
|
||||
|s: &mut ImmutableString, s2: ImmutableString| {
|
||||
if !s2.is_empty() {
|
||||
shared_make_mut(s).push_str(s2.as_str());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
);
|
||||
lib.set_fn_2("+", |s: ImmutableString, ch: char| Ok(s + ch));
|
||||
lib.set_fn_2_mut("+=", |s: &mut ImmutableString, ch: char| { *s += ch; Ok(()) });
|
||||
lib.set_fn_2_mut("append", |s: &mut ImmutableString, ch: char| { *s += ch; Ok(()) });
|
||||
lib.set_fn_2_mut("+=", |s: &mut ImmutableString, s2: ImmutableString| { *s += &s2; Ok(()) });
|
||||
lib.set_fn_2_mut("append", |s: &mut ImmutableString, s2: ImmutableString| { *s += &s2; Ok(()) });
|
||||
});
|
||||
|
@@ -1,5 +1,4 @@
|
||||
use crate::def_package;
|
||||
use crate::fn_native::shared_make_mut;
|
||||
use crate::module::FuncReturn;
|
||||
use crate::parser::{ImmutableString, INT};
|
||||
use crate::utils::StaticVec;
|
||||
@@ -48,12 +47,12 @@ fn sub_string(s: ImmutableString, start: INT, len: INT) -> FuncReturn<ImmutableS
|
||||
}
|
||||
fn crop_string(s: &mut ImmutableString, start: INT, len: INT) -> FuncReturn<()> {
|
||||
let offset = if s.is_empty() || len <= 0 {
|
||||
shared_make_mut(s).clear();
|
||||
s.make_mut().clear();
|
||||
return Ok(());
|
||||
} else if start < 0 {
|
||||
0
|
||||
} else if (start as usize) >= s.chars().count() {
|
||||
shared_make_mut(s).clear();
|
||||
s.make_mut().clear();
|
||||
return Ok(());
|
||||
} else {
|
||||
start as usize
|
||||
@@ -67,7 +66,7 @@ fn crop_string(s: &mut ImmutableString, start: INT, len: INT) -> FuncReturn<()>
|
||||
len as usize
|
||||
};
|
||||
|
||||
let copy = shared_make_mut(s);
|
||||
let copy = s.make_mut();
|
||||
copy.clear();
|
||||
copy.extend(chars.iter().skip(offset).take(len));
|
||||
|
||||
@@ -166,17 +165,17 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
||||
},
|
||||
);
|
||||
lib.set_fn_1_mut("clear", |s: &mut ImmutableString| {
|
||||
shared_make_mut(s).clear();
|
||||
s.make_mut().clear();
|
||||
Ok(())
|
||||
});
|
||||
lib.set_fn_2_mut("append", |s: &mut ImmutableString, ch: char| {
|
||||
shared_make_mut(s).push(ch);
|
||||
s.make_mut().push(ch);
|
||||
Ok(())
|
||||
});
|
||||
lib.set_fn_2_mut(
|
||||
"append",
|
||||
|s: &mut ImmutableString, add: ImmutableString| {
|
||||
shared_make_mut(s).push_str(add.as_str());
|
||||
s.make_mut().push_str(add.as_str());
|
||||
Ok(())
|
||||
}
|
||||
);
|
||||
@@ -198,11 +197,11 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
||||
|s: &mut ImmutableString, len: INT| {
|
||||
if len > 0 {
|
||||
let chars: StaticVec<_> = s.chars().collect();
|
||||
let copy = shared_make_mut(s);
|
||||
let copy = s.make_mut();
|
||||
copy.clear();
|
||||
copy.extend(chars.into_iter().take(len as usize));
|
||||
} else {
|
||||
shared_make_mut(s).clear();
|
||||
s.make_mut().clear();
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
@@ -210,7 +209,7 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
||||
lib.set_fn_3_mut(
|
||||
"pad",
|
||||
|s: &mut ImmutableString, len: INT, ch: char| {
|
||||
let copy = shared_make_mut(s);
|
||||
let copy = s.make_mut();
|
||||
for _ in 0..copy.chars().count() - len as usize {
|
||||
copy.push(ch);
|
||||
}
|
||||
|
Reference in New Issue
Block a user